diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Settle the theme and header before the first paint
-rw-r--r--assets/cgit.css21
-rw-r--r--assets/cgit.js31
2 files changed, 38 insertions, 14 deletions
diff --git a/assets/cgit.css b/assets/cgit.css
index 878e96c..0f0c898 100644
--- a/assets/cgit.css
+++ b/assets/cgit.css
@@ -3,7 +3,7 @@
*
* Colours are driven by CSS custom properties via light-dark(), so the
* whole theme follows the reader's system preference and can be flipped
- * with the header toggle (which sets data-theme on div#cgit). All rules
+ * with the header toggle (which sets data-theme on <html>). All rules
* stay scoped under div#cgit so cgit can be embedded in another page.
*/
@@ -103,9 +103,11 @@ div#cgit {
background: var(--bg);
}
-/* Explicit theme choices made through the header toggle. */
-div#cgit[data-theme="light"] { color-scheme: light; }
-div#cgit[data-theme="dark"] { color-scheme: dark; }
+/* Explicit theme choices made through the header toggle. The marker is on
+ * <html> rather than div#cgit so the script can set it before the body is
+ * parsed, which is what keeps the first paint from showing the other theme. */
+html[data-theme="light"] div#cgit { color-scheme: light; }
+html[data-theme="dark"] div#cgit { color-scheme: dark; }
/* On a standalone cgit page, paint the page background to match the app
* and drop the default body margin so the interface is part of the page
@@ -257,10 +259,20 @@ div#cgit #header .theme-toggle svg {
/* Reserve the logo column. The image carries no width attribute, since the
* logo is configurable and its size is not known here, so without this the
* column collapses to nothing and the masthead jumps sideways on load. */
+/* The toggle starts hidden and is revealed once the script has run, so its
+ * column is reserved up front to keep the header from jumping. Only when
+ * scripting is on, otherwise the space would sit empty forever. */
+html.cgit-js div#cgit #header {
+ grid-template-columns: auto 1fr auto var(--control-h);
+}
+
+/* Reserve the logo's box so the header does not grow when the image
+ * arrives. The height matches the shipped 192x128 logo capped to 96px. */
div#cgit #header .logo {
grid-area: logo;
align-self: start;
min-width: 96px;
+ min-height: 64px;
}
div#cgit #header .logo img {
@@ -1406,6 +1418,7 @@ div#cgit table.ssdiff td.space div {
}
div#cgit #header .logo {
min-width: 56px;
+ min-height: 37px;
}
div#cgit #header .logo img {
max-width: 56px;
diff --git a/assets/cgit.js b/assets/cgit.js
index 6fe53ba..f3fedc1 100644
--- a/assets/cgit.js
+++ b/assets/cgit.js
@@ -160,36 +160,47 @@ function persist(value) {
try { localStorage.setItem(KEY, value); } catch (e) { }
}
-function apply(theme, root, btn) {
+function apply(theme, btn) {
+ var html = document.documentElement;
if (theme === "auto")
- root.removeAttribute("data-theme");
+ html.removeAttribute("data-theme");
else
- root.setAttribute("data-theme", theme);
+ html.setAttribute("data-theme", theme);
/* Keep the standalone page background in sync with the choice. */
- document.documentElement.style.colorScheme = (theme === "auto") ? "" : theme;
+ html.style.colorScheme = (theme === "auto") ? "" : theme;
if (btn) {
btn.innerHTML = ICONS[theme];
btn.title = "Colour theme: " + theme;
}
}
+var theme = saved();
+if (ORDER.indexOf(theme) < 0)
+ theme = "auto";
+
+/* Settled here rather than on DOMContentLoaded. This file is fetched from
+ * <head> and runs before the body is parsed, so the choice lands on <html>
+ * ahead of the first paint and the page never shows the other theme first.
+ * The marker sits on <html> for the same reason, since div#cgit does not
+ * exist yet. cgit-js reserves the toggle's column so revealing the button
+ * below does not shift the header. */
+apply(theme, null);
+document.documentElement.classList.add("cgit-js");
+
document.addEventListener("DOMContentLoaded", function () {
var root = document.getElementById("cgit");
if (!root)
return;
var btn = root.querySelector(".theme-toggle");
- var theme = saved();
- if (ORDER.indexOf(theme) < 0)
- theme = "auto";
-
- apply(theme, root, btn);
if (!btn)
return;
+
+ apply(theme, btn);
btn.hidden = false;
btn.addEventListener("click", function () {
theme = ORDER[(ORDER.indexOf(theme) + 1) % ORDER.length];
persist(theme);
- apply(theme, root, btn);
+ apply(theme, btn);
});
}, false);