Il existe de nombreuses approches et solutions différentes pour gérer le CSS en React, je vais parler ici de styled-components qui permet de gagner en productivité et en qualité quand on veut créer et distribuer des composants UI.
La force de styled-components c'est de faciliter la création de composants visuels React minimalistes et configurables, en combinant du CSS standard et un zeste de JavaScript. Ces composants deviendront littéralement les pièces de lego qui pourront être utilisées et partagées entre les UIs de toutes vos applications, sites webs...
Si vous voulez jouer avec, je vous conseille d'utiliser
create-react-app pour
générer un projet vierge puis d'ajouter styled-components au projet :
npm i --save styled-components
.
Avec styled, on peut abstraire le CSS et le DOM de la vue, ce qui va grandement simplifier le code de la partie "métier" de l'application, et améliorer la lisibilité.
// solution en pure CSS-in-JS
const styles = {
box: {
width: '60%',
border: '1px solid silver'
},
title: {
fontSize: '1.2em',
fontWeight: 'bold'
},
description: {
fontSize: '0.8em'
},
important: {
fontWeight: 'bold'
}
}
// nos composants intègrent les styles dans le code
<div className={ styles.box }>
<div className={ styles.title }>{ title }</div>
<div className={ classnames(styles.description, styles.important) }>{ description }</div>
</div>
// avec styled-components
const Box = styled.div`
width: 60%;
border: 1px solid silver;
`
const Title = styled.div`
font-size: 1.2em;
font-weight: bold;
`
const Description = styled.div`
font-size: 0.8em;
font-weight: ${ props => props.important ? 'bold' : 'normal '}
`
// les composants sont pré-stylés, pas de bruit généré par le styling
<Box>
<Title>{ title }</Title>
<Description important>{ description }</Description>
</Box>
Techniquement, styled-components va pour chaque composant "styled" présent dans le DOM :
<head>
de la
page, au runtime.className
unique (ainsi que ses ownProps
)La syntaxe est certes exotique, le CSS étant défini dans un template-string ES2015, mais ceci rend le code très concis.
Pour en savoir plus sur les "Template Strings", ou "Littéraux de gabarits" en Français 🇫🇷 vous pouvez lire l'excellente doc chez MDN.
import styled from 'styled-components'
// exemple ici avec une div
const Title = styled.div`
font-size: 3rem;
color: #ff3333;
`
// utilisable comme ceci :
<Title>Hello, World</Title>
ceci qui génèrera automatiquement dans le DOM:
<div class="dxhUOh">Hello, World</div>
et injectera dans le CSS de la page le style associé :
.dxhUOh {
font-size: 3rem;
color: #ff3333;
}
Les composants styled sont des composants React standards qui peuvent recevoir
des children
et se composer les uns avec les autres.
const Box = styled.div`
border: 1px solid silver;
width: 80%;
padding: 1em;
text-align: center;
background: #e7f3ff;
`
const Title = styled.div`
font-size: 1.5em;
color: #0080ff;
`
<Box>
<Title>Hello, World</Title>
</Box>
Surcharger un composant avec du CSS :
const Title = styled.div`
font-size: 3rem;
color: #ff3333;
`
const BlueTitle = styled(Title)`
color: #0080ff;
`
<Title>titre en rouge</Title>
<BlueTitle>titre en bleu</BlueTitle>
Les pseudo-classes, le nesting sont acceptées
const Button = styled.button`
font-size: 3rem;
color: #ff3333;
&:hover {
color: #0080ff;
}
`;
Les medias queries sont possibles facilement :
const Cover = styled.div`
background-image: url(http://putaindecode.io/assets/npm.png);
background-repeat: no-repeat;
background-size: contain;
background-position: center center;
width: 800px;
height: 300px;
@media (max-width: 800px) {
width: 400px;
}
`;
Usage avancé des media queries : https://github.com/styled-components/styled-components/blob/master/docs/tips-and-tricks.md#media-templates
Mieux : comme le composant à directement accès aux props
(attributs du
composant), on peut le configurer depuis le JavaScript :
const Title = styled.div`
font-size: 3rem;
color: ${props => props.blue ? '#0080ff' : '#ff3333'};
`
<Title>titre en rouge</Title>
<Title blue>titre en bleu</Title>
Avec la methode styled.css
, une className
unique est générée et peut être
utilisée pour vos composants :
import Notification from "./Notification";
const warning = styled.css`
color: #ff3333;
`;
const WarningNotification = () => <Notification className={warning} />;
Comme styled utilise des templates literals vous pouvez utiliser n'importe quelle variable dans votre CSS :
const textStyle = `
font-size: 2em;
letter-spacing: 5px;
`
const TextRed = styled.div`
${textStyle}
color: #ff3333;
`
const TextBlue = styled.div`
${textStyle}
color: #0080ff;
`
<TextRed>texte en rouge</TextRed>
<TextBlue>texte en bleu</TextBlue>
Par défaut les composants styled passent toutes leur props
au DOM, par exemple
ici, placeholder
.
const SuperInput = styled.input`
border: 2px solid silver;
border-radius: 2px;
text-align: center;
font-size: 1.5em;
`
<SuperInput placeholder="Your name"/>
Pour rendre son UI themable, il suffit d'encapsuler son App dans un composant
ThemeProvider
; Chaque composant styled se verra alors fournir une props
theme
avec toutes les variables du thème :
const Button = styled.button`
background: ${props => props.theme.main || 'silver'};
`
// Create a green theme
const greenTheme = {
main: 'mediumseagreen',
}
// Create a blue theme
const blueTheme = {
main: '#0080ff',
}
<ThemeProvider theme={greenTheme}>
<Button>I'm green!</Button>
</ThemeProvider>
Et pour aller loin, consultez la documentation officielle
Parfois on a besoin d'intégrer aussi du CSS "global". Par exemple pour les fontes, ou lorsque l'on migre une grosse application.
Voici une façon de le faire avec styled :
import { injectGlobal } from "styled-components";
injectGlobal`
@import url('https://fonts.googleapis.com/css?family=Roboto');
* {
font-family: 'Roboto', sans-serif;
}
`;
Plus d'infos sur la doc d'injectGlobal
En ajoutant react-storybook dans votre projet, vous pourrez facilement vous constituter une bibliothèque visuelle avec vos propres composants, hors-contexte, dans tous leurs états possibles, et avec du Hot-Reload ce qui est très très pratique dans la phase de conception.