Say the feed page's background before the stylesheet canUnverified
Clicking through to the feed flashed white for one frame on the way in. The page names an external stylesheet, and a transform's result is parsed and painted once before that stylesheet has been applied: for that frame the canvas is the browser's default, which is white whatever the page is about to be. Coming from a dark page it reads as the page blanking, and it is the first thing a reader sees of it. Say the colour inline, in the head the transform writes, where it is in hand the moment the markup is. The stylesheet still owns the page - its rule comes later and wins the instant it arrives - and this only covers the gap before it. On body rather than on :root, which is where style.scss puts it too. A background on the root element becomes the canvas and stops the body's own from ever reaching it, which would quietly cost this page the glow every other page is painted on. Both renderings of the page say it, since both have the gap. The two colours are style.scss's --paper, light and dark, named once per file now that the theme-color metas and this rule both want them. Measured on the way in from the home page, screencast frame by frame: one pure-white frame before, none after, dark and light, in the transform and in the standby alike.
fe98fed parent: bcb209e modified
blog/layouts/_default/home.feedscript.js +17 -2 | @@ -24,7 +24,11 @@ | ||
| 24 | 24 | {{- $integrity = .Data.Integrity }} |
| 25 | 25 | {{- end }} |
| 26 | 26 | {{- end }} |
| 27 | +{{- /* style.scss's --paper, light and dark - the theme-color metas and the | |
| 28 | + inline background rule below both want them. */}} | |
| 27 | 29 | {{- $cfg := dict |
| 30 | + "paper" "#f5f2ec" | |
| 31 | + "paperDark" "#15171a" | |
| 28 | 32 | "lang" site.Language.Lang |
| 29 | 33 | "site" site.Title |
| 30 | 34 | "home" ("/" | relLangURL) |
| @@ -82,9 +86,20 @@ | ||
| 82 | 86 | meta({charset: "utf-8"}); |
| 83 | 87 | meta({name: "viewport", content: "width=device-width, initial-scale=1"}); |
| 84 | 88 | meta({name: "color-scheme", content: "light dark"}); |
| 85 | - meta({name: "theme-color", content: "#f5f2ec", media: "(prefers-color-scheme: light)"}); | |
| 86 | - meta({name: "theme-color", content: "#15171a", media: "(prefers-color-scheme: dark)"}); | |
| 89 | + meta({name: "theme-color", content: C.paper, media: "(prefers-color-scheme: light)"}); | |
| 90 | + meta({name: "theme-color", content: C.paperDark, media: "(prefers-color-scheme: dark)"}); | |
| 87 | 91 | meta({name: "robots", content: "noindex"}); |
| 92 | + // The background, inline, ahead of the stylesheet link below: this page | |
| 93 | + // can be painted once before an external stylesheet has been applied, and | |
| 94 | + // that first paint uses the browser's default canvas - white, whatever | |
| 95 | + // the page is about to be. Coming from a dark page that is a white flash. | |
| 96 | + // On body, as style.scss has it: a background on the root element is the | |
| 97 | + // canvas, and would keep the body's own from ever reaching it again. | |
| 98 | + const canvas = out.createElement("style"); | |
| 99 | + canvas.textContent = | |
| 100 | + `body{background:${C.paper}}` + | |
| 101 | + `@media (prefers-color-scheme: dark){body{background:${C.paperDark}}}`; | |
| 102 | + head.appendChild(canvas); | |
| 88 | 103 | head.appendChild(make("title", null, `${text(src, "channel > title") || C.site} · ${C.pageTitle}`)); |
| 89 | 104 | if (C.css) { |
| 90 | 105 | const link = out.createElement("link"); |
| @@ -24,7 +24,11 @@ | |||
| 24 | {{- $integrity = .Data.Integrity }} | 24 | {{- $integrity = .Data.Integrity }} |
| 25 | {{- end }} | 25 | {{- end }} |
| 26 | {{- end }} | 26 | {{- end }} |
| 27 | +{{- /* style.scss's --paper, light and dark - the theme-color metas and the | ||
| 28 | + inline background rule below both want them. */}} | ||
| 27 | {{- $cfg := dict | 29 | {{- $cfg := dict |
| 30 | + "paper" "#f5f2ec" | ||
| 31 | + "paperDark" "#15171a" | ||
| 28 | "lang" site.Language.Lang | 32 | "lang" site.Language.Lang |
| 29 | "site" site.Title | 33 | "site" site.Title |
| 30 | "home" ("/" | relLangURL) | 34 | "home" ("/" | relLangURL) |
| @@ -82,9 +86,20 @@ | |||
| 82 | meta({charset: "utf-8"}); | 86 | meta({charset: "utf-8"}); |
| 83 | meta({name: "viewport", content: "width=device-width, initial-scale=1"}); | 87 | meta({name: "viewport", content: "width=device-width, initial-scale=1"}); |
| 84 | meta({name: "color-scheme", content: "light dark"}); | 88 | meta({name: "color-scheme", content: "light dark"}); |
| 85 | - meta({name: "theme-color", content: "#f5f2ec", media: "(prefers-color-scheme: light)"}); | 89 | + meta({name: "theme-color", content: C.paper, media: "(prefers-color-scheme: light)"}); |
| 86 | - meta({name: "theme-color", content: "#15171a", media: "(prefers-color-scheme: dark)"}); | 90 | + meta({name: "theme-color", content: C.paperDark, media: "(prefers-color-scheme: dark)"}); |
| 87 | meta({name: "robots", content: "noindex"}); | 91 | meta({name: "robots", content: "noindex"}); |
| 92 | + // The background, inline, ahead of the stylesheet link below: this page | ||
| 93 | + // can be painted once before an external stylesheet has been applied, and | ||
| 94 | + // that first paint uses the browser's default canvas - white, whatever | ||
| 95 | + // the page is about to be. Coming from a dark page that is a white flash. | ||
| 96 | + // On body, as style.scss has it: a background on the root element is the | ||
| 97 | + // canvas, and would keep the body's own from ever reaching it again. | ||
| 98 | + const canvas = out.createElement("style"); | ||
| 99 | + canvas.textContent = | ||
| 100 | + `body{background:${C.paper}}` + | ||
| 101 | + `@media (prefers-color-scheme: dark){body{background:${C.paperDark}}}`; | ||
| 102 | + head.appendChild(canvas); | ||
| 88 | head.appendChild(make("title", null, `${text(src, "channel > title") || C.site} · ${C.pageTitle}`)); | 103 | head.appendChild(make("title", null, `${text(src, "channel > title") || C.site} · ${C.pageTitle}`)); |
| 89 | if (C.css) { | 104 | if (C.css) { |
| 90 | const link = out.createElement("link"); | 105 | const link = out.createElement("link"); |
modified
blog/layouts/_default/home.feedstyle.xsl +21 -2 | @@ -17,6 +17,12 @@ | ||
| 17 | 17 | escaping of its own: anything interpolated into the XML is escaped here, by |
| 18 | 18 | hand, with transform.XMLEscape. |
| 19 | 19 | */ -}} |
| 20 | +{{- /* The page's two canvas colours - style.scss's --paper, light and dark. | |
| 21 | + Named here because three things in the head below need them: the theme-color | |
| 22 | + metas, and the inline rule that paints the page before the stylesheet has | |
| 23 | + loaded. */}} | |
| 24 | +{{- $paper := "#f5f2ec" }} | |
| 25 | +{{- $paperDark := "#15171a" }} | |
| 20 | 26 | {{- $feed := "" }} |
| 21 | 27 | {{- with .OutputFormats.Get "RSS" }}{{ $feed = .Permalink }}{{ end }} |
| 22 | 28 | {{- $signal := partial "signal.html" $feed }} |
| @@ -54,8 +60,21 @@ | ||
| 54 | 60 | <meta charset="utf-8"/> |
| 55 | 61 | <meta name="viewport" content="width=device-width, initial-scale=1"/> |
| 56 | 62 | <meta name="color-scheme" content="light dark"/> |
| 57 | - <meta name="theme-color" content="#f5f2ec" media="(prefers-color-scheme: light)"/> | |
| 58 | - <meta name="theme-color" content="#15171a" media="(prefers-color-scheme: dark)"/> | |
| 63 | + <meta name="theme-color" content="{{ transform.XMLEscape $paper }}" media="(prefers-color-scheme: light)"/> | |
| 64 | + <meta name="theme-color" content="{{ transform.XMLEscape $paperDark }}" media="(prefers-color-scheme: dark)"/> | |
| 65 | + {{- /* The background, inline, ahead of the stylesheet link below. | |
| 66 | + A transform's result is painted once before an external stylesheet | |
| 67 | + it names has been applied, and that first paint uses the browser's | |
| 68 | + default canvas - white, whatever the page is about to be. Coming | |
| 69 | + from a dark page that is a white flash, so say the colour here, | |
| 70 | + where it is in hand the moment the markup is. | |
| 71 | + | |
| 72 | + On body and not on :root, which is where style.scss puts it too: a | |
| 73 | + background on the root element is the canvas, and would stop the | |
| 74 | + body's own - the paper colour and the glow above it - from ever | |
| 75 | + reaching the canvas again. The stylesheet's rule comes after this | |
| 76 | + one and wins the moment it arrives. */}} | |
| 77 | + <style>body{background:{{ transform.XMLEscape $paper }}}@media (prefers-color-scheme: dark){body{background:{{ transform.XMLEscape $paperDark }}}}</style> | |
| 59 | 78 | {{- /* Not a page anyone should reach from a search result; the feed |
| 60 | 79 | URL itself is the thing worth indexing, and only as a feed. */}} |
| 61 | 80 | <meta name="robots" content="noindex"/> |
| @@ -17,6 +17,12 @@ | |||
| 17 | escaping of its own: anything interpolated into the XML is escaped here, by | 17 | escaping of its own: anything interpolated into the XML is escaped here, by |
| 18 | hand, with transform.XMLEscape. | 18 | hand, with transform.XMLEscape. |
| 19 | */ -}} | 19 | */ -}} |
| 20 | +{{- /* The page's two canvas colours - style.scss's --paper, light and dark. | ||
| 21 | + Named here because three things in the head below need them: the theme-color | ||
| 22 | + metas, and the inline rule that paints the page before the stylesheet has | ||
| 23 | + loaded. */}} | ||
| 24 | +{{- $paper := "#f5f2ec" }} | ||
| 25 | +{{- $paperDark := "#15171a" }} | ||
| 20 | {{- $feed := "" }} | 26 | {{- $feed := "" }} |
| 21 | {{- with .OutputFormats.Get "RSS" }}{{ $feed = .Permalink }}{{ end }} | 27 | {{- with .OutputFormats.Get "RSS" }}{{ $feed = .Permalink }}{{ end }} |
| 22 | {{- $signal := partial "signal.html" $feed }} | 28 | {{- $signal := partial "signal.html" $feed }} |
| @@ -54,8 +60,21 @@ | |||
| 54 | <meta charset="utf-8"/> | 60 | <meta charset="utf-8"/> |
| 55 | <meta name="viewport" content="width=device-width, initial-scale=1"/> | 61 | <meta name="viewport" content="width=device-width, initial-scale=1"/> |
| 56 | <meta name="color-scheme" content="light dark"/> | 62 | <meta name="color-scheme" content="light dark"/> |
| 57 | - <meta name="theme-color" content="#f5f2ec" media="(prefers-color-scheme: light)"/> | 63 | + <meta name="theme-color" content="{{ transform.XMLEscape $paper }}" media="(prefers-color-scheme: light)"/> |
| 58 | - <meta name="theme-color" content="#15171a" media="(prefers-color-scheme: dark)"/> | 64 | + <meta name="theme-color" content="{{ transform.XMLEscape $paperDark }}" media="(prefers-color-scheme: dark)"/> |
| 65 | + {{- /* The background, inline, ahead of the stylesheet link below. | ||
| 66 | + A transform's result is painted once before an external stylesheet | ||
| 67 | + it names has been applied, and that first paint uses the browser's | ||
| 68 | + default canvas - white, whatever the page is about to be. Coming | ||
| 69 | + from a dark page that is a white flash, so say the colour here, | ||
| 70 | + where it is in hand the moment the markup is. | ||
| 71 | + | ||
| 72 | + On body and not on :root, which is where style.scss puts it too: a | ||
| 73 | + background on the root element is the canvas, and would stop the | ||
| 74 | + body's own - the paper colour and the glow above it - from ever | ||
| 75 | + reaching the canvas again. The stylesheet's rule comes after this | ||
| 76 | + one and wins the moment it arrives. */}} | ||
| 77 | + <style>body{background:{{ transform.XMLEscape $paper }}}@media (prefers-color-scheme: dark){body{background:{{ transform.XMLEscape $paperDark }}}}</style> | ||
| 59 | {{- /* Not a page anyone should reach from a search result; the feed | 78 | {{- /* Not a page anyone should reach from a search result; the feed |
| 60 | URL itself is the thing worth indexing, and only as a feed. */}} | 79 | URL itself is the thing worth indexing, and only as a feed. */}} |
| 61 | <meta name="robots" content="noindex"/> | 80 | <meta name="robots" content="noindex"/> |