diff --git a/assets/static/css/bcarlin.css b/assets/static/css/bcarlin.css index b00a9f7..daf7192 100644 --- a/assets/static/css/bcarlin.css +++ b/assets/static/css/bcarlin.css @@ -236,7 +236,9 @@ body { main { .translations { text-align: end; - margin-bottom: 0.3em; + margin-block-end: 0.3em; + padding-inline-end: 2em; + font-size: 0.9em; a { text-decoration: none; @@ -266,7 +268,48 @@ main { } } - ul > li { + section.table-of-contents { + font-size: 0.9em; + margin-block-end: 2em; + margin-inline-start: 1em; + padding-inline-start: 1em; + border-inline-start: 1px solid var(--pico-muted-color); + + + p { + margin-bottom: 0; /* reset pico styles */ + margin-block-end: 0.2em; + font-weight: bold; + } + + nav { + ol { + &:last-of-type { + margin-right: initial; /* reset pico styles */ + } + + &:first-of-type { + margin-left: initial; /* reset pico styles */ + } + + li { + display: list-item; /* reset pico styles */ + padding: initial; /* reset pico styles */ + list-style-type: none; + + ol { + margin-inline-start: 1em !important; + } + } + } + } + } + + :where(ol,ul) li { + margin-bottom: 0;; + } + + ul li { list-style-type: disc; } diff --git a/config/_default/hugo.yaml b/config/_default/hugo.yaml index cff0111..5d615c3 100644 --- a/config/_default/hugo.yaml +++ b/config/_default/hugo.yaml @@ -7,7 +7,7 @@ copyright: '© 2025 Bruno Carlin' summaryLength: 15 params: author: - email: mail@bcarlin.net + email: blog@mail.bcarlin.net name: Bruno Carlin languages: @@ -36,7 +36,10 @@ outputFormats: markup: highlight: + lineNumbersInTable: false noClasses: false goldmark: parser: wrapStandAloneImageWithinParagraph: false + tableOfContents: + ordered: true diff --git a/config/_default/menus.en.yaml b/config/_default/menus.en.yaml index 627d8d0..b93efae 100644 --- a/config/_default/menus.en.yaml +++ b/config/_default/menus.en.yaml @@ -10,9 +10,16 @@ weight: 20 secondary: + - name: 'Projects' + url: 'https://code.bcarlin.net' + weight: 10 + params: + iconName: "git-pull-request-fill" + iconTitle: "My software forge" + - name: '@bcarlin@hachyderm.io' url: 'https://hachyderm.io/@bcarlin' - weight: 10 + weight: 20 params: rel: "me" iconName: "mastodon-fill" @@ -20,7 +27,7 @@ - name: 'LinkedIn' url: 'https://www.linkedin.com/in/brunocarlin' - weight: 20 + weight: 30 params: rel: "me" iconName: "linkedin-fill" @@ -28,7 +35,7 @@ - name: 'GPG Key' url: '/bcarlin.gpg' - weight: 30 + weight: 40 params: class: "u-key" iconName: "key-fill" diff --git a/config/_default/menus.fr.yaml b/config/_default/menus.fr.yaml index 69fcffa..ccddedd 100644 --- a/config/_default/menus.fr.yaml +++ b/config/_default/menus.fr.yaml @@ -10,9 +10,16 @@ weight: 20 secondary: + - name: 'Projets' + url: 'https://code.bcarlin.net' + weight: 10 + params: + iconName: "git-pull-request-fill" + iconTitle: "Ma forge logicielle" + - name: '@bcarlin@hachyderm.io' url: 'https://hachyderm.io/@bcarlin' - weight: 10 + weight: 20 params: rel: "me" iconName: "mastodon-fill" @@ -20,7 +27,7 @@ - name: 'LinkedIn' url: 'https://www.linkedin.com/in/brunocarlin' - weight: 20 + weight: 30 params: rel: "me" iconName: "linkedin-fill" @@ -28,7 +35,7 @@ - name: 'Clef GPG' url: '/bcarlin.gpg' - weight: 30 + weight: 40 params: class: "u-key" iconName: "key-fill" diff --git a/content/blog/008-embracing-modern-css/index.en.md b/content/blog/008-embracing-modern-css/index.en.md new file mode 100644 index 0000000..b1ed39f --- /dev/null +++ b/content/blog/008-embracing-modern-css/index.en.md @@ -0,0 +1,542 @@ +--- +# vim: spell spelllang=en +title: 'Embracing Modern CSS' +slug: '008-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 ` + + + + + + +``` + +Voici le [composant Modal de Tailwind Plus] : + +```html +
+ + +
+``` + +Comparez-les avec le [composant Modal de PicoCSS] : + +```html + +
+
+ +

+ Titre de la fenêtre +

+
+ + Corps de la fenêtre + +
+ + +
+
+
+``` + +Cela fait une énorme différence en termes de simplicité, de lisibilité et +d'accessibilité (notez que les attributs ARIA sont rendus inutiles car le +balisage sémantique porte déjà cette information). + +[TailwindCSS]: https://tailwindcss.com +[Sélecteurs CSS Niveau 4]: https://drafts.csswg.org/selectors-4/ +[BootstrapCSS]: https://getbootstrap.com +[PicoCSS]: https://picocss.com +[composant Modal de Bootstrap]: https://getbootstrap.com/docs/4.3/components/modal/#live-demo +[composant Modal de Tailwind Plus]: https://tailwindcss.com/plus/ui-blocks/application-ui/overlays/modal-dialogs +[composant Modal de PicoCSS]: https://picocss.com/docs/modal + +## `@import` pour diviser les fichiers CSS + +Un dernièr point pour lequel j'aimais utiliser SASS était la possibilité de +diviser les fichiers CSS en fichiers plus petits pour les rendre plus faciles à +comprendre. Par exemple : + +```scss +@use 'reset'; +@use 'typography'; +@use 'layout'; +@use 'content'; +``` + +Avec le module [CSS Cascading and Inheritance Level 5], CSS a cela nativement : + +```css +@import url('reset.css'); +@import url('typography.css'); +@import url('layout.css'); +@import url('content.css'); +``` + +De ma compréhension, les fichiers CSS `@import`és sont téléchargés en parallèle, +ce qui réduit le coût d'avoir plusieurs fichiers à télécharger. Les règles +CSS `@import` ont même l'avantage d'être conditionnelles. Par exemple : + +```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/ + +## Les évolutions que j'attends avec impatience + +Voici quelques spécifications que j'ai hâte d'utiliser. Je ne les utilise pas +encore en raison du support des navigateurs ou parce que je n'en ai pas encore +eu besoin. Mais je suis impatient de les essayer. + +### Mixins CSS + +Les Mixins CSS sont également une fonctionnalité majeure de SASS, et favorisent +un code CSS plus propre et plus réutilisable. + +CSS les aura avec le [Module des fonctions et mixins CSS], qui est encore un +brouillon, et dans lequel les mixins ne sont pas encore spécifiés. + +En attendant, voici un exemple du [Guide des Mixins SASS] : + +```scss +@mixin rtl($property, $ltr-value, $rtl-value) { + #{$property}: $ltr-value; + + [dir=rtl] & { + #{$property}: $rtl-value; + } +} + +.sidebar { + @include rtl(float, left, right); +} +``` + +Bien que dans certains cas, cela puisse être facilement remplacé par des +variables CSS : + +```css +:root { + --sidebar-float: left; +} + +[dir=rtl] { + --sidebar-float: right; +} + +.sidebar { + float: var(--sidebar-float); +} +``` + +[Guide des Mixins SASS]: https://sass-lang.com/documentation/at-rules/mixin/#arguments +[Module des fonctions et mixins CSS]: https://www.w3.org/TR/2025/WD-css-mixins-1-20250515/ + +### Propriétés Personnalisées CSS + +Celle-ci est une petite fonctionnalité sympa du module [CSS Properties and +Values API Level 1] qui étend les variables CSS. + +Elles permettent de définir le type, la valeur initiale et la règle d'héritage +d'une variable personnalisée. Par exemple : + +```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; +} +``` + +Ici, la définition de `--my-color` à la ligne 12 n'est pas valide (c'est une +longueur et non une couleur). Comme la valeur de la propriété n'est pas héritée +d'un parent, la valeur initiale sera utilisée : un `