How to use global variables in CSS-Modules?
Asked Answered
K

5

39

I'm busy learning React with CSS-Modules and I don't quite understand how one would store variables? For example, in Sass you're able to do this:

// _variables.scss
$primary-color: #f1f1f1; 

// heading.scss
@import './variables';
.heading {
  color: $primary-color
}

How do you achieve this in CSS Modules?

Kall answered 24/11, 2016 at 6:45 Comment(0)
G
8

One way could be to use dependencies. For example,

// variables.css
.primaryColor {
  color: #f1f1f1
}

// heading.css
.heading {
  composes: primaryColor from "./variables.css"
}

See more detailed information here: https://github.com/css-modules/css-modules#dependencies

If you're using webpack there are more examples here: https://github.com/webpack/css-loader#composing-css-classes

Also if you are using webpack you can still use Sass with CSS modules.

Geffner answered 24/11, 2016 at 7:5 Comment(3)
While composition is an option, I would advise following Icharbon's answer. With postcss you have actual variable support, and will help keep code DRY'er. CSS Modules and Sass can be used together though, so I'd prefer Sass variables over the @Value syntax mentioned.Marlinmarline
composition !== variables.Forespeak
While this works for this example, this answer is not the answer to the question "how can you use global values with css modules" haha. For example, what if I wanted to use this color for the background color as well as color?Villar
V
68

This is how you do it with vanilla CSS Modules

// vars.css
:root {
  --color-black: #222;
}


// myComponent.module.css
@import './vars.css';

.component {
  color: var(--color-black);
}
Vallie answered 20/4, 2019 at 22:54 Comment(0)
T
24

The CSS-Modules documentation mentions variables here: https://github.com/css-modules/css-modules/blob/master/docs/values-variables.md

With this you can import variables as so:

@value colors: "../../main/colors.css";
@value primary, secondary, tertiary from colors;

which can be used in your css:

.main {
    background-color: tertiary;
    border-top: 30px solid primary;
}

To make this work postcss-loader and postcss-modules-values need to be added to your webpack config. See below:

        {
            test: /\.css$/,
            use: [{
                    loader: 'style-loader'
                },
                {
                    loader: 'css-loader',
                    options: {
                        modules: true,
                        localIdentName: '[name]_[local]_[hash:base64:5]'
                    }
                },
                {
                    loader: 'postcss-loader',
                    options: {
                        plugins: [postcssModulesValues]
                    }
                }
            ]
        }
Tatar answered 10/8, 2017 at 20:54 Comment(2)
localIdentName has now moved inside modules. You may wanna do: modules: {auto: true, localIdentName: "[name]_[local]_[hash:base64:5]",}Meatus
Any idea how a @value can be used in a CSS calc() ? For example this throws and error: "@value margin: 10px; .someclass{ width: calc(100% - margin); }"Sinfonietta
G
8

One way could be to use dependencies. For example,

// variables.css
.primaryColor {
  color: #f1f1f1
}

// heading.css
.heading {
  composes: primaryColor from "./variables.css"
}

See more detailed information here: https://github.com/css-modules/css-modules#dependencies

If you're using webpack there are more examples here: https://github.com/webpack/css-loader#composing-css-classes

Also if you are using webpack you can still use Sass with CSS modules.

Geffner answered 24/11, 2016 at 7:5 Comment(3)
While composition is an option, I would advise following Icharbon's answer. With postcss you have actual variable support, and will help keep code DRY'er. CSS Modules and Sass can be used together though, so I'd prefer Sass variables over the @Value syntax mentioned.Marlinmarline
composition !== variables.Forespeak
While this works for this example, this answer is not the answer to the question "how can you use global values with css modules" haha. For example, what if I wanted to use this color for the background color as well as color?Villar
H
5

If you add the root css variables in index.css you can access these globally without using @import

This is assuming that index.css is imported in the src/App.js file as the default file structure.

css modules are scoped meaning that the variables inside them are local, but that does not mean you cannot access variables from a global css file.

Example One

Let's say this is our index.css

:root {
  --header-width: 95vw;
  --border-radius-one: 5px;
}
body {
  background-color: #261d54;
  margin: 0;
  font-family: "Poppins", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

We can then access this root css variables like so:

#header {
  margin: 0 auto;
  width: var(--header-width);
  border:1px solid blue;
  border-radius: var(--border-radius-one);
}

Now, if you would like to modify these variables from the script, so that you can make them dynamic you can use the setProperty() JS method to set a new value for a CSS property.

So, the way you would do this in React is by creating a function to change the property and implement an onClick in JSX

Example Two

function changeFontSize(size){
   document.documentElement.setProperty('--font-size', size)
}

return(
  <div>
    <button onClick={() => changeFontSize('18px')}>
      set font size to 18px
    </button>
    <button onClick={() => changeFontSize('12px')}>
      set font size to 12px
    </button>
  </div>
)

If you want to read about documentElement go here.

Haggard answered 14/11, 2022 at 13:18 Comment(0)
B
0

You really don't have to do anything fancy to use CSS Variables in CSS modules.

app/global.css

html {
  --test-color: red;
}

app/layout.tsx

import './globals.css' // << The important bit
import { Link } from '@/app/component/Link'

export default function RootLayout({ children }){
  return (
    <>
      <Link href="/">Home</Link>
      {children}
    </>
  )
}

app/component/link.module.css (nothing fancy, this just works)

.linkElem {
  color: var(--test-color);
}

app/component/Link.tsx

import styles from './link.module.css'

export function Link({ children, href }) {
  return (
    <a href={href} className={styles.linkElem}>{children}</a>
  )
}

PS. I disagree with using :root for defining the base variables since html has lower specificity than :root and so is easier to override.

Beata answered 16/7 at 13:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.