Vincent Barrault

Des thèmes natifs avec les variables CSS.

Des thèmes natifs avec les variables CSS.

Table des matières

Contexte

Dans un de mes précedent article, je me suis posé la question de savoir comment faire un design system avec des thèmes en SASS.

Ce système a des avantages comme celui d'être compatible avec d'anciens navigateurs, mais il a aussi quelques inconvénients.

Par exemple, il n'est pas possible d'imbriquer plusieurs thèmes les uns dans les autres.

./example.html
<div class="theme1">
    <p>Will work</p>
    <div class="theme2">
        <p>Will work if the theme2</p>
        <p>is defined after the theme1</p>
        <div class="theme1">
            <p>Wont work</p>
        </div>
    </div>
</div>

J'ai donc cherché un autre moyen de faire ce genre d'imbrication.

Styled-component

Nativement, styled-components propose un système de thèmes utilisable comme ceci:

./my-component.ts
import styled from 'styled-components';

export MyComponent = styled.div`
    color: ${({ theme }) => theme.primary };
`;

Pour la définition des thèmes, il s'agit de simples fichiers javascript:

./themes.ts
export const theme1 = {
    primary: 'red';
};

export const theme2 = {
    primary: 'blue';
};

La définition du thème se fait de cette manière:

./app.tsx
import { ThemeProvider } from 'styled-components';
import { MyComponent } from './my-component.ts';
import { theme1, theme2 } from './themes.ts';

export function App() {
    return (
        <ThemeProvider theme={theme1}>
            <MyComponent>Red</MyComponent>
        
            <ThemeProvider theme={theme2}>
                <MyComponent>Blue</MyComponent>

                <ThemeProvider theme={theme1}>
                    <MyComponent>Red</MyComponent>
                </ThemeProvider>
            </ThemeProvider>
        </ThemeProvider>
    );
}

Mais en cherchant un peu plus, et comme je ne pouvais pas utiliser styled-components dans mon projet, j'ai trouvé une solution tout aussi simple avec le CSS natif.

Les variables css

Avec cette solution, je peux utiliser SASS, mais ce n'est pas une obligation.

Je commence par définir un fichier de thèmes comme ceci:

./themes.css
:root, .theme1 {
    --color-primary: red;
}
.theme2 {
    --color-primary: blue;
}

Je continue de la même façon avec mon composant (CSS cette fois):

./my-component.css
.my-component {
    color: var(--color-primary);
}

Et l'utilisation de ce code se fait nativement, comme ceci:

./index.html
<div class="whatever">
    <p>This is red by default</p>
    <div class="theme2">
        <p>This is blue</p>
        <div class="theme1">
            <p>This is red</p>
        </div>
    </div>
</div>

Les variables CSS ne sont pas compatibles avec tous les navigateurs, mais ce code est très flexible et sa taille réduite en fait un bon candidat pour partir en production !