diff --git a/docs/_includes/head_custom.html b/docs/_includes/head_custom.html
index 701d0ae6..4a919ce1 100644
--- a/docs/_includes/head_custom.html
+++ b/docs/_includes/head_custom.html
@@ -40,6 +40,81 @@
return mediaQuery.matches ? "dark" : "light";
}
+ const colorSchemePattern = /just-the-docs-(default|light|dark)\.css(\?.*)?$/;
+ let pendingColorLink = null;
+
+ function findColorStylesheet() {
+ const links = document.querySelectorAll('link[rel="stylesheet"]');
+ for (let index = 0; index < links.length; index += 1) {
+ if (colorSchemePattern.test(links[index].getAttribute("href") || "")) {
+ return links[index];
+ }
+ }
+
+ return null;
+ }
+
+ function stylesheetTheme(link) {
+ const match = colorSchemePattern.exec(link.getAttribute("href") || "");
+ const scheme = match ? match[1] : "default";
+ return scheme === "default" ? "light" : scheme;
+ }
+
+ /*
+ * Swap the color stylesheet without going through jtd.setTheme, which
+ * rewrites the href of the render-blocking link and lets the page paint
+ * unstyled until the replacement CSS arrives. The site has no color_scheme,
+ * so the default stylesheet equals the light one and needs no swap at all;
+ * for dark, keep the old sheet applied until the new one has loaded.
+ */
+ function setColorStylesheet(theme) {
+ const currentLink = findColorStylesheet();
+ if (!currentLink) {
+ return;
+ }
+
+ if (pendingColorLink) {
+ if (pendingColorLink.parentNode) {
+ pendingColorLink.parentNode.removeChild(pendingColorLink);
+ }
+ pendingColorLink = null;
+ }
+
+ if (stylesheetTheme(currentLink) === theme) {
+ return;
+ }
+
+ const newLink = document.createElement("link");
+ newLink.setAttribute("rel", "stylesheet");
+ newLink.setAttribute("blocking", "render");
+ newLink.setAttribute(
+ "href",
+ currentLink.getAttribute("href").replace(colorSchemePattern, "just-the-docs-" + theme + ".css")
+ );
+
+ newLink.addEventListener("load", function() {
+ if (pendingColorLink !== newLink) {
+ return;
+ }
+ pendingColorLink = null;
+ if (currentLink.parentNode) {
+ currentLink.parentNode.removeChild(currentLink);
+ }
+ });
+
+ newLink.addEventListener("error", function() {
+ if (pendingColorLink === newLink) {
+ pendingColorLink = null;
+ }
+ if (newLink.parentNode) {
+ newLink.parentNode.removeChild(newLink);
+ }
+ });
+
+ currentLink.parentNode.insertBefore(newLink, currentLink.nextSibling);
+ pendingColorLink = newLink;
+ }
+
function nextPreference(preference) {
const index = validPreferences.indexOf(preference);
if (index === -1 || index === validPreferences.length - 1) {
@@ -62,9 +137,7 @@
const safePreference = isValidPreference(preference) ? preference : "system";
const theme = resolvedTheme(safePreference);
- if (window.jtd && typeof window.jtd.setTheme === "function") {
- window.jtd.setTheme(theme);
- }
+ setColorStylesheet(theme);
document.documentElement.setAttribute("data-theme-preference", safePreference);
document.documentElement.setAttribute("data-theme", theme);
setThemeToggleLabel(safePreference);
diff --git a/docs/_sass/custom/custom.scss b/docs/_sass/custom/custom.scss
index 5149a2a3..498de1b3 100644
--- a/docs/_sass/custom/custom.scss
+++ b/docs/_sass/custom/custom.scss
@@ -62,6 +62,16 @@
color-scheme: dark;
}
+/*
+ * Applied before the dark stylesheet finishes loading, so browsers that
+ * do not support blocking="render" avoid a light-colored first paint.
+ * Values match $grey-dk-300 and $grey-lt-300 from the dark color scheme.
+ */
+:root[data-theme="dark"] body {
+ background-color: #27262b;
+ color: #e6e1e8;
+}
+
:root[data-theme="light"] {
color-scheme: light;
}