---
# vim: spell spelllang=en
title: 'Embracing Modern CSS'
slug: '8-embracing-modern-css'
date: '2025-07-06T14:29:26+02:00'
draft: false
categories:
- dev
tags:
- CSS
summary: |
Where I write about my discoveries of recent CSS I was unaware of.
description: |
The article explores recent developments in CSS, such as nested rules, CSS
variables, and classless CSS, which allow for cleaner and more efficient
stylesheet writing. It also mentions future features like CSS mixins, custom
CSS properties, and CSS scopes, which promise to further enhance the way user
interfaces are styled.
---
I recently stumbled upon a note on a page of [Plain Vanilla] in which I learned
that nested CSS is a thing. It's a thing that's been around for quite some time,
but I did not know about it (I'm quite late in my RSS reader).
This allowed me to catch up on some of the recent evolutions of CSS.
[Plain Vanilla]: https://plainvanillaweb.com/pages/styling.html
## Nested CSS
Nesting CSS rules is one of the main reasons I've been using [SASS] for 15
years.
I've always preferred to write nested rules to group together coherent units of
CSS. For example,
```scss
a {
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
header {
nav {
ul {
list-style: none;
li {
text-align: center;
}
}
}
}
```
makes more sense to me than
```css
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
header nav ul {
list-style: none;
}
header nav ul li {
text-align: center;
}
```
I have a few reasons for this:
* It's easier to read because selectors are sorter and the hierarchy is easier
to grasp;
* I can move around a group of selector without forgetting a declaration;
* I can use my IDE code folding based on indent to close a group and navigate
long CSS files.
Since the [CSS Nesting Module] is [Baseline Widely Available] and is supported
by [90% of users], It can be used to write nested CSS. So now, this is a thing in
CSS:
```css
a {
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
header {
nav {
ul {
list-style: none;
li {
text-align: center;
}
}
}
}
```
The [CSS file] of this site has been rewritten using nested CSS.
[SASS]: https://sass-lang.com
[CSS Nesting Module]: https://drafts.csswg.org/css-nesting/
[Baseline Widely Available]: https://webstatus.dev/features/Nesting
[90% of users]: https://caniuse.com/css-nesting
[CSS file]: https://bcarlin.net/static/css/bcarlin.css
## CSS Variables
To me, variables are essential to ensure a coherent user interface. They allow to
reuse colors, sizes, spacing, and so on.
This is also a reason why I've been using [SASS]. It allowed me to write CSS
with reusable variables :
```scss
$color-error: red;
$color-success: green;
label {
&.error {
color: $color-error;
}
&.success {
color: $color-success;
}
}
.notification {
&.error {
background-color: $color-error;
}
&.success {
background-color: $color-success;
}
}
```
I missed the [CSS Custom Properties for Cascading Variables Module Level 1]
module from 2017, which allowed me to write the same thing in pure CSS:
```css
:root {
--color-error: red;
--color-success: green;
}
label {
&.error {
color: var(--color-error);
}
&.success {
color: var(--color-success);
}
}
.notification {
&.error {
background-color: var(--color-error);
}
&.success {
background-color: var(--color-success);
}
}
```
[CSS Custom Properties for Cascading Variables Module Level 1]: https://www.w3.org/TR/css-variables/
## Classless CSS
Maybe I an going backwards here, given the popularity of utility-first CSS
frameworks like [TailwindCSS].
This one is not really a CSS feature *per se*, but it is a way to write CSS,
where semantically correct HTML is automatically styled correctly. To some
extent, it is, however, backed by some [CSS Selectors Level 4] which are now
Widely implemented across browsers, such as `:has`, `:is`, `:where`, `:not` and
so on.
I used to use [BootstrapCSS] in my projects because it is complete and easy to
use, but I never liked the way it imposed a heavy CSS Structure on my source. For
this site, I was looking for something lighter and came across [PicoCSS] which
styles 90% of my site without changing anything to my templates.
I already had a meaningful semantic HTML base structure:
```html
Page Title
```
And I really like the way it works: the content is styled based on its semantic
markup, and not on a HTML imposed structure.
For example, here is [Bootstrap Modal component]:
```html
Modal Title
Modal Body
```
Here is the [Modal component from Tailwind Plus]:
```HTML
Modal Title
Modal Body
```
Compare those with [PicoCSS Modal component]:
```html
```
It makes a huge difference in simplicity, readability and accessibility (note
that the ARIA attributes are rendered useless because the semantic markup
already carries that information).
[TailwindCSS]: https://tailwindcss.com
[CSS Selectors Level 4]: https://drafts.csswg.org/selectors-4/
[BootstrapCSS]: https://getbootstrap.com
[PicoCSS]: https://picocss.com
[Bootstrap Modal Component]: https://getbootstrap.com/docs/4.3/components/modal/#live-demo
[Modal component from Tailwind Plus]: https://tailwindcss.com/plus/ui-blocks/application-ui/overlays/modal-dialogs
[PicoCSS Modal component]: https://picocss.com/docs/modal
## `@import` to split CSS files
One last thing I liked to use SASS for was the possibility to split CSS files
into smaller ones to make them easier to grasp. For example:
```scss
@use 'reset';
@use 'typography';
@use 'layout';
@use 'content';
```
With the [CSS Cascading and Inheritance Level 5] module, CSS has that natively:
```css
@import url('reset.css');
@import url('typography.css');
@import url('layout.css');
@import url('content.css');
```
From my understanding, the `@import`ed CSS files are downloaded in parallel,
which reduces the penalty of having several files to download.
CSS `@import` rules even have the benefit of being conditional. For example:
```css
@import url("light.css") only screen and (prefers-color-scheme: light);
@import url('dark.css') only screen and (prefers-color-scheme: dark);
```
[CSS Cascading and Inheritance Level 5]: https://drafts.csswg.org/css-cascade-5/
## Things I'm looking forward to
Those are some things I'm looking forward to using. I do not use them yet
because of browser support or because I did not have a use for them yet. But I'm
excited to try them out.
### CSS Mixins
CSS Mixins are also a major feature of SASS, and foster a cleaner and more
reusable CSS code.
CSS will have them with the [CSS Functions and Mixins Module], which is still a
draft where mixins are not specified yet.
In the meantime, here is an example from [SASS Mixin Guide]:
```scss
@mixin rtl($property, $ltr-value, $rtl-value) {
#{$property}: $ltr-value;
[dir=rtl] & {
#{$property}: $rtl-value;
}
}
.sidebar {
@include rtl(float, left, right);
}
```
Though in some cases, it can easily be replaced with CSS variables:
```css
:root {
--sidebar-float: left;
}
[dir=rtl] {
--sidebar-float: right;
}
.sidebar {
float: var(--sidebar-float);
}
```
[SASS Mixin Guide]: https://sass-lang.com/documentation/at-rules/mixin/#arguments
[CSS Functions and Mixins Module]: https://www.w3.org/TR/2025/WD-css-mixins-1-20250515/
### CSS Custom Properties
This one is a nice little feature from the [CSS Properties and Values API Level
1] module which extends CSS variables nicely.
They allow to define the type, initial value and inheritance rule of a custom
variables. For example:
```css {linenos=true}
@property --my-color {
syntax: "";
inherits: false;
initial-value: black;
}
.primary {
--my-color: red;
}
.secondary {
--my-color: 10px;
}
button {
background-color: var(--my-color);
color: white;
}
```
Here, the definition of `--my-color` on line 12 is not valid (it is a length and
not a color). As the property value is not inherited from a parent, the initial
value will be used: a `