skip to Main Content

I am trying to create a basic CSS template for a project. It needs to support both a light and dark mode.

In the html, the body tag has data-layout-color attribute. I have some toggles that allow switching between light and dark, and it is updating this attribute. In my CSS sheet, I use the attribute selector for background color, and it works! Now I need to be able to set other elements color based on the light/dark mode, but that’s not working as the individual element doesn’t have the attribute. I don’t want to add data-layout-color to everything, and then have to update it all with my js. Any suggestions?

HTML:

<body ng-controller="myApp" data-layout-color="dark" data-layout="topnav">
<button type="button" class="btn btn-primary">PRESS ME!</button>
</body>

CSS:

body[data-layout-color="dark"]{
background-color: var(--my-body-dark-bg);
}
body[data-layout-color="light"]{
background-color: var(--my-body-light-bg);
}
.btn-primary[data-layout-color="light" {
color: var(--my-white-light);
background-color: var(--my-primary-light);
border-color: var(--my-primary-light);
}
.btn-primary[data-layout-color="dark" {
color: var(--my-white-dark);
background-color: var(--my-primary-dark);
border-color: var(--my-primary-dark);
}

2

Answers


  1. With plain css you can write it like this

    body[data-layout-color="dark"]{
        background-color: var(--my-body-dark-bg);
    }
    
    body[data-layout-color="dark"] .btn-primary{
        color: var(--my-white-dark);
        background-color: var(--my-primary-dark);
        border-color: var(--my-primary-dark);
    }
    
    body[data-layout-color="dark"] .btn-primary a{
        text-decoration: underline overline #FF3028;
    }
    
    

    I suggest you use scss though. It will make your life easier. If you’r using visualstudio code just download Live sass complier and click watch sass in the bottom right corner.

    Using scss you would write it like this:

    
    body[data-layout-color="dark"]{
        background-color: var(--my-body-dark-bg);
    
        .btn-primary{
            color: var(--my-white-dark);
            background-color: var(--my-primary-dark);
            border-color: var(--my-primary-dark);
    
            a{
                 text-decoration: underline overline #FF3028;
            }
        }
    
    
        .btn-secondary{
            color: var(--my-white-dark-secondary);
            background-color: var(--my-primary-dark-secondary);
            border-color: var(--my-primary-dark-secondary);
        }
    
        p{
            color: var(--my-white-dark);
        }
    }
    body[data-layout-color="light"]{
        background-color: var(--my-body-light-bg);
    
        /*etc etc*/
    
    }
    
    Login or Signup to reply.
  2. You could write your selectors such that the attribute selector remains on body:

      /* primary button under a "light" layout parent */
    
      [data-layout-color="light"] .btn-primary {
        color: var(--my-white-light);
        background-color: var(--my-primary-light);
        border-color: var(--my-primary-light);
      }
    

    But I think a better idea would be to change the custom property values so you don’t need the theme-specific selectors on child elements in the first place:

    [data-layout-color="dark"] {
      --button-color-bg: white;
      --button-color-fg: black;
    }
    
    [data-layout-color="light"] {
      --button-color-bg: black;
      --button-color-fg: white;
    }
    
    .btn-primary {
      background-color: var(--button-color-bg);
      color: var(--button-color-fg);
      
      display: inline-block;
      padding: 0.25em 1em;
      border: 1px solid grey;
      margin: 0.5em;
    }
    <div data-layout-color="dark">
      <div class="btn-primary">Dark Body</div>
    </div>
    
    <div data-layout-color="light">
      <div class="btn-primary">Light Body</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search