--- # 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 ``` Here is the [Modal component from Tailwind Plus]: ```HTML
``` Compare those with [PicoCSS Modal component]: ```html

Modal Title

Modal Body
``` 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 `