Reputation: 15
you guys helped me with this before. Thanks to you both toggles are working now.
Now I have one more question:
Is it possible, when clicking on a toggle (no matter which one) to activate/deactivate the other one at the same time as well? so that the status is always the same?
Assuming that works: What would happen if i set "input type="checkbox" checked" for one toggle?
Example: https://jsfiddle.net/zndyf9e6/
const btns = document.querySelectorAll(".btn-toggle-darkmode");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
const currentTheme = localStorage.getItem("theme");
if (currentTheme == "dark") {
console.log(currentTheme)
document.body.classList.toggle("dark-theme");
} else if (currentTheme == "light") {
document.body.classList.toggle("light-theme");
}
btns.forEach(function(btn){
btn.addEventListener("click", function() {
if (prefersDarkScheme.matches) {
document.body.classList.toggle("light-theme");
var theme = document.body.classList.contains("light-theme") ?
"light" :
"dark";
} else {
document.body.classList.toggle("dark-theme");
var theme = document.body.classList.contains("dark-theme") ?
"light" :
"dark";
}
localStorage.setItem("theme", theme);
});
})
Thank you!
Upvotes: 0
Views: 327
Reputation: 22320
you over-complicated the code unnecessarily. But in your defense, the management of dark mode is itself a bag of knots. I have done several tests and research on the issue and my current conclusion is that code window.matchMedia ('(prefers-color-scheme: dark)'). Matches
is not really usable today.
I activated the dark mode on FireFox or Chrome, neither of the 2 browsers is detected, neither in css, nor in javascript. Except in debug mode, firefox allows you to change this flag, but this is only valid while you are using the page.
Discussions about Bugzilla are going round and round, there have been differents changed implementations over the versions of FireFox and also of Chrome, and I feel like there is some sort of confusion between using a theme (via extension) and the management of this simple flag as it is imagined in css - js.
I still left the JS code on this part, I deleted it in the CSS because it doesn't do anything. everything depends on the addition (or not) of the class on the <body>
tag.
I also cleaned your CSS, and redone your checkbox buttons which were also uselessly complicated
base code (without window.matchMedia or localStorage ):
(function() // IIFE Closure
{
const
darkClass = 'dark-theme'
, darkModeBtns = document.querySelectorAll('label.btn-dark-mode > input[type="checkbox"]')
, syncBnts = flag => darkModeBtns.forEach(bt=>bt.checked = flag)
;
let darkMode = false // default
;
document.body.classList.toggle(darkClass, darkMode ) // init page
// toggle dark mode via checkboxes
darkModeBtns.forEach( bt=>
{
bt.checked = darkMode // init page
bt.oninput =_=>
{
document.body.classList.toggle(darkClass, bt.checked )
syncBnts(bt.checked )
}
})
})()
:root {
--background : #f7f7f8;
--main : #ffffff;
--border : #e0e4e7;
--text : #244357;
--link : #0f6c9e;
--button-hover : #e8ebf0;
}
body {
background-color : var(--background);
padding-top : 15px;
padding-bottom : 15px;
color : var(--text);
font-family : sans-serif;
line-height : 1.75;
}
body.dark-theme {
--background : #18191a;
--main : #242526;
--border : #30343a;
--text : #909090;
--link : #ffffffd7;
--button-hover : #26292e;
}
label.btn-dark-mode > input { display: none; }
label.btn-dark-mode {
display : inline-block;
position : relative;
width : 40px;
height : 20px;
margin : 0 auto;
border-radius : 40px;
border : 1px solid var(--border);
overflow : hiden;
cursor : pointer;
}
label.btn-dark-mode::before,
label.btn-dark-mode::after {
position : absolute;
display : block;
border-radius : 50%;
content : ' ';
overflow : hiden;
}
label.btn-dark-mode::before {
top : 3px;
left : 2px;
width : 14px;
height : 14px;
background-color : var(--link);
transition : 0.5s ease transform, 0.2s ease background-color;
}
body.dark-theme label.btn-dark-mode::before {
transform : translateX(22px);
}
label.btn-dark-mode::after {
top : -8px;
left : 0px;
width : 15px;
height : 15px;
background-color : var(--background);
transition : transform ease 0.5s;
transform : scale(0);
}
body.dark-theme label.btn-dark-mode::after {
transform : scale(1) translate(18px,8px);
}
<label class="btn-dark-mode"><input type="checkbox"></label>
<label class="btn-dark-mode"><input type="checkbox"></label>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor,
dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas
ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie,
enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque
vitae, consequat in, pretium a, enim. Pellentesque congue.
</p>
<label class="btn-dark-mode"><input type="checkbox"></label>
full JS code (with window.matchMedia and localStorage ):
(function() // IIFE Closure
{
const
darkClass = 'dark-theme'
, darkModeBtns = document.querySelectorAll('label.btn-dark-mode > input[type="checkbox"]')
, syncBnts = flag => darkModeBtns.forEach(bt=>bt.checked = flag)
;
let darkMode = !!window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
;
darkMode = JSON.parse( localStorage.getItem(darkClass) || darkMode.toString() )
document.body.classList.toggle(darkClass, darkMode ) // init page
// toggle dark mode via checkboxes
darkModeBtns.forEach(bt=>
{
bt.checked = darkMode // init page
bt.oninput =_=>
{
document.body.classList.toggle(darkClass, bt.checked )
syncBnts(bt.checked )
localStorage.setItem(darkClass, bt.checked.toString() )
}
})
// toggle dark mode via browser preference
window
.matchMedia('(prefers-color-scheme: dark)')
.addListener(e =>
{
syncBnts( e.matches )
document.body.classList.toggle(darkClass, e.matches )
localStorage.setItem(darkClass, e.matches.toString() )
});
})()
Upvotes: 3