skip to Main Content

Since I don’t know a way to style a web component with parent lightDOM class selector to choose which is the theme selector (light or dark) i’ve found a way to choose it via custom property:

The HTML page

<html style="--global-pref-theme:dark;">
  <my-component></my-component>
</html>
:root {
  --tone-neutral-01: #000000;
  /* etc... */
}

:root.dark-mode {
  --tone-neutral-01: #FFFFFF;
  /* etc... */
}

My web component

<host>
 <div class="tabs">
   ... 
 </div>
</host>

Web component CSS

.tabs {
  background-color: var(--tone-neutral-01);
  border: 1px solid transparent;
}

@container style(--global-pref-theme: dark) {
  .tabs {
    border-color: var(--tone-neutral-02);
  }
}

I need this approach to solve UI visual exceptions, when dark mode differs from light mode.

This approach would be great but it ignores the operating system settings when the user chooses and forces me to add media query rule and potentially duplicate a lot of CSS code:

Web component CSS


.tabs {
  background-color: var(--tone-neutral-01);
  border: 1px solid transparent;
}

@container style(--global-pref-theme: dark) {
  /* user select only */
  .tabs {
    border-color: var(--tone-neutral-02);
  }
}

@container style(--global-pref-theme: system) {
  @media (prefers-color-scheme: dark) {
    /* OS only */
    .tabs {
      border-color: var(--tone-neutral-02);
    }
  }
}

I can’t use a list of query selectors but it would be nice:


.tabs {
  background-color: var(--tone-neutral-01);
  border: 1px solid transparent;
}

@container style(--global-pref-theme: dark),
@container style(--global-pref-theme: system) {
  @media (prefers-color-scheme: dark) {
    /* OS only */
    .tabs {
      border-color: var(--tone-neutral-02);
    }
  }
}

Is there some way to do it and avoid duplicate CSS code?

I’m open to tailwind, postcss or rollup solutions if necessary (I’m using stencil).

I would avoid a javascript way cause i have 75 web components to be styled and this would be awful for me.

I allready use custom properties for colors

2

Answers


  1. To style light and dark modes in Stencil components without duplicating CSS:

    Define global styles with CSS variables for light and dark modes.

    Use these variables in your component stylesheets.

    Global Stylesheet

    /* Light mode by default */
    :root {
      --background-color: #ffffff;
      --text-color: #000000;
    }
    
    /* Dark mode styles */
    @media (prefers-color-scheme: dark) {
      :root {
        --background-color: #000000;
        --text-color: #ffffff;
      }
    }
    

    Component Stylesheet

    :host {
      display: block;
      background-color: var(--background-color);
      color: var(--text-color);
      padding: 10px;
    }
    
    Login or Signup to reply.
  2. This is a great reference for implementing a light/dark theme switch for a website whilst syncing with the OS settings.

    The concept is that you:

    1. provide a mode switch which operates within the website, and persist the value of the switch in session storage or local storage so that the mode stays the same as the user browses from page to page;
    2. listen for any changes to the OS dark mode setting and adjust the local setting to match;
    3. if there is no mode in session storage or local storage, such as would happen when a user visits the site for the first time, then read the OS dark mode setting and use that as the initial setting.
    4. Include a data attribute on the body element which indicates the current mode, and in your stylesheet use CSS selectors which target specific values of this data attribute to apply light or dark styles.

    And yes, this answer does not specifically apply to web components, but you may find some of these concepts helpful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search