javascripthtmlcssmeta-tags

Update `theme-color` when class/theme of page is toggled


I have a Javascript toggle that adds/removes classes on the html element to change the colour/theme of my page. 1st (no class) = white, the 2nd (.dark-mode) theme is black, the 3rd (.retro) is beige.

The Javascript toggle does have some extra theme setting stuff in it which I've tripped out just to streamline the example below:

const html = document.querySelector("html");
const button = document.querySelector(".contrast__link");

button.addEventListener("click", (e) => {
    e.preventDefault();
    if (html.classList.contains("dark-mode")) {
        html.classList.remove("dark-mode");
        html.classList.add("retro");
    } else if (html.classList.contains("retro")) {
        html.classList.remove("retro");
    } else {
        html.classList.add("dark-mode");
    }
});

When the class/theme updates. I'd like to update the theme-color in the document head to match the rest of the page. My original tag looked like this:

<meta name="theme-color" content="#ffffff">

I tried using a CSS variable thinking it would pull in the relevant colour...

CSS

:root       { --color-secondary : rgb(255,255,255); }
.dark-mode  { --color-secondary : rgb(0,0,0); }
.retro      { --color-secondary : rgb(243, 238, 226); }

Tag

<meta name="theme-color" content="var(--color-primary">

But it looks like this is not supported. Is there a way for this theme-color to be inherited or does it need to be a fixed/set value?


Solution

  • You're correct that the content attribute doesn't support CSS variables.

    To update this value based on your theme, you will have to use JavaScript.

    const html = document.querySelector("html");
    const button = document.querySelector(".contrast__link");
    
    // Let's start with defining your colors
    const colors = {
      default: '#ffffff', // color for the default theme
      darkMode: '#000000', // color for the dark-mode theme
      retro: '#f3eee2' // color for the retro theme
    }
    
    // Access the meta tag
    const metaThemeColor = document.querySelector("meta[name=theme-color]");
    
    button.addEventListener("click", (e) => {
      e.preventDefault();
      if (html.classList.contains("dark-mode")) {
        html.classList.remove("dark-mode");
        html.classList.add("retro");
        // update the theme-color meta tag
        metaThemeColor.setAttribute('content', colors.retro);
      } else if (html.classList.contains("retro")) {
        html.classList.remove("retro");
        // update the theme-color meta tag
        metaThemeColor.setAttribute('content', colors.default);
      } else {
        html.classList.add("dark-mode");
        // update the theme-color meta tag
        metaThemeColor.setAttribute('content', colors.darkMode);
      }
    });