Skip to content

Commit

Permalink
Merge pull request #86 from m417z/flashing-fix
Browse files Browse the repository at this point in the history
Add a stylesheet loader script to fix flashing (issue #77)
  • Loading branch information
tomayac authored Jan 17, 2024
2 parents fd5f3f3 + 4e05ff5 commit b1fe6cd
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 2 deletions.
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,13 @@ more than one file per theme. The example below illustrates the principle.
-->

```html
<!-- In the `<head>`
<head>
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
<script type="module" src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"></script>
-->
</head>
<!-- ... -->
<main>
<h1>Hi there</h1>
<img
Expand All @@ -102,6 +103,27 @@ more than one file per theme. The example below illustrates the principle.
</aside>
```

The above method might cause flashing
([#77](https://github.com/GoogleChromeLabs/dark-mode-toggle/issues/77)) when the
page loads, as the dark mode toggle module is loaded after the page is rendered.
A loader script can be used to apply the saved theme before the page is
rendered. Wrap the stylesheet tags with `<noscript
id="dark-mode-toggle-stylesheets">...</noscript>` and add the loader script as
following:

```html
<head>
<link rel="stylesheet" href="common.css">
<noscript id="dark-mode-toggle-stylesheets">
<link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
</noscript>
<script src="dark-mode-toggle-stylesheets-loader.min.js"></script>
<script type="module" src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"></script>
</head>
<!-- ... -->
```

### ② Using a CSS class that you toggle

If you prefer to not split your CSS in different files based on the color
Expand Down
2 changes: 2 additions & 0 deletions demo/1-mb.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ <h1>Hi there!</h1>
<a href="dist.html">built variant</a> that uses the minified version of
the script in the <code>dist</code> folder.
</p>
<p>
See <a href="with-flashing.html">the flashing issue</a> and the fix
(<a href="https://github.com/GoogleChromeLabs/dark-mode-toggle/issues/77">#77</a>).
</p>
</main>
<aside>
<dark-mode-toggle id="dark-mode-toggle-1"></dark-mode-toggle>
Expand Down
27 changes: 27 additions & 0 deletions demo/with-flashing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
</head>
<body>
<h1>Demo with flashing</h1>
<div>
Switch theme:
<dark-mode-toggle permanent></dark-mode-toggle>
</div>
<div>
Refresh to test: <a href="with-flashing.html">Refresh</a>
</div>
<div>
Go to the version <a href="without-flashing.html">without flashing</a>
</div>

<script type="module" src="../src/dark-mode-toggle.mjs"></script>
<script>
// Load uncached script to simulate a slow loading.
const rand = Math.random();
document.write('<script src="1-mb.js?r=' + rand + '"><\/script>');
</script>
</body>
</html>
30 changes: 30 additions & 0 deletions demo/without-flashing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<noscript id="dark-mode-toggle-stylesheets">
<link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)">
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)">
</noscript>
<script src="../src/dark-mode-toggle-stylesheets-loader.js"></script>
</head>
<body>
<h1>Demo without flashing</h1>
<div>
Switch theme:
<dark-mode-toggle permanent></dark-mode-toggle>
</div>
<div>
Refresh to test: <a href="without-flashing.html">Refresh</a>
</div>
<div>
Go to the version <a href="with-flashing.html">with flashing</a>
</div>

<script type="module" src="../src/dark-mode-toggle.mjs"></script>
<script>
// Load uncached script to simulate a slow loading.
const rand = Math.random();
document.write('<script src="1-mb.js?r=' + rand + '"><\/script>');
</script>
</body>
</html>
34 changes: 34 additions & 0 deletions src/dark-mode-toggle-stylesheets-loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";

(() => {
const ELEMENT_ID = "dark-mode-toggle-stylesheets";
const STORAGE_NAME = "dark-mode-toggle";
const LIGHT = "light";
const DARK = "dark";

let stylesheets = document.getElementById(ELEMENT_ID).textContent;

let mode = null;
try {
mode = localStorage.getItem(STORAGE_NAME);
} catch (e) {}

const lightCSSMediaRegex = /\(\s*prefers-color-scheme\s*:\s*light\s*\)/gi;
const darkCSSMediaRegex = /\(\s*prefers-color-scheme\s*:\s*dark\s*\)/gi;

switch (mode) {
case LIGHT:
stylesheets = stylesheets
.replace(lightCSSMediaRegex, "$&, all")
.replace(darkCSSMediaRegex, "$& and not all");
break;

case DARK:
stylesheets = stylesheets
.replace(darkCSSMediaRegex, "$&, all")
.replace(lightCSSMediaRegex, "$& and not all");
break;
}

document.write(stylesheets);
})();
1 change: 1 addition & 0 deletions src/dark-mode-toggle-stylesheets-loader.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b1fe6cd

Please sign in to comment.