💅CSS in JS

Compatibility with solutions like styled-components, emotion and TSS.

At build time react-dsfr parses the official dsfr.css files and spits out a typed JavaScript representation of the DSFR. In particular, its colors options and decisions, the spacing system and the breakpoints values.

This enables to write DSFR compliant CSS in JS code, since we are able to expose function that are the equivalent of the DSFR utility classes.

You can use the style props on native react components but you won't be able to use the fr.breakpoint utility that enable to write responsive code.

import { fr } from "@codegouvfr/react-dsfr";

export type Props = {
    className?: string;
};

export const MyComponent =(props: Props) => {

    const { className } = props;
    
    return (
	<div 
	    className={className}
	    style={{
	        padding: fr.spacing("10v"),
		//SEE: https://components.react-dsfr.codegouv.studio/?path=/docs/%F0%9F%8E%A8-color-helper--page
	        backgroundColor: fr.colors.decisions.background.alt.blueFrance.active
	    }}
	>
	    <span 
	        className={fr.cx("fr-p-1v")}
	        style={{
	            ...fr.spacing("margin", { "topBottom": "3v" })
	        }}
	    >
	        Hello World
	    </span>
	</div>
    );

};

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

import { fr } from "@codegouvfr/react-dsfr";

function MyComponent() {

    return (
        <div 
            style={{ 
                marginTop: fr.spacing("2v"),
                ...fr.spacing("padding", { topBottom: "5w", left: 5 })
            }}
        />
    );

}

The above code is equivalent to:

import { fr } from "@codegouvfr/react-dsfr";

function MyComponent() {

    return (
        <div 
            style={{ 
                marginTop: fr.spacing("2v"),
                paddingTop: fr.spacing("5w"),
                paddingBottom: fr.spacing("5w"),
                paddingLeft: 5
            }}
        />
    );

}

Which is in turn equivalent to:

import { fr } from "@codegouvfr/react-dsfr";

function MyComponent() {

    return (
        <div 
            style={{ 
                marginTop: "0.5rem",
                paddingTop: "2.5rem",
                paddingBottom: "2.5rem",
                paddingLeft: 5
            }}
        />
    );

}

breakpoints

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";

function MyComponent() {

    const { css, theme } = useStyles();
    
    return (
        <div
            className={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.

This approad is React agnostic and yield the best performances.

import { fr } from "@codegouvfr/react-dsfr";

function MyComponent(){

  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";

function MyComponent(){

  const { isDark } = useIsDark();

  return (
    <div style={{
      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";

function MyComponent(){

    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:

import { tss } from "tss-react";
import { useIsDark } from "@codegouvfr/react-dsfr/useIsDark";

function MyComponent(props){

    const { className } = props;
    
    const { isDark } = useIsDark();
    const { classes, cx } = useStyles({ isDark });
    
    return (
        <div classNames={cx(classes.root, className)}>
           // ...
        </div>
    );
    
}

const useStyles = tss
  .withParams<{ isDark: boolean; }>()
  .create(({ isDark })=> ({
    root: { /* ... */ }
  }));

useBreakpointsValuesPx()

It returns the values in pixel of the different breakpoint ("xs", "md", "lg", "xl") based on the current root font size.

It can be used to do stuffs like this, geting the number of column of a responsive layout in JavaScript:

import { useBreakpointsValuesPx } from "@codegouvfr/react-dsfr/useBreakpointsValuesPx";
import { useWindowInnerSize } from "@codegouvfr/react-dsfr/tools/useWindowInnerSize";

function useColumnCount(){

        const { breakpointsValues } = useBreakpointsValuesPx();

        const { windowInnerWidth } = useWindowInnerSize();

        const columnCount = (() => {
            if (windowInnerWidth < breakpointsValues.md) {
                return 1;
            }

            if (windowInnerWidth < breakpointsValues.xl) {
                return 2;
            }

            return 3;
        })();
        
        return collumnCount;

}

Last updated

Was this helpful?