mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-11-18 01:10:49 -05:00
update dark mode script and post
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
/* jshint esversion: 6, indent: 2, browser: true, quotmark: single */
|
/* jshint esversion: 6, indent: 2, browser: true, quotmark: single */
|
||||||
|
|
||||||
/*! Dark mode switcheroo | MIT License | jrvs.io/bWMz */
|
/*! Dark mode switcheroo | MIT License | jrvs.io/darkmode */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
// improve variable mangling
|
// improve variable mangling when minifying
|
||||||
var win = window;
|
var win = window;
|
||||||
var doc = win.document;
|
var doc = win.document;
|
||||||
var bod = doc.body;
|
var bod = doc.body;
|
||||||
@@ -12,67 +12,59 @@
|
|||||||
|
|
||||||
// check for preset `dark_mode_pref` preference in localStorage
|
// check for preset `dark_mode_pref` preference in localStorage
|
||||||
var pref_key = 'dark_mode_pref';
|
var pref_key = 'dark_mode_pref';
|
||||||
var pref_on = 'true';
|
|
||||||
var pref_off = 'false';
|
|
||||||
var pref = sto.getItem(pref_key);
|
var pref = sto.getItem(pref_key);
|
||||||
|
|
||||||
|
// change CSS via these <body> classes:
|
||||||
|
var dark = 'dark';
|
||||||
|
var light = 'light';
|
||||||
|
|
||||||
|
// use an element with class `dark-mode-toggle` to trigger swap when clicked
|
||||||
|
var toggle = doc.querySelector('.dark-mode-toggle');
|
||||||
|
|
||||||
// keep track of current state (light by default) no matter how we got there
|
// keep track of current state (light by default) no matter how we got there
|
||||||
var dark = false;
|
var active = false;
|
||||||
|
|
||||||
// change CSS via these body classes:
|
// receives a class name and switches <body> to it
|
||||||
var cls_light = 'light';
|
var activateTheme = function(theme) {
|
||||||
var cls_dark = 'dark';
|
cls.remove(dark, light);
|
||||||
var activateDarkMode = function() {
|
cls.add(theme);
|
||||||
cls.remove(cls_light);
|
active = (theme === dark);
|
||||||
cls.add(cls_dark);
|
|
||||||
dark = true;
|
|
||||||
};
|
|
||||||
var activateLightMode = function() {
|
|
||||||
cls.remove(cls_dark);
|
|
||||||
cls.add(cls_light);
|
|
||||||
dark = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// if user already explicitly toggled in the past, restore their preference.
|
// if user already explicitly toggled in the past, restore their preference
|
||||||
if (pref === pref_on) activateDarkMode();
|
if (pref === dark) activateTheme(dark);
|
||||||
if (pref === pref_off) activateLightMode();
|
if (pref === light) activateTheme(light);
|
||||||
|
|
||||||
// user has never clicked the button, so go by their OS preference until/if they do so
|
// user has never clicked the button, so go by their OS preference until/if they do so
|
||||||
if (!pref) {
|
if (!pref) {
|
||||||
|
// check for OS dark mode setting and switch accordingly
|
||||||
var prefers_dark = '(prefers-color-scheme: dark)';
|
var prefers_dark = '(prefers-color-scheme: dark)';
|
||||||
var prefers_light = '(prefers-color-scheme: light)';
|
var prefers_light = '(prefers-color-scheme: light)';
|
||||||
|
|
||||||
// check for OS dark mode setting and switch accordingly
|
|
||||||
// https://gist.github.com/Gioni06/eb5b28343bcf5793a70f6703004cf333#file-darkmode-js-L47
|
|
||||||
if (win.matchMedia(prefers_dark).matches)
|
if (win.matchMedia(prefers_dark).matches)
|
||||||
activateDarkMode();
|
activateTheme(dark);
|
||||||
else
|
else
|
||||||
activateLightMode();
|
activateTheme(light);
|
||||||
|
|
||||||
// real-time switching if supported by OS/browser
|
// real-time switching if supported by OS/browser
|
||||||
// TODO: stop listening when the parent condition becomes false,
|
win.matchMedia(prefers_dark).addListener(function(e) { if (e.matches) activateTheme(dark); });
|
||||||
// right now these keep listening even if pref is set.
|
win.matchMedia(prefers_light).addListener(function(e) { if (e.matches) activateTheme(light); });
|
||||||
win.matchMedia(prefers_dark).addListener(function(e) { if (e.matches) activateDarkMode(); });
|
|
||||||
win.matchMedia(prefers_light).addListener(function(e) { if (e.matches) activateLightMode(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use an element with class `dark-mode-toggle` to trigger swap
|
// don't freak out if page happens not to have a toggle
|
||||||
var toggle = doc.querySelector('.dark-mode-toggle');
|
|
||||||
|
|
||||||
// don't freak out if page happens not to have a toggle button
|
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
// lightbulb toggle re-appears now that we know user has JS enabled
|
// toggle re-appears now that we know user has JS enabled
|
||||||
toggle.style.visibility = 'visible';
|
toggle.style.visibility = 'visible';
|
||||||
|
|
||||||
// handle lightbulb click
|
// handle toggle click
|
||||||
toggle.addEventListener('click', function() {
|
toggle.addEventListener('click', function() {
|
||||||
// switch to the opposite theme & save preference in local storage
|
// switch to the opposite theme & save preference in local storage
|
||||||
if (!dark) {
|
if (!active) {
|
||||||
activateDarkMode();
|
activateTheme(dark);
|
||||||
sto.setItem(pref_key, pref_on);
|
sto.setItem(pref_key, dark);
|
||||||
} else {
|
} else {
|
||||||
activateLightMode();
|
activateTheme(light);
|
||||||
sto.setItem(pref_key, pref_off);
|
sto.setItem(pref_key, light);
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: "How To: Add Dark Mode to a Website 🌓"
|
title: "How To: Add Dark Mode to a Website 🌓"
|
||||||
date: 2020-04-29 12:14:09-0400
|
date: 2020-04-29 12:14:09-0400
|
||||||
description: "Simple dark mode switching with local storage & OS setting detection."
|
description: "Simple dark mode switching using local storage, OS preference detection, and minimal JavaScript."
|
||||||
tags:
|
tags:
|
||||||
- CSS
|
- CSS
|
||||||
- JavaScript
|
- JavaScript
|
||||||
@@ -13,8 +13,9 @@ css: |
|
|||||||
height: 200px;
|
height: 200px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 650px;
|
max-width: 650px;
|
||||||
margin: 0 auto;
|
|
||||||
display: block;
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0 auto;
|
||||||
border: 2px solid #cccccc;
|
border: 2px solid #cccccc;
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
@@ -25,14 +26,14 @@ It _is_ possible to use [pure CSS3 media queries to do this](https://css-tricks.
|
|||||||
|
|
||||||
I've written a simple implementation below, which...
|
I've written a simple implementation below, which...
|
||||||
|
|
||||||
- Defaults to a user's system preference (until they press your toggle and set it themselves)
|
- Defaults to a user's system preference, until they press your toggle to set it themselves
|
||||||
- Remembers this setting between visits using the [local storage](https://www.w3schools.com/html/html5_webstorage.asp) of the user's browser (not cookies, please don't use cookies!)
|
- Listens for clicks on any element of your choosing --- just set the class to `dark-mode-toggle`. For example:
|
||||||
- Listens for clicks on an element of your choosing --- just set the class to `dark-mode-toggle`. For example:
|
|
||||||
|
|
||||||
```html {linenos=false}
|
```html {linenos=false}
|
||||||
<button class="dark-mode-toggle">💡 Switch Themes</button>
|
<button class="dark-mode-toggle">💡 Switch Themes</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Remembers the visitor's preference between visits using the [local storage](https://www.w3schools.com/html/html5_webstorage.asp) of the their browser (not cookies, please don't use cookies!)
|
||||||
- Switches your `<body>`'s class between `light` and `dark`...
|
- Switches your `<body>`'s class between `light` and `dark`...
|
||||||
|
|
||||||
...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules --- your background, text, links, etc. --- into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality.
|
...meaning that any CSS selectors beginning with `body.dark` or `body.light` will only apply when the respective mode is active. A good place to start is by separating any color rules --- your background, text, links, etc. --- into a different section of your CSS. Using [SASS or SCSS](https://sass-lang.com/) makes this a whole lot [easier with nesting](https://sass-lang.com/guide#topic-3) but is not required; this was written with a [KISS](https://getyarn.io/yarn-clip/embed/eed08f4f-d1c9-4cc0-b041-f280a5dbf0a5?autoplay=false) mentality.
|
||||||
@@ -43,17 +44,17 @@ A _very_ barebones example is embedded above ([view the source here](https://git
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Minified JS:
|
### Minified JS (392 bytes gzipped 📦):
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/*! Dark mode switcheroo | MIT License | jrvs.io/bWMz */
|
/*! Dark mode switcheroo | MIT License | jrvs.io/darkmode */
|
||||||
(function(){var e=window,t=e.document,i=t.body.classList,a=localStorage,r="dark_mode_pref",c="true",d="false",o=a.getItem(r),s=!1,n="light",m="dark",l=function(){i.remove(n);i.add(m);s=!0},f=function(){i.remove(m);i.add(n);s=!1};o===c&&l();o===d&&f();if(!o){var h="(prefers-color-scheme: dark)",u="(prefers-color-scheme: light)";e.matchMedia(h).matches?l():f();e.matchMedia(h).addListener((function(e){e.matches&&l()}));e.matchMedia(u).addListener((function(e){e.matches&&f()}))}var v=t.querySelector(".dark-mode-toggle");if(v){v.style.visibility="visible";v.addEventListener("click",(function(){if(s){f();a.setItem(r,d)}else{l();a.setItem(r,c)}}),!0)}})();
|
(function(){var e=window,t=e.document,i=t.body.classList,a=localStorage,c="dark_mode_pref",d=a.getItem(c),r="dark",o="light",s=t.querySelector(".dark-mode-toggle"),n=!1,m=function(e){i.remove(r,o);i.add(e);n=e===r};d===r&&m(r);d===o&&m(o);if(!d){var l="(prefers-color-scheme: dark)",f="(prefers-color-scheme: light)";e.matchMedia(l).matches?m(r):m(o);e.matchMedia(l).addListener((function(e){e.matches&&m(r)}));e.matchMedia(f).addListener((function(e){e.matches&&m(o)}))}if(s){s.style.visibility="visible";s.addEventListener("click",(function(){if(n){m(o);a.setItem(c,o)}else{m(r);a.setItem(c,r)}}),!0)}})();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Full JS:
|
### Full JS:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/*! Dark mode switcheroo | MIT License | jrvs.io/bWMz */
|
/*! Dark mode switcheroo | MIT License | jrvs.io/darkmode */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
// improve variable mangling when minifying
|
// improve variable mangling when minifying
|
||||||
@@ -65,30 +66,28 @@ A _very_ barebones example is embedded above ([view the source here](https://git
|
|||||||
|
|
||||||
// check for preset `dark_mode_pref` preference in localStorage
|
// check for preset `dark_mode_pref` preference in localStorage
|
||||||
var pref_key = 'dark_mode_pref';
|
var pref_key = 'dark_mode_pref';
|
||||||
var pref_on = 'true';
|
|
||||||
var pref_off = 'false';
|
|
||||||
var pref = sto.getItem(pref_key);
|
var pref = sto.getItem(pref_key);
|
||||||
|
|
||||||
// keep track of current state (light by default) no matter how we got there
|
// change CSS via these <body> classes:
|
||||||
var dark = false;
|
var dark = 'dark';
|
||||||
|
var light = 'light';
|
||||||
|
|
||||||
// change CSS via these body classes:
|
// use an element with class `dark-mode-toggle` to trigger swap when clicked
|
||||||
var cls_light = 'light';
|
var toggle = doc.querySelector('.dark-mode-toggle');
|
||||||
var cls_dark = 'dark';
|
|
||||||
var activateDarkMode = function() {
|
// keep track of current state (light by default) no matter how we got there
|
||||||
cls.remove(cls_light);
|
var active = false;
|
||||||
cls.add(cls_dark);
|
|
||||||
dark = true;
|
// receives a class name and switches <body> to it
|
||||||
};
|
var activateTheme = function(theme) {
|
||||||
var activateLightMode = function() {
|
cls.remove(dark, light);
|
||||||
cls.remove(cls_dark);
|
cls.add(theme);
|
||||||
cls.add(cls_light);
|
active = (theme === dark);
|
||||||
dark = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// if user already explicitly toggled in the past, restore their preference
|
// if user already explicitly toggled in the past, restore their preference
|
||||||
if (pref === pref_on) activateDarkMode();
|
if (pref === dark) activateTheme(dark);
|
||||||
if (pref === pref_off) activateLightMode();
|
if (pref === light) activateTheme(light);
|
||||||
|
|
||||||
// user has never clicked the button, so go by their OS preference until/if they do so
|
// user has never clicked the button, so go by their OS preference until/if they do so
|
||||||
if (!pref) {
|
if (!pref) {
|
||||||
@@ -97,18 +96,15 @@ A _very_ barebones example is embedded above ([view the source here](https://git
|
|||||||
var prefers_light = '(prefers-color-scheme: light)';
|
var prefers_light = '(prefers-color-scheme: light)';
|
||||||
|
|
||||||
if (win.matchMedia(prefers_dark).matches)
|
if (win.matchMedia(prefers_dark).matches)
|
||||||
activateDarkMode();
|
activateTheme(dark);
|
||||||
else
|
else
|
||||||
activateLightMode();
|
activateTheme(light);
|
||||||
|
|
||||||
// real-time switching if supported by OS/browser
|
// real-time switching if supported by OS/browser
|
||||||
win.matchMedia(prefers_dark).addListener(function(e) { if (e.matches) activateDarkMode(); });
|
win.matchMedia(prefers_dark).addListener(function(e) { if (e.matches) activateTheme(dark); });
|
||||||
win.matchMedia(prefers_light).addListener(function(e) { if (e.matches) activateLightMode(); });
|
win.matchMedia(prefers_light).addListener(function(e) { if (e.matches) activateTheme(light); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// use an element with class `dark-mode-toggle` to trigger swap
|
|
||||||
var toggle = doc.querySelector('.dark-mode-toggle');
|
|
||||||
|
|
||||||
// don't freak out if page happens not to have a toggle
|
// don't freak out if page happens not to have a toggle
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
// toggle re-appears now that we know user has JS enabled
|
// toggle re-appears now that we know user has JS enabled
|
||||||
@@ -117,12 +113,12 @@ A _very_ barebones example is embedded above ([view the source here](https://git
|
|||||||
// handle toggle click
|
// handle toggle click
|
||||||
toggle.addEventListener('click', function() {
|
toggle.addEventListener('click', function() {
|
||||||
// switch to the opposite theme & save preference in local storage
|
// switch to the opposite theme & save preference in local storage
|
||||||
if (!dark) {
|
if (!active) {
|
||||||
activateDarkMode();
|
activateTheme(dark);
|
||||||
sto.setItem(pref_key, pref_on);
|
sto.setItem(pref_key, dark);
|
||||||
} else {
|
} else {
|
||||||
activateLightMode();
|
activateTheme(light);
|
||||||
sto.setItem(pref_key, pref_off);
|
sto.setItem(pref_key, light);
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
@@ -158,22 +154,22 @@ A _very_ barebones example is embedded above ([view the source here](https://git
|
|||||||
color: #222;
|
color: #222;
|
||||||
}
|
}
|
||||||
body.light a {
|
body.light a {
|
||||||
color: blue;
|
color: #06f;
|
||||||
}
|
}
|
||||||
body.dark {
|
body.dark {
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
body.dark a {
|
body.dark a {
|
||||||
color: limegreen;
|
color: #fe0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="light">
|
<body class="light">
|
||||||
<h1>Welcome to the dark side</h1>
|
<h1>Welcome to the dark side 🌓</h1>
|
||||||
<p><a href="https://github.com/jakejarvis/dark-mode-example">View the source code.</a></p>
|
<p><a href="https://github.com/jakejarvis/dark-mode-example">View the source code.</a></p>
|
||||||
|
|
||||||
<button class="dark-mode-toggle">💡 You know you want to click this</button>
|
<button class="dark-mode-toggle">💡 You know you want to click this...</button>
|
||||||
|
|
||||||
<script async defer src="dark-mode.min.js"></script>
|
<script async defer src="dark-mode.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user