惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
WordPress大学
WordPress大学
小众软件
小众软件
Cloudbric
Cloudbric
AWS News Blog
AWS News Blog
腾讯CDC
量子位
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
Scott Helme
Scott Helme
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
Jina AI
Jina AI
Attack and Defense Labs
Attack and Defense Labs
S
SegmentFault 最新的问题
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
Google Online Security Blog
Google Online Security Blog
美团技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
罗磊的独立博客
L
LINUX DO - 最新话题
博客园 - Franky
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
AI
AI
C
Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
I
Intezer
S
Securelist

endtimes.dev

Happy new year | endtimes.dev why lowercase letters save data Practical betterments | endtimes.dev Short posts and some site updates Input Output | endtimes.dev Actually, dark mode can save the planet Why your website should be under 14kB in size HTML and CSS only multiple color scheme picker Why your website should work without Javascript. you can use css to remove the double-tap zoom feature on iOs Missing Dice | endtimes.dev Can Dark Mode Save Battery Life and Human Civilzation? Your DNS has a significant impact on site speed. Add spaces to the dock on MacOS You can leave out <html>, <head>, and <body> tags. Listen for changes between dark and light mode with javascript Use a keyboard shortcut to quickly toggle light and dark mode on MacOs. Why Your Website Should Use Dithered Images You can restore the startup chimes on MacOS Emoji Clipboard | endtimes.dev You can use Emojis as Favicons .dev and HSTS preload | endtimes.dev Prod — Block Distractions. Achieve your goals. Pattern generator | endtimes.dev Green Quarantine | endtimes.dev Qwitter Bot | endtimes.dev
An HTML and CSS only dark-mode toggle button.
2021-03-14 · via endtimes.dev

A quick guide to building an html and css only dark-mode toggle.

Using just css and html we'll build a button that:

  • changes between light-mode and dark-mode
  • defaults to the user's preferred color scheme
  • changes the label to reflect the user's preferred color scheme.

Here's a CodePen with the final product (plus some styling)

Why no javascript? #

I've been building a website with tools for board game players. Simple things like dice and random playing cards.

One of my goals is for every tool to work without javascript. The site also has a dark-mode and light-mode. (and some other color schemes too).

I needed a way to toggle dark-mode without javascript — while still defaulting to the visitor preferred-color-scheme.

Here's my solution, simplified for this tutorial:

How it works: #

Most dark-mode toggle buttons work by changing an attribute on the <body> tag, and then targeting that attribute in the css. Like so:

<body class="dark-mode">
<!-- Site Content -->
</body>

<style>

body {
background:white
}

body.dark-mode {
background:black
}

</style>

<script>
function toggleDarkMode() {
// some logic to change the class on the body tag
}
</script>

This is very simple, but requires javascript to add and remove the dark-mode class.

Luckily we can still make changes to our styles without javascript. We can use CSS to target non-javascript user interactions.

Here we're going to use a checkbox, and the :checked pseudo-selector:

<body>
<input id="color-mode" type="checkbox" name="color-mode">
<label for="color-mode">Dark Mode</label>

<!-- Site Content -->
</body>

We need to make sure the input is the first thing in our <body> so we can target everything after it in our CSS.


body {
background:white
}

#dark-mode:checked ~ * {
background:black
}

But there's a problem with this!

There's no way in CSS to target the parent of an element. So we can't change the color of the <body>.

So we'll use a work around. We'll place a <div> after our checkbox that does the job of the <body>. Then we style the <div> to fill the screen.

Now we can use the checkbox input to style our <div>:

<body>
<input id="color-mode" type="checkbox" name="color-mode">
<label for="color-mode">Dark Mode</label>

<div class="color-scheme-wrapper">
<!-- Site Content -->
</div>
</body>

<style>

.color-scheme-wrapper {
min-height:100vh;
background:white;
color:black;
}

#color-mode:checked ~ .color-scheme-wrapper {
background:black;
color:white;
}

</style>

This works! But there's still a few things we need to fix:

  • We need to make it default to the user's preferred color scheme.
  • We should use css variables because it will make life easier.
  • We need to change the label to reflect the user's preferences.

First let's add the css variables. #

CSS variables allow us to define colors that change based on the checkbox. We'll use just two colors one for the background and one for text:

:root {
--bg:#F4F0EB;
--text:#141414;
}

#dark-mode:checked ~ .color-scheme-wrapper {
--bg:#333;
--text:#fff;
}

.color-scheme-wrapper {
background:var(--bg);
color:var(--text);
}

Now, when we check the checkbox the variables change, and those changes are reflected in the rest of or css.

Defaulting to our visitors' preferred color scheme. #

Now let's make it so it defaults to user's preferences. To target user preferences we can use a @media query.

Based on the result of the prefers-color-scheme media query we'll swap our light-mode and dark-mode themes.

So if a user's device has dark-mode enabled it starts off dark:

:root {
--bg:white;
--text:black;
}

@media (prefers-color-scheme: dark) {
:root {
--bg:black;
--text:white;
}
}

#color-mode:checked ~ .color-scheme-wrapper {
--bg:black;
--text:white;
}

@media (prefers-color-scheme: dark) {
#color-mode:checked ~ .color-scheme-wrapper {
--bg:white;
--text:black;
}
}

.color-scheme-wrapper {
min-height:100vh;
background:var(--bg);
color:var(--text);
}

Changing the label based on user preferences. #

Now that we've swapped dark-mode and light-mode we need to make sure the label for our checkbox reflects this.

It would be confusing if the label said dark-mode was on when the screen was bright white.

There's a quick fix for this too. First we add two sets of text in our <label> one for each user preference:

<input id="color-mode" type="checkbox" name="color-mode">
<label for="color-mode">
<span class="dark-mode-hide">Dark Mode</span>
<span class="light-mode-hide">Light Mode</span>
</label>

Then we hide one of the labels depending on the mode.

This set of media queries allows us to target both light-mode, dark -mode, and browsers that don't support prefers-color-scheme:


.light-mode-hide {
display:none;
}

@media (prefers-color-scheme: dark) {
.dark-mode-hide {
display:none;
}
}

@media (prefers-color-scheme: dark) {
.light-mode-hide {
display:initial;
}
}

That's it. Let me know what you think!

If you can think of a clever way of having the color scheme remain the same after you've navigated to a different page. Let me know.

Also - There's a good argument for using input[type=radio] instead of input[type=checkbox]. But the concept is easier illustrated with a checkbox.

Links:

Here's a link to the codePen example with some extra styling: codepen.io

Here's a link to the five color version on: missingdice.com

published
14 Mar 2021
modified
14 Mar 2021
author
Nathaniel
tags
posts post html css a11y tutorial dark mode