• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 23/02/2024

Scopez votre CSS avec styled components

Pour ajouter du style à votre application React, vous avez certainement jusqu'ici utilisé du CSS. Pour gagner du temps de développement sur le CSS nous pouvons même utiliser des bibliothèques comme Bootstrap ou encore Tailwind. Cependant, vous est-il déjà arrivé de réutiliser le nom d'une classe CSS dans un autre composant sans faire exprès ? Ou bien encore de trouver du style appliqué à un élément sans comprendre d'où il venait ? Si ça vous est déjà arrivé, vous devez savoir à quel point c'est frustrant ! 😬

L'enjeu de scoper notre style aux composants concernés est réel.

Hmm… "scoper", encore un anglicisme que je n'ai jamais vu... ?

Le scope correspond aux parties de notre code qui ont accès à un élément, comme une variable, ou une classe CSS. Il peut être global (comme c'est le cas pour les classes CSS dont je vous parlais il y a quelques instants), ou bien concerner une partie spécifique du code.

Pour scoper le style, il existe des solutions, telles que des méthodologies d'architecture de CSS ou bien des outils spécifiques comme Sass (qui requiert un préprocesseur). Mais depuis quelques années, le CSS in JS émerge comme l'une des solutions à notre problème.

Découvrez le CSS in JS

Comme son nom l'indique, le CSS in JS est généré… avec du JavaScript. Il sera inséré dans le DOM dans un élément  <style>  .

Ah mais je vois, c'est comme l'inline style qu'on avait vu au chapitre "Incorporez du style et des assets à votre projet", dans le cours précédent

... Eh bien non. L'inline style est inséré dans le DOM sur l'attribut  style  d'un élément spécifique (souvenez-vous, on fait  <div style={{ color: 'red' }} />  ). Par ailleurs, l'inline style ne permet pas d'utiliser les pseudo-selectors. Ce n'est pas pareil pour le CSS in JS, avec lequel on peut utiliser autant de pseudo-selectors que nécessaire (on le verra un plus tard dans ce chapitre).

Mais avec le CSS in JS, on garde l'idée que le style est attaché à un composant spécifique, directement dans le même fichier. Beaucoup plus simple lorsqu'il faut supprimer ou modifier du style déjà existant, n'est-ce pas ?

Il existe plusieurs solutions de CSS in JS, avec leurs syntaxes propres. Ici nous allons nous intéresser à la bibliothèque styled components. 💅

Commençons dès maintenant par installer la bibliothèque avec  yarn add styled-components  :

Styled-components s’installe
Styled-components s’installe

Tada !

Penchons-nous dès maintenant sur le style que nous allons pouvoir créer ! 👀

Appliquez la logique styled components

Dans styled components, la principale chose à comprendre est que tout est composant. Pour voir cela, créons dès maintenant notre premier styled component (styled composant).

Dans  Card/index.jsx  , créons donc le style pour le  label  .

On commence par ajouter l'import de styled-components puis nous créons notre composant  CardLabel  de la manière suivante :

import styled from 'styled-components'

const CardLabel = styled.span``

Et on a réutilisé  CardLabel  directement dans le JSX :

<CardLabel>{label}</CardLabel>

Mais qu'est-ce que c'est que cette syntaxe bizarre ? 😬

Pas de panique ! Ici,  styled-components  utilise des templates literals, que vous pouvez voir dans la documentation Mozilla. Vous pouvez écrire votre CSS directement à l'intérieur. Ce qui nous donne :

const CardLabel = styled.span`
    color: #5843e4;
    font-size: 22px;
    font-weight: bold;
`

Profitons-en pour ajouter du style à notre image. Cette fois-ci, toujours dans le même fichier  Card/index.jsx  , on a :

const CardImage = styled.img`
    height: 80px;
    width: 80px;
    border-radius: 50%;
`

… qu'on utilise dans le code :

<CardImage src={picture} alt="freelance" />

Bravo à vous ! Vous avez généré des éléments  span  et  img  auxquels vous avez appliqué du style avec  styled-components  ! 🎉 Vous vous en doutez, ça ne s'arrête pas à  span  et  img  : vous pouvez ainsi générer tous les éléments existants du DOM… mais pas que.

Par exemple, comment faire si je veux styliser un élément qui vient d'une bibliothèque ?

Styled components prévoit ce cas ! Prenons l'exemple de  Header/index.jsx  . Pour cela, il nous suffit de faire :

import { Link } from 'react-router-dom'
import styled from 'styled-components'

const StyledLink = styled(Link)`
    padding: 15px;
    color: #8186a0;
    text-decoration: none;
    font-size: 18px;
`

function Header() {
    return (
        <nav>
            <StyledLink to="/">Accueil</StyledLink>
            <StyledLink to="/survey/1">Questionnaire</StyledLink>
            <StyledLink to="/freelances">Profils</StyledLink>
        </nav>
    )
}

export default Header

Essayez ce code pour voir le rendu vous-même – pas mal, n'est-ce pas ?

Passez des props dans votre CSS

C'est bien beau, nous avons créé nos styled components et nous les avons utilisés, mais quels autres avantages tire-t-on du fait d'écrire notre style avec du JS ?

... Eh bien justement, on utilise du JS. 😎 On va pouvoir passer des props à nos composants directement depuis notre composant React.

Voyons voir concrètement ce que cela donne dans notre  Header  .

<StyledLink to="/survey/1" $isFullLink>
    Faire le test
</StyledLink>

Ici on passe la prop $isFullLink  . Ce qui nous permet d'utiliser la prop directement dans le style :

const StyledLink = styled(Link)`
    padding: 15px;
    color: #8186a0;
    text-decoration: none;
    font-size: 18px;
    ${(props) =>
        props.$isFullLink &&
        `color: white; border-radius: 30px; background-color: #5843E4;`}
`

C'est quoi ce  $  ?

Eh bien, cela permet de signaler à  styled-components  que notre prop nous sert pour le style, et qu'elle ne doit pas être passée dans le DOM.

Ce  $  est uniquement nécessaire pour passer une prop si le composant en question est un composant React, comme ici pour  Link  (et non un élément HTML). Si mon styled component était basé sur une simple balise  a  , je pourrais totalement utiliser la prop  isFullLink  sans le  $  .

Voyons l’utilisation du state en prop de plus près dans le screencast ci-dessous :

Pas maaaal ! 🤩

Utilisez des variables

Vous voyez, dans notre dernier snippet de code juste au-dessus du screencast, on a encore utilisé la couleur violette  #5843E4  . Qui dit JS dit aussi qu'on peut utiliser des variables, et c'est ce que nous allons faire : nous allons utiliser des variables pour stocker nos couleurs !

Vous pourriez tout simplement déclarer un objet  colors  qui reprend toutes les couleurs de notre application, mais il est considéré comme une bonne pratique de créer un thème géré par  styled-components  .

On crée donc un dossier  /utils  directement dans  src/  , dans lequel on met un dossier  /style  . On y crée notre fichier  colors.js  , ce qui nous donne :

├── assets
│   └── profile.png
├── components
│   ├── Card
│   │   └── index.jsx
│   ├── Error
│   │   └── index.jsx
│   └── Header
│       └── index.jsx
├── index.jsx
├── pages
│   ├── Freelances
│   │   └── index.jsx
│   ├── Home
│   │   └── index.jsx
│   ├── Results
│   │   └── index.jsx
│   └── Survey
│       └── index.jsx
└── utils
└── style
└── colors.js

Dans  colors.js  , on définit nos couleurs :

const colors = {
    primary: '#5843E4',
    secondary: '#8186A0',
    backgroundLight: '#F9F9FC',
}

export default colors

Pour l'utiliser, il nous suffit de l'importer directement dans notre template string :

const StyledLink = styled(Link)`
    padding: 15px;
    color: #8186a0;
    text-decoration: none;
    font-size: 18px;
    ${(props) =>
        props.$isFullLink &&
        `color: white; border-radius: 30px; background-color: ${colors.primary};`}
`

Et on a bien ce qu'on voulait. 💅

Par contre, comment faire si je veux styliser mon composant au survol de la souris ?

Eh bien, c'est très simple ici puisque les pseudosélecteurs fonctionnent dans nos styled components.

Pour mettre tout ça en pratique, on va retourner sur nos  Cards  . On y ajoutera un peu de style pour que l'effet de hover soit plus visible. Dans  pages/freelances.jsx  , on met :

const CardsContainer = styled.div`
    display: grid;
    gap: 24px;
    grid-template-rows: 350px 350px;
    grid-template-columns: repeat(2, 1fr);
`

... qu'on utilise tout de suite dans le même fichier :

function Freelances() {
    return (
        <div>
            <h1>Freelances 👩‍💻👨‍💻👩‍💻</h1>
            <CardsContainer>
                {freelanceProfiles.map((profile, index) => (
                    <Card
                        key={`${profile.name}-${index}`}
                        label={profile.jobTitle}
                        title={profile.name}
                    />
                ))}
            </CardsContainer>
        </div>
    )
}

Puis dans  Card/index.jsx  , on peut créer un effet d'ombre au survol de la souris. Pour ça, on crée un  CardWrapper  qui vient remplacer notre précédente  div  :

function Card({ label, title, picture }) {
    return (
        <CardWrapper>
            <CardLabel>{label}</CardLabel>
            <CardImage src={picture} alt="freelance" />
            <span>{title}</span>
        </CardWrapper>
    )
}

Et on définit CardWrapper comme suit :

const CardWrapper = styled.div`
    display: flex;
    flex-direction: column;
    padding: 15px;
    background-color: ${colors.backgroundLight};
    border-radius: 30px;
    width: 350px;
    transition: 200ms;
    &:hover {
        cursor: pointer;
        box-shadow: 2px 2px 10px #e2e3e9;
    }
`

La syntaxe  &:hover  nous permet d'accéder au pseudosélecteur du survol de la souris, et on a bien l'effet souhaité ! 🤩

Une ombre s'affiche au survol de la souris
On a bien l'effet d'ombre au survol de la souris

Créez un style global

Nous avons déjà vu beaucoup de choses avec styled components. Encore une fois, nous ne pouvons pas tout couvrir dans ce chapitre, mais avant de conclure j'aimerais que nous créions un style global. Cela nous permettra de créer un style de base, notamment pour la police ou pour d'autres propriétés CSS.

Pour cela, dans  index.jsx  à la racine de notre projet, vous pouvez créer un composant GlobalStyle :

const GlobalStyle = createGlobalStyle`
    div {
        font-family: 'Trebuchet MS', Helvetica, sans-serif;
    }
`

Et vous l'importez tout simplement dans vos composants :

<Router>
    <GlobalStyle />
    <Header />
        …
</Router>

Et voilà ! Ensemble, nous avons utilisé  styled-components  pour styliser notre application ! 🎉

Exercez-vous

C'est maintenant le moment de vous exercer en autonomie sur la bibliothèque  styled-components  . Vous trouverez la base de code nécessaire pour commencer cet exercice sur la branche  P1C4-begin  du projet sur GitHub.

Cette fois-ci, vous devrez vous appuyer sur la maquette Figma et créer le style pour : 

  • le header (intégration du logo, position des liens) ;

  • la page d'accueil (intégration du texte, de l'illustration, du background, etc.) ;

  • la page Profils (texte au-dessus des Cards) ;

  • la page d'erreur.

Comme d'habitude, vous trouverez la solution de cet exercice sur la branche  P1C4-solution . 🤫

En résumé

  • Styled components est une bibliothèque de CSS in JS qui permet de créer du style en appliquant une logique de composants.

  • Les template strings utilisées écrites entre  ``   permettent d'utiliser des variables et de passer des props.

  • Il est possible de créer un style global avec  createGlobalStyle  .

Bravo à vous, maintenant que vous avez intégré du style, l'application que vous codez pour Shiny Agency commence vraiment à prendre forme ! 

Dans le prochain chapitre, vous allez tester vos connaissances avec le quiz de cette partie. Alors, bonne chance à vous ! 🍀

Exemple de certificat de réussite
Exemple de certificat de réussite