Dark themes are all the rage, people love them! I love them, there is nothing more satisfying than opening an app and having the option to change from light theme to dark, or even matching my phone’s theme. It’s a great experience when it is late night and you open a site or app and its not trying to blind you with its bright white theme.
Today we are going to a talk through how to get a nice dark theme, how to automatically switch based upon someone’s preferences on their machine. 
The first thing to talk about is, a great new(ish) Media Query 

  @media (prefers-color-scheme: dark) {
      // do some stuff.
    }

The media query checks to see if the user has dark mode enabled on their device and then does some styling based upon whatever you type in there. What If you just wanted to create a switch, that you could toggle light or dark mode making it work 100% of the time and not waiting for the browsers to catch up.
We will use a button that someone can toggle and than use CSS Variables to handle all the work, it’s quite a simple concept and with a few tweaks to this code you could implement this on your site or web app in minutes. 

<nav>
      <div class="theme-switch-wrapper">
           <label class="theme-switch" for="checkbox">
        <input type="checkbox" id="checkbox" />
        <div class="slider round"></div>
      </label>
        <em>Dark Mode</em>
      </div>
    
    </nav>  
    <section>
        <article class="post">
          <h1>A Title for your post</h1>
          <p class="post-meta">2019 <span>by</span> The Poster</p>
            SOME GREAT TEXT ABOUT HOW GREAT DARK THEMES ARE
     <a href="#">Read More</a>
      </article>
    </section>

Then the CSS to go with it.

@import url(https://fonts.googleapis.com/css?family=Lato:400,400italic,700|Sansita+One);
      
     :root {
        --primary-color: #302AE6;
        --secondary-color: #536390;
        --font-color: #424242;
        --bg-color: #fff;
        --heading-color: #292922;
    }
    
    [data-theme="dark"] {
        --primary-color: #9A97F3;
        --secondary-color: #818cab;
        --font-color: #ffffff;
        --bg-color: #161625;
        --heading-color: #818cab;
    }
    body {
      font-family: "Lato", sans-serif;
      background-color: var(--bg-color);
      color: var(--font-color);
      max-width: 90%;
      margin: 0 auto;
      font-size: calc(1rem + 0.25vh);
    }
    
    h1 {
        color: var(--heading-color);
        font-family: "Sansita One", serif;
        font-size: 2rem;
        margin-bottom: 1vh;
    }
    
    p {
      font-size: 1.1rem;
      line-height: 1.6rem;
    }
    
    a {
      color: var(--primary-color);
      text-decoration: none;
      border-bottom: 3px solid transparent;
      font-weight: bold;
      &:hover, &:focus {
          border-bottom: 3px solid currentColor;
      }
    }
    
    section {
      max-width: 68%;
      margin: 0 auto;
    }
    
    .post-meta {
      font-size: 1rem;
      font-style: italic;
      display: block;
      margin-bottom: 4vh;
      color: var(--secondary-color);
    }
    
    nav {
      display: flex;
      justify-content: flex-end;
      padding: 20px 0;
    }
    
    /*slider switch css */
    .theme-switch-wrapper {
      display: flex;
      align-items: center;
      
      em {
        margin-left: 10px;
        font-size: 1rem;
      }
    }
    .theme-switch {
      display: inline-block;
      height: 34px;
      position: relative;
      width: 60px;
    }
    
    .theme-switch input {
      display:none;
    }
    
    .slider {
      background-color: #ccc;
      bottom: 0;
      cursor: pointer;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      transition: .4s;
    }
    
    .slider:before {
      background-color: #fff;
      bottom: 4px;
      content: "";
      height: 26px;
      left: 4px;
      position: absolute;
      transition: .4s;
      width: 26px;
    }
    
    input:checked + .slider {
      background-color: #66bb6a;
    }
    
    input:checked + .slider:before {
      transform: translateX(26px);
    }
    
    .slider.round {
      border-radius: 34px;
    }
    
    .slider.round:before {
      border-radius: 50%;
    }

Finally We have some javascript 

const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');
    const currentTheme = localStorage.getItem('theme');
    
    if (currentTheme) {
        document.documentElement.setAttribute('data-theme', currentTheme);
      
        if (currentTheme === 'dark') {
            toggleSwitch.checked = true;
        }
    }
    
    function switchTheme(e) {
        if (e.target.checked) {
            document.documentElement.setAttribute('data-theme', 'dark');
            localStorage.setItem('theme', 'dark');
        }
        else {        document.documentElement.setAttribute('data-theme', 'light');
              localStorage.setItem('theme', 'light');
        }    
    }
    
    toggleSwitch.addEventListener('change', switchTheme, false);

It is quite a simple process to a do a manual toggle, Which you can combine with the media rule so you support both auto detect and manually changing. Maybe a user prefers to read in a light theme but works hard in a dark theme, you can give them the option without having to force theme in to something they don’t want. 

Well that is all have on dark theme and detection, implementation. I hope you enjoyed the coverage and implement dark themes on your next project.