Dark Mode for Ease: Has Anyone Done it?

This is more of a general question as I am starting to look at Ease. Has anyone implemented dark mode with Ease and if so, how? Would appreciate some insight.

AFAIK, dark mode is just a set of CSS variables that switch when a button is pressed.

Yes, it is.

So you would just add a button/toggle somewhere and change the root CSS variables with Javascript when it’s toggle, no?

Yes. But it needs to remember that setting (cookie) and I don’t know what files to copy and edit.
I am not asking the “how to” behind it, I’m asking if anyone else have made it and if so, what files etc that I need to fix.

Guess I should have been clearer.

This post appears to address the cookie as it relates to dark mode toggle:

Yep, reading it now and working my way “around” it for Ease. Thanks for posting.

Got the code in (hardcoded). Now it’s just a matter of styling the dark theme since there’s nothing to toggle in Ease. Or maybe there is and I don’t know the correct class.

Here’s how I’d do this:

  1. I probably wouldn’t hardcode it in case there’s an update to the theme.
  2. I’d inject the button via Javascript.
  3. I’d use the button to toggle the CSS custom props. You can redefine the properties (e.g., --white-color: #000) and set them with a custom data attribute to override the defaults.
  4. I’d save the user preference in local storage. I think it’s easier to work with than cookies.
    Included a screenshot of the theme with variables changed.

In case it might help someone as a copy-and-paste starting point using local storage… here is the most simple way I found to do this which is also not hard-coded so won’t break on theme updates…

In the Site Header Code Injection:

<style>

.dark-mode-toggle {
    position: absolute;
    top: 15px;
    left: 15px;
    font-size: 32px;
}

a.dark-mode-toggle,
    .dark-mode-toggle a:active,
    .dark-mode-toggle a:hover,
    .dark-mode-toggle a:focus {
        outline: none;
        text-decoration: none;
}
    
body {
    color: #222;
    background: #f4f0eb;
}
    
body.dark-mode {
    color: #eee;
    background: #000;
}

#site-head {
    opacity: 1;
}

.dark-mode #site-head {
    opacity: 60%;
}

p, .post-excerpt p {
    background-color: #565656;
    color: #000;
}   

.dark-mode p, .dark-mode .post-excerpt p {
    background-color: #ffffffd9;
    color: #ffffff36;
}

.site-footer {
    color: #46a1c7;
    background:#e3e3e3 ;
}

.dark-mode .site-footer {
    color: #BBC7CC;
    background: #1c212b;
}    
    
</style>

And in the Site Footer Code Injection:

<script>
$('.navbar-header').prepend('<a href="#" onclick="themeToggle()" class="dark-mode-toggle">🌗</a>');
(function() {
    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && localStorage.getItem('theme') == null) {
        document.body.classList.add('dark-mode');
        localStorage.setItem("theme", "dark-mode");
    }
    let cookie = localStorage.getItem("theme") || "";
    if(cookie){
    	document.body.classList.add(cookie);
    }
  })();
  
function themeToggle() {
    document.body.classList.toggle("dark-mode");

  let theme = localStorage.getItem("theme");
  if (theme && theme === "dark-mode") {
    localStorage.setItem("theme", "");
  } else {
    localStorage.setItem("theme", "dark-mode");
  }
}
</script>

Here is how this appears on my site

Dark Mode

Light Mode

That’s awesome – thank you! I’ll continue to customize it. Any idea on how to change the icon to represent dark / light mode?

You can have hours of fun hunting for gems on Codpen.io

Here’s a bling-y one: https://codepen.io/pieter-biesemans/pen/LYRdaKw

Awesome :slight_smile: Thank you. Think I’ll stick with that one!

Here’s a good and thorough article discussing important additional considerations when using dark mode – on one of my favorite learning sites:

1 Like

@thebear.dev try the below… I have this working in Casper…

In the Site Header Injection:

<style>

.switch {  
  position: relative;
  overflow: hidden;
  width: 8rem;
  height: 4.5rem;
  transform: scale(0.7);
  display: inline-block;
  padding: .25rem;
  border-radius: 20px;
}

.switch input {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  opacity: 0;
}

.switch label {
  cursor: pointer;
}

