Inheritance media queries and css variables
3 min read

This article aims to show an alternative to overriding properties directly. Instead we can use CSS variables with the help of inheritance and media queries. I think that this approach leads to CSS that is easier to read, where all of the properties that appear on a class are all defined in one place.

To demonstrate inheritance we need a class that uses some variables

.sign-up-button {
  background-color: var(--color-alias-sign-up-button);
  color: var(--color-white);
}

Maybe we have a section of our site where we want to apply a dark theme to our sign up button, we can create a class to override the variable used in the sign-up-button class

.dark-theme {
  --color-alias-sign-up-button: var(--color-black);
}

To override through inheritance we can use our dark-theme class as a parent element to our button

<div>
  <h2>DEFAULT</h2>
  <button class="sign-up-button">SIGN UP</button>
</div>
<div class="dark-theme">
  <h2>DARK THEME</h2>
  <button class="sign-up-button">SIGN UP</button>
</div>

This will only override the variable usage for the children elements of our override class. If we wanted to override the variable for all elements we can use the :root selector

:root {
  --color-alias-sign-up-button: var(--color-black);
}

Media Queries

Similar to inheritance through parent elements we can also override variables with media queries

.header {
  --header-height: 50px;
  height: var(--header-height);
}

@media screen and (min-width: 900px) {
  .header {
    --header-height: 30px;
  }
}

Only overriding variables may not always possible because you may need to introduce new properties within a media query

.header {
  --header-height: 50px;
  height: var(--header-height);
}

@media screen and (min-width: 900px) {
  .header {
    --header-height: 30px;
    /* Flex was not in the original class */
    display: flex;
  }
}

When you can pull off a media query by only overriding variables it keeps all of what a class is concerned within one place

.header {
  /* Defining all of the base values within the main class */
  --header-height: 50px;
  --header-display: block;
  height: var(--header-height);
  display: var(--header-display);
}

@media screen and (min-width: 900px) {
  .header {
    /* Then only doing overrides in the media query */
    --header-height: 30px;
    --header-display: flex;
  }
}

I think this pattern of the base class always having the defaults for every property it will use throughout its life on a page leads to CSS that is easier to read.

This pattern is a similar concept that you might use in Javascript where what the function does is in the first few lines of the function then it runs other functions

function setup() {
    buildHTML();
    draw();
    print();
}

function buildHTML { /* ... */ }
function draw { /* ... */ }
function print { /* ... */ }

Combination

The inheritance and the media query techniques can be used in combination too

@media screen and (min-width: 900px) {
  .dark-theme {
    --color-alias-sign-up-button: var(--color-black);
  }
}

More about the color naming pattern in another article.

Was this article helpful?

I'm writing an ebook called Robust UI. Subscribe to get chapters from it via email