Now with dark mode

Published by

If your device supports a dark mode, and you’ve set this as your preference, you can now view my website in a darker color scheme. I worked on it this weekend during an IndieWeb Create Day—one day dedicated to working on our personal websites or various IndieWeb projects out in the open.

NickSimson dot com slash info
My info page in both light mode and dark mode

I launched my site with an off-white background, so the "light mode" design will be my default design. Adding dark mode support is pretty straightforward. There is a media query for dark color scheme preference:


@media (prefers-color-scheme: dark) {
    
    */ Write your dark mode styles here /*

  }

Within that rule you can write in any overrides you desire. The complexity is going to depend on how your CSS is structured. I’m using Sass on nicksimson.com, and I have several places where I am declaring colors. First, I have a _config.scss file where I have fonts, colors, and sizes declared as Sass variables. The colors are named things like $darkblue and $lightyellow.

Throughout my various .scss files I have colors applied to the body, base elements like h1, and classes like .post-tag.

To get started, I fired up Eleventy and localhost, set my OS preferences to dark mode, and created a new _darkmode.scss file. I started writing a few rules on body to see how the browser rendered my site. The easiest place for me to start was to swap the text color and background color:


@media (prefers-color-scheme: dark) {
    
    body {
        background: $darkgray;
        color: $ivory;
    }

  }

This base rule quickly shows how many places where you may need to adjust colors to fix contrast issues. My $darkblue hyperlinks for example, started to disappear into the background. I already have a page that displays every html element so I used this to quicky diagnose other elements to override. My site is not minimal in that it uses white black and blue. I have supporting text in medium gray, I apply subtle background colors to elements like pre and code, not to mention classes like .post-tag and .panel. When you highlight text on my site, it applies a high contrast highlight color scheme, so another thing I needed to override too.

Remember how I said I had several classes in several .scss files applying color rules? For organizations sake it makes more sense to include the dark mode overrides in each file, rather than putting all these random elements and classes in one file. At the same time I didn't want to have to add the media query after every rule that apllied a color in the stylesheet.

CSS variables to the rescue #

From a couple dozen colors declared in my config file, I narrowed down the big five that make up my core color scheme. I wrote these values as CSS variables on the root element, named by purpose instead of color value. These are background color, text color, light text (heading levels 5 and 6 plus supporting text like figcaption), link color and link hover color.


:root {
  --bg-color: #faf9f9;
  --text-color: #343434;
  --light-text: #676767;
  --link-color: #334492;
  --link-hover: #ee453b;
}

This involved changing some rules from Sass variables to these new CSS variables, like on the body element for example:


body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

Going back to my _darkmode.scss file, I erased my body rules and changed these root colors within the dark mode media query:

@media (prefers-color-scheme: dark) {
    :root {
        --bg-color: #343434;
        --text-color: #faf9f9;
        --light-text: #c0c0c0;
        --link-color: #a4bfeb;
        --link-hover: #f18680;
      }
  }

This covers most of my dark mode needs. Beyond these variables, I am still including dark mode overrides on other .scss files, at the end of each stylesheet. There are only a few of these, and again they are on files like _panel.scss and _tags.scss.

It only took a few hours and it was fun to share my work at the end of the day on Zoom with a few others in the IndieWeb community. Now I’m happy to share it with the world.