.background {
  box-sizing: border-box;
  z-index: 1;
  position: absolute;
  width: 7.5rem;
  height: 4rem;
  border-radius: 2.5rem;
  border: 0.25rem solid #202020;
  background: linear-gradient(to right, #484848 0%,#202020 100%);
  transition: all 0.3s;
}

.fill {
  
  position: fixed;
  top: 0;
  right: 0;
  bottom: 2rem;
  left: 0;
  background: #484848;
  transition: 0.75s all ease;
}

.switch input:checked ~ .fill {
  background: #E9F8FD;
}

.stars1,
.stars2 {
  
  position: absolute;
  height: 0.4rem;
  width: 0.4rem; 
  background: #FFFFFF;
  border-radius: 50%;
  transition: 0.3s all ease;
}

.stars1 {
  top: 6px;
  right: 23px;
}

.stars2 {
  top: 40px;
  right: 48px;
}

.stars1:after,
.stars1:before,
.stars2:after,
.stars2:before{
  
  position: absolute;
  content: "";
  display: block;
  height: 0.25rem;
  width: 0.25rem;
  background: #FFFFFF;
  border-radius: 50%;
  transition: 0.2s all ease;
}

.stars1:after {
  top: 8px;
  right: 20px;
}

.stars1:before {
  top: 18px;
  right: -12px;
}

.stars2:after {
  top: -8px;
  right: -16px;
}

.stars2:before {
  top: 6px;
  right: -26px;
}

.sun-moon {
  box-sizing: border-box;
  z-index: 2;
  position: absolute;
  left: 0;
  display: inline-block;
  height: 3rem;
  width: 3rem;
  margin: 0.5rem;
  background: #FFFDF2;
  border-radius: 50%;
  transition: all 0.5s ease;
  
  /* Default to Moon */
  border: 0.25rem solid #DEE2C6;
}

.sun-moon .dots {
  box-sizing: border-box;
  position: absolute;
  top: 3px;
  left: 23px;
  height: 1rem;
  width: 1rem; 
  background: #EFEEDB;
  border: 0.25rem solid #DEE2C6;
  border-radius: 50%;
  transition: 0.4s all ease;
}

.sun-moon .dots:after,
.sun-moon .dots:before {
  position: absolute;
  content: "";
  display: block;
  height: 0.25rem;
  width: 0.25rem;
  background: #EFEEDB;
  border: 0.25rem solid #DEE2C6;
  border-radius: 50%;
  transition: 0.4s all ease;
}

.sun-moon .dots:after {
  top: -4px;
  left: -26px;
}

.sun-moon .dots:before {
  top: 18px;
  left: -10px;
}

/* Transition to Sun */

.switch input:checked ~ .sun-moon {
  left: calc(100% - 4rem);
  background: #F5EC59;
  border-color: #E7C65C;
  transform: rotate(-25deg);
}

.switch input:checked ~ .sun-moon .dots,
.switch input:checked ~ .sun-moon .dots:after,
.switch input:checked ~ .sun-moon .dots:before {
  background: #FFFFFF;
  border-color: #FFFFFF;
}

.switch input:checked ~ .sun-moon .dots {
  height: 1.5rem;
  width: 1.5rem;
  top: 0px;
  left: -20px;
  transform: rotate(25deg);
}

.switch input:checked ~ .sun-moon .dots:after {
  height: 0.65rem;
  width: 0.65rem;
  top: 2px;
  left: -12px;
}

.switch input:checked ~ .sun-moon .dots:before {
  height: 0.4rem;
  width: 0.4rem;
  top: 6px;
  left: 14px;
}

.switch input:checked ~ .background .stars1,
.switch input:checked ~ .background .stars2 {
  opacity: 0;
  transform: translateY(2rem);
}

.switch input:checked ~ .background {
  border: 0.25rem solid #78C1D5;
  background: linear-gradient(to right, #78C1D5 0%, #BBE7F5 100%);
}

/* Don't forget to add a second CSS snippet for each existing class you want to change with the switcher, adding .dark-mode in front of it like I did here to darken the background of the .post-card */

.dark-mode .post-card {
    background: #404040;
}

</style>

In the Site Footer Injection…

<script>
/* Dark Mode Sets Cookie */

// On page load set the theme.
$(document).ready(function(){
    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && localStorage.getItem('theme') == null) {
        document.documentElement.classList.add('dark-mode');
        localStorage.setItem("theme", "dark-mode");
    }
    let cookie = localStorage.getItem("theme") || "";
    if(cookie) {
        document.documentElement.classList.add(cookie);
    }

    if($('html').hasClass('dark-mode')) {
        $('.switch input').prop( "checked", false );
    } else {
        $('.switch input').prop( "checked", true );
    }
});

$('.switch').click(function(e){
    e.preventDefault();
    $('html').toggleClass("dark-mode");
    console.log($('.switch'))
    let theme = localStorage.getItem("theme");
    if (theme && theme === "dark-mode") {
      localStorage.setItem("theme", "");
    } else {
      localStorage.setItem("theme", "dark-mode");
    }

    if($('html').hasClass('dark-mode')) {
        $('.switch input').prop( "checked", false );
    } else {
        $('.switch input').prop( "checked", true );
    }
});
</script>

In default.hbs (and/or wherever else you want the bling-y button)…

<div class="switch">
<label for="toggle">
<input id="toggle" class="toggle-switch" type="checkbox">
<div class="sun-moon"><div class="dots"></div></div>
<div class="background"><div class="stars1"></div><div class="stars2"></div></div>
</label>
</div>

For example, here in default.hbs just before the Subscribe button…

Looks like this… (you can see it live at https://Ghizmos.com – at least for the moment)

Light Mode…

Dark Mode…

1 Like

Very nice. Thank you so much for taking the time to review and work on this, seriously; thank you! I will test it out and write a post about it (obviously giving you credit).

1 Like

You are welcome, @thebear.dev. I enjoyed doing it. I had in mind to do it anyway, and your post here gave me just the nudge I needed. I’m enjoying your participation here in the forum – you are an interesting character!

Wow… :slight_smile: Don’t know about interesting, but I enjoy learning and I learn fast.