How to create a theme switcher with HTML & CSS

preview_player
Показать описание
A few custom properties and the :has() selector make color theming super easy to do! Add in a bit of JS and we can save the user’s preferences in localStorage, and we’re good to go!

Of course, :has() support isn’t perfect, but we can build in a quick fallback with just a little bit more JS.

🔗 Links

⌚ Timestamps
00:00 - Introduction
00:57 - What we’re starting with
01:58 - Setting up the color theme selector
04:04 - Hiding the labels
05:39 - Styling the color theme picker
12:05 - Adding functionality with :has()
13:48 - Using localStorage to remember the users choice
23:52 - Adding a fallback for when there is no :has() support

Corrections:
24:54 I should have made separate selectors here, as this won't work in Firefox - see codepen in description for a working version
27:20 Because I moved this here, the theme should have been changed to activeTheme - see codepen in description for a working version

#css

--

Come hang out with other dev's in my Discord Community

Keep up to date with everything I'm up to

Come hang out with me live every Monday on Twitch!

---

Help support my channel

---

---

I'm on some other places on the internet too!

If you'd like a behind the scenes and previews of what's coming up on my YouTube channel, make sure to follow me on Instagram and Twitter.

---

And whatever you do, don't forget to keep on making your corner of the internet just a little bit more awesome!
Рекомендации по теме
Комментарии
Автор

Don't apologize for the mistake, you fixing it is valuable content! We need more mistakes lol

codaniel
Автор

I just love how Kevin always makes sure to include accessibility features to his website for visually impaired persons. In general, it's very rare in tutorials where you see things like that.

mayukhdevansahu
Автор

I like how the mistake are fixed raw like without editing or trimming the video or even adding annotations. Thanks for that, Kevin

hollengrhen
Автор

Nice one. A tiny note though. In your JS file `document.onload = setTheme()`
this expression does not exactly do what you expect it to.
When your page loads your JS file runs and when it comes to line 25
`setTheme()` function runs (retrieves data from localStorage, checks one of the radio buttons, etc...)
and assigns `undefined` to the `document.onload`.
Hence `onload` event doesn't really run at all.
Moreover, for this type of action, you could probably use `DomContentLoaded` event.


The DOMContentLoaded event fires when the HTML document has been completely parsed, and all deferred scripts (<script defer src="…"> and <script type="module">) have downloaded and executed. It doesn't wait for other things like images, subframes, and async scripts to finish loading.

KonRud
Автор

A better event than 'click' may be 'input', as _somebody_ is going to tab and enter on those radio buttons and bypass your event handler. I ran into that earlier this year in similar code.

EvanEdwards
Автор

I used a very similar method when experimenting with themes before having ":has". The way I handled the styling flash is that I started with all color vars being black and setting a transition. So, the page starts totally black and fades to the selected color scheme.

Mr.RobotHead
Автор

IIRC, if the browser does not support a selector in a list of selectors (like .green, root:has()), it drops the entire rule. I think you can use :is() to fix that. Because that's not done in the video, the theme selector actually should not work when the browser doesn't have :has(), even with the presumable fallback.

_nikeee
Автор

Thanks! You absolutely made me love css a bit today, it's exactly what I've been trying to figure out the past few days (in the end all I needed was to know :has in css).
Here is my token of gratitude (it's not gonna be a lot because of my currency, sry about that 😅)

TheMediinaa
Автор

Dude, you're awesome and spreading the wealth. WE APPRECIATE IT.

I never comment, like once in 5 years kinda never. You deserve the praise. Thank you.

KB-kjdj
Автор

I remember making my website using languages instead of color themes for Portfolio website when learning html, css. This is an amazing process to go through and learn. Awesome that we have this on YT. I learned it googling and searching and stealing websites sooo much to understand the process.

bkmodx
Автор

11:28 Using the outline instead of the border creates here an accessibility issue, in that the focus ring is no longer visible on the element

To get around this you could change the appearance of the outline during :focus-visible

JJ-rvtt
Автор

Kevin, thank you. It's mad how easy everything is when you explain it.

ktna
Автор

Would be cool to also incorporate prefers-color-scheme since a lot of devices (phones in particular) now allow the user to specify their preference

crvlwanek
Автор

Just a JS note, the thing you assign to document.onLoad should be a function (reference). Your code has a slight problem on this line `document.onLoad = retrieveTheme()`; you’re invoking the retrieveTheme function and then setting `document.onLoad` to undefined (since that’s the return value of `retrieveTheme()`). The app works just fine since you’re invoking `retrieveTheme` regardless, but not in the way you probably intended. The correct version should just be `document.onLoad = retrieveTheme`. This way, you’re giving `onLoad` the function reference, and >IT< gets to decide when to invoke that function instead of you prematurely invoking it. Just thought to draw your attention to it. Fantastic work!! :)

RevolutionaryUsername
Автор

For getting rid of that flicker of the checked state in the beginning, you could also set the body or the theme switcher's opacity to be 0, then set it to 1 (or add the appropriate show class to it) in setTheme(), along with a short opacity transition.

i.j.
Автор

Loved this video, I basically gave up on having multiple themes years ago. These days, I just do a dark and light theme and set it based on prefers-color-scheme media queries. This video gave me a new hope.

I wish firefox gets a better ceo, I want them back working on improving servo, and implement new stuff under the hood, not the stupid colorway experiment and ui tweaks.. :has selector is amazing addition to css and my fav browser is lagging behind.

AbhinavKulshreshtha
Автор

This is incredible Kevin, thank you so much. I just watched it through in 1 go. And I will watch it again slower to exactly implement the Code and try it myself. I really love your channel and videos. Just now I shared your channel with me co-workers cause at least 3-5 of us are all working, studying and learning about CSS :)

kyrill
Автор

This is beyond cool. I always wondered if you can do theming with only css. I does make sense the JS you have to implement, for those additional features. LOVE THIS!

TheRubiosMusic
Автор

When using js you can get rid of the flickering by using a script tag in the head. Vite does it on their docs site, it´s pretty easy :)

dave-
Автор

This king completes people's skills. Respect.

tranthanhlan
visit shbcf.ru