SCSS— Implement styles for multiple themes with the @content directive

Liu Ting Chun
3 min readApr 22, 2020

Modern websites usually have more than one theme, e.g. light and dark themes. They have different set of preset colors and they can be toggled between each other in runtime. The simplest way to implement this use case is to have different sets of theme colors predefined as SCSS variables and use wrapper classes to apply them.

$theme-light: (
primary: #4287f5,
secondary: #666666
);
$theme-dark: (
primary: #f542b6,
secondary: #c9c9c9
);
.btn {
display: inline-block;
font-weight: 400;
color: #212529;
text-align: center;
vertical-align: middle;
cursor: pointer;
user-select: none;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
}
.theme-light .btn {
background-color: map-get($theme-light, primary);
border-color: map-get($theme-light, primary);
}
.theme-dark .btn {
background-color: map-get($theme-dark, primary);
border-color: map-get($theme-dark, primary);
}

If you are trying to implement your themes like this, you will soon find it a nightmare to maintain. It is because you have to repeatedly write the rules and styles for each theme. In fact, this can be done in a much cleverer way with the SCSS @content directive.

Image from material.io

What is the @content directive?

@content is a SCSS built-in directive that takes a block of styles and projects those styles into a mixin. It allows developers to flexibly add a set of styles into a mixin. You may consider it as something like <ng-content> in Angular or <slot> in Vue in a higher level understanding. Here is an example:

@mixin hover {
&:not([disabled]):hover {
border-width: 2px;
@content;
}
}
.button {
border: 1px solid black;
@include hover {
border-color: gray;
}
}

Is equivalent to:

.button {
border: 1px solid black;

&:not([disabled]):hover {
border-width: 2px;
border-color: gray;
}
}

What is more, you can even pass arguments to your @content block. Here is another piece of example code which is also equivalent:

Liu Ting Chun

Web developer from Hong Kong. Most interested in Angular and Vue. Currently working on a Nuxt.js + NestJS project.