Advantages of tss-react over other CSS in JS solutions
I'm the author of TSS, it gets premium integration and support.
I made tss-react in coordination the MUI team. (TSS is documented in the MUI documentation here and here) so it works very well with it. Besides, getting MUI to correctly SSR in a Next.js setup is complicated (see the reference repo). With the help of TSS, it's much easier.
styled-component and @emotion/styled are equivalent API-wise so I give the example with Emotion since it has a better MUI integration.
Optionally, if you want to have access to isDark in your styles, but this is not nessesary because fr.colors uses CSS variables by default.
import { ThemeProvider } from'@emotion/react'import { useIsDark } from"@codegouvfr/react-dsfr/useIsDark";functionRoot(){const { isDark } =useIsDark();return ( <ThemeProvidertheme={{ isDark }}> <App /> </ThemeProvider> );}// Then you'll be able to do the following to have the // hex values of the colors instead of var(--xxx).exportconstMyComponent=MyComponentNotStyled` background-color: ${({ theme: { isDark } })=>fr.colors.getHex({ isDark }).decisions.background.alt.blueFrance.active};`;
spacing
For ensuring the spacing between elements is consistent throughout the website.
This tool is build using this file that is automatically generated from dsfr.css
For writing responsive UIs with media query (@media).
This tool is build using this file that is automatically generated from dsfr.css
import { useStyles } from"tss-react";import { fr } from"@codegouvfr/react-dsfr";functionMyComponent() {const { css,theme } =useStyles();return ( <divclassName={css({ width:"100px", height:"100px" backgroundColor: theme.decisions.background.flat.info.default,// On screen larger than MD the background color // will be colors.decisions.background.alt.blueFrance.default. [fr.breakpoints.up("md")]: { backgroundColor:theme.decisions.background.alt.blueFrance.default }, maxWidth:fr.breakpoints.values.xl })} /> );}
colors
Using the theme object that holds the colors decisions and options.
📣📣📣📣📣📣
There is a tool at your disposal to help you pick your colors.
Use it! It's great!
📣📣📣📣📣📣📣
Using CSS variables (recommended)
This approad is React agnostic and yield the best performances.
import { fr } from"@codegouvfr/react-dsfr";functionMyComponent(){return (<div style={{// The recommended method, using CSS variables: backgroundColor:fr.colors.decisions.background.default.grey.default // This is: backgroundColor: "var(--background-default-grey)" }} /> );}
Using HEX color code
Some third party libraries might require you to provide explicit value as colors.
When CSS variable references doesn't work you can do:
import { fr } from"@codegouvfr/react-dsfr";import { useIsDark } from"@codegouvfr/react-dsfr/useIsDark";functionMyComponent(){const { isDark } =useIsDark();return ( <divstyle={{ backgroundColor:fr.colors.getHex({ isDark }).decisionsbackground.default.grey.default// This is backgroundColor: "#161616" when isDark is true// and backgroundColor: "#ffffff" when isDark is false }} /> );}
useIsDark()
You can access the active mode (isDark: true/false) in the theme object. However, if you want to manually switch the mode, you can use setIsDark(true/false) .
Consider using the <Display /> component instead of trying to manually manage the active mode.
import { useIsDark, getIsDark // Let you access the current value of isDark outside of React (client side only)} from"@codegouvfr/react-dsfr/useIsDark";functionMyComponent(){const { isDark,setIsDark } =useIsDark();//isDark is a boolean that is true if the App is currently in dark mode.//Calling setIsDark(true) will switch the app in dark mode.//calling setIsDark("system") will set to whatever mode is signaled as prefered//by the user browser}
If you want to use the isDark value in your styles:
Be carefull though, favor using fr.breakpoints over client size mesurement and computation.
On the backend you can't know ahead of time the size of the screen of your users so this kind of approach will result in a flickering in SSR setups.
For example, your backend has no clue the size of the device making the request so it renders for a 1080p screen but the device making the request was, in fact, an iPhone and the first print is fully broken, the app becomes usable only after hydration.
Long story short, use this only if you are building an SPA.