fix: theme flash
This commit is contained in:
parent
cf99fba91c
commit
422ac5fb79
5 changed files with 78 additions and 38 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "coryd.dev",
|
||||
"version": "5.9.1",
|
||||
"version": "5.9.2",
|
||||
"description": "The source for my personal site. Built using 11ty and hosted on Netlify.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
|
@ -104,7 +104,9 @@
|
|||
</script>
|
||||
{% endif %}
|
||||
<script defer data-domain="coryd.dev" src="/js/script.js"></script>
|
||||
<script>window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }</script>
|
||||
<script>
|
||||
window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }
|
||||
</script>
|
||||
<noscript>
|
||||
<style>
|
||||
.client-side {
|
||||
|
@ -114,6 +116,10 @@
|
|||
</noscript>
|
||||
</head>
|
||||
<body>
|
||||
{% capture js %}
|
||||
{% render "../assets/scripts/theme.js" %}
|
||||
{% endcapture %}
|
||||
<script>{{ js }}</script>
|
||||
{{ content }}
|
||||
{% capture js %}
|
||||
{% render "../assets/scripts/index.js" %}
|
||||
|
|
|
@ -42,26 +42,16 @@ if (window.location.hostname !== 'localhost') {
|
|||
|
||||
;(async function() {
|
||||
const btn = document.querySelector('.theme__toggle');
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = localStorage?.getItem('theme');
|
||||
let theme;
|
||||
|
||||
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
document.body.classList.toggle('theme__dark');
|
||||
} else if (currentTheme === 'light') {
|
||||
document.body.classList.toggle('theme__light');
|
||||
} else if (prefersDarkScheme) {
|
||||
document.body.classList.toggle('theme__dark');
|
||||
} else if (!prefersDarkScheme) {
|
||||
document.body.classList.toggle('theme__light');
|
||||
}
|
||||
|
||||
btn.addEventListener('click', () => {
|
||||
document.body.classList.toggle('theme__light');
|
||||
document.body.classList.toggle('theme__dark');
|
||||
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = localStorage?.getItem('theme');
|
||||
let theme;
|
||||
|
||||
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
|
||||
|
||||
if (prefersDarkScheme) {
|
||||
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark';
|
||||
} else {
|
||||
|
|
24
src/assets/scripts/theme.js
Normal file
24
src/assets/scripts/theme.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
;(function() {
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = localStorage?.getItem('theme');
|
||||
let theme;
|
||||
|
||||
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
document.body.classList.add('theme__dark');
|
||||
} else if (currentTheme === 'light') {
|
||||
document.body.classList.add('theme__light');
|
||||
} else if (prefersDarkScheme) {
|
||||
document.body.classList.add('theme__dark');
|
||||
} else if (!prefersDarkScheme) {
|
||||
document.body.classList.add('theme__light');
|
||||
}
|
||||
|
||||
if (prefersDarkScheme) {
|
||||
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark';
|
||||
} else {
|
||||
theme = document.body.classList.contains('theme__dark') ? 'dark' : 'light';
|
||||
}
|
||||
localStorage?.setItem('theme', theme);
|
||||
})()
|
|
@ -36,33 +36,51 @@ The `client-side` class above hides the button should the user have JavaScript d
|
|||
</noscript>
|
||||
```
|
||||
|
||||
And JavaScript is used to control the behavior of the toggle:
|
||||
And JavaScript is used to control the behavior of the toggle — first, in the `<body>` of my base template:
|
||||
|
||||
{% raw %}
|
||||
```liquid
|
||||
{% capture js %}
|
||||
{% render "../assets/scripts/theme.js" %}
|
||||
{% endcapture %}
|
||||
<script>{{ js }}</script>
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
Where `theme.js` sets the initial state:
|
||||
|
||||
```javascript
|
||||
;(async function() {
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = localStorage?.getItem('theme');
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
document.body.classList.add('theme__dark');
|
||||
} else if (currentTheme === 'light') {
|
||||
document.body.classList.add('theme__light');
|
||||
} else if (prefersDarkScheme) {
|
||||
document.body.classList.add('theme__dark');
|
||||
} else if (!prefersDarkScheme) {
|
||||
document.body.classList.add('theme__light');
|
||||
}
|
||||
})()
|
||||
```
|
||||
|
||||
With the following JavaScript set in `assets/scripts/index.js` to add the `click` event listener for the theme toggle:
|
||||
|
||||
```javascript
|
||||
;(async function() {
|
||||
const btn = document.querySelector('.theme__toggle');
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches; // check the user's OS appearance preference
|
||||
const currentTheme = localStorage?.getItem('theme'); // check if a theme has been set
|
||||
let theme;
|
||||
|
||||
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light')) // if a theme hasn't been set, set one based on their OS preference
|
||||
|
||||
// set the body class based on the derived preferences above
|
||||
if (currentTheme === 'dark') {
|
||||
document.body.classList.toggle('theme__dark');
|
||||
} else if (currentTheme === 'light') {
|
||||
document.body.classList.toggle('theme__light');
|
||||
} else if (prefersDarkScheme) {
|
||||
document.body.classList.toggle('theme__dark');
|
||||
} else if (!prefersDarkScheme) {
|
||||
document.body.classList.toggle('theme__light');
|
||||
}
|
||||
|
||||
// allow the user to toggle the theme by clicking the theme button
|
||||
btn.addEventListener('click', () => {
|
||||
document.body.classList.toggle('theme__light');
|
||||
document.body.classList.toggle('theme__dark');
|
||||
|
||||
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const currentTheme = localStorage?.getItem('theme');
|
||||
let theme;
|
||||
|
||||
if (!currentTheme) localStorage?.setItem('theme', (prefersDarkScheme ? 'dark' : 'light'))
|
||||
|
||||
if (prefersDarkScheme) {
|
||||
theme = document.body.classList.contains('theme__light') ? 'light' : 'dark';
|
||||
} else {
|
||||
|
@ -138,4 +156,6 @@ Finally, the theme is updated based on the body class applied by the JavaScript,
|
|||
}
|
||||
```
|
||||
|
||||
With those changes in place, visitors can toggle whichever theme they'd prefer and their preference is persisted in `localStorage` should it be available.
|
||||
With those changes in place, visitors can toggle whichever theme they'd prefer and their preference is persisted in `localStorage` should it be available.
|
||||
|
||||
**EDIT:** Many thanks to [Tixie Salander](https://mastodon.guerilla.studio/@tixie) for [guiding me to a solution that improves the initial load experience](https://mastodon.guerilla.studio/@tixie/111950371813634672).
|
Reference in a new issue