Great things are done by a series of small things brought together

Vincent Van Gogh

Sass placeholder and its limits

From the official πŸ“š Sass documentation

Sass has a special kind of selector known as a β€œplaceholder”. It looks and acts a lot like a class selector, but it starts with a % and it's not included in the CSS output. In fact, any complex selector (the ones between the commas) that even contains a placeholder selector isn't included in the CSS, nor is any style rule whose selectors all contain placeholders.

We can write a placeholder for reusable pieces of code prefixed by the % keyword:

// colors.scss

%colors-per-viewport {
background: red;

@media (min-width: 768px) {
background: blue;
}
}

and call the placeholder using the syntax @extend %[placeholder-name]

// component.scss

.colors {
@extend %colors-per-viewport;
}

CSS output:

.colors {
background: red;
}
@media (min-width: 768px) {
.colors {
background: blue;
}
}

As seen above, we could also declare a code snippet with mediaquery inside.

The small matter #

Unfortunately, we cannot call a placeholder declaration inside a mediaquery 😩

For instance, if we try to declare two placeholders and call them inside a media query

%colors-mobile {
background: yellow;
}

%colors-tablet {
background: green;
}
.colors-viewport {
@extend %colors-mobile; // ok!

@media (min-width: 768px) {
@extend %colors-tablet; // nope!
}
}

The code above will throw an error 😭

You may not @extend an outer selector from within @media.
You may only @extend selectors within the same directive.

So, if we really need to reuse a code snipped inside a mediaquery, we can use a mixin declaration.

I know, it is not the correct use of the mixin function... but it's a desperate measure! πŸ˜…

@mixin colors-mobile {
background: yellow;
}

@mixin colors-tablet {
background: green;
}
.colors-viewport {
@include colors-mobile; // ok!

@media (min-width: 768px) {
@include colors-tablet; // yasss!
}
}

πŸ“š More info

Edit this page on GitLab

Comment on DEV or Hashnode

Take me to the next post!