Skip to content

Dark Mode

Henner S edited this page Mar 27, 2023 · 1 revision

Edje WordPress - Dark Mode

Create a "Dark Mode Toggle" widget to switch between light and dark theme.

⚠️ Requires: ACF Pro and Theme Support h-dark-mode

Dark Mode Styles

This plugin doesn't provide the CSS and JS since it's intended to be used with Edje Theme.

If you are using this in another theme, add these styles (in Sass format):

body.h-is-dark
  filter: invert(100%) hue-rotate(180deg)

  // invert back the image
  img
    filter: invert(100%) hue-rotate(180deg) brightness(1.2)

  // image that you want to stay inverted
  .wp-block-site-logo img,
  .my-icon
    filter: none

// Fix weird positioning bug with adminbar when <body> has filter
html[lang]
  margin-top: 0 !important
#wpadminbar
  position: sticky
  
  body.h-is-dark &
    filter: invert(100%) hue-rotate(180deg) 

.h-dark-toggle
  cursor: pointer
  display: flex
  align-items: center
  row-gap: 0.25rem
  column-gap: 0.25rem

  span
    text-transform: uppercase
    font-size: 12px
    font-weight: 700

  input[type="checkbox"]
    display: none


.h-dark-toggle__switch
  --width: 44px
  --height: 24px
  --padding: 4px

  display: block
  overflow: hidden
  position: relative
  background-color: black
  width: var(--width)
  height: var(--height)
  border: 1px solid white
  border-radius: 1rem

  &:focus
    box-shadow: 0 0 0 2px white

  &::before
    content: ""
    position: absolute
    z-index: 3
    display: inline-block
    background-color: white

    width: calc(var(--height) - var(--padding) - var(--padding))
    height: calc(var(--height) - var(--padding) - var(--padding))
    top: 50%
    left: var(--padding)
    border-radius: 50%
    transform: translateY(-50%)
    transition: all .25s ease-in-out
  
    input:checked + &
      transform: translateY(-50%) translateX(calc(var(--width) / 2 - var(--padding) / 2))

  // turn the circle into crescent
  &::after
    content: ""
    position: absolute
    top: 50%
    left: 0
    z-index: 2

    display: inline-block
    background-color: black
    transition: all .25s ease-in-out
    transform: translateY(-50%)

    width: 1px
    height: 1px
    border-radius: 50%

    body.h-is-dark &
      z-index: 4
      width: calc(var(--width) * 0.7)
      height: calc(var(--width) * 0.7)

Dark Mode Scripts

const myDarkMode = {
  init() {
    this.clickListener();
    this.tabindexListener();
  },

  /**
   * Click listener for dark mode toggle
   */
  clickListener() {
    const $darkToggles = document.querySelectorAll('.h-dark-toggle input[type="checkbox"]');
    if ($darkToggles.length <= 0) { return; }

    $darkToggles.forEach(($t) => {
      $t.addEventListener('change', (e) => {
        this.toggle(e.currentTarget.checked);
      });
    });
  },

  /**
   * Keyboard listener for dark mode toggle
   */
  tabindexListener() {
    const $darkSwitches = document.querySelectorAll('.h-dark-toggle__switch');

    $darkSwitches.forEach(($s) => {
      $s.addEventListener('keyup', (e) => {
        if (e.key === 'Enter' || e.keyCode === 13) {
          const $checkbox = e.currentTarget.closest('.h-dark-toggle').querySelector('input[type="checkbox"]');
          $checkbox.checked = !$checkbox.checked;
          this.toggle($checkbox.checked);
        }
      });
    });
  },

  /**
   * Toggle the body class and cache the variable
   */
  toggle(isChecked) {
    document.querySelector('body').classList.toggle('h-is-dark', isChecked);

    // the checker for this is outputed into wp_body_open() by Edje WP Library
    localStorage.setItem('hDarkMode', isChecked);
  },
};

document.addEventListener('DOMContentLoaded', () => {
  myDarkMode.init();
});

Clone this wiki locally