CSS variables for React developers
Tags: react, css, html, javascript
Published: 2022-06-05 17:54:18

Everyone has met a case when we need to customize React components for special design, right? Maybe you even have a UI-kit, but the designer thinks that this is a special case and you have to make this button bigger and brighter? So, I have a simple way to solve it. Say "No" to your designer. That's all. Bye.
It's a joke. I think the work of a software engineer is related to finding tradeoffs and sometimes we must do something a designer wants. Well, I want to talk about an easy way to customize components in React.

### Naive way
Assume you have a button. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lckllhrjw1j27ish86de.png) 
```javascript
export const Button = ({ text, onClick }) => {
  return (
    <button className="button" onClick={onClick}>
      {text}
    </button>
  );
};
```
 With this css:
```css
.button {
  padding: 12px 26px;
  background-color: skyblue;
  color: #ffffff;
  font-size: 1rem;
}
```
And now you need to increase padding and change color:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cdec37n3oh3bg6gk2gh.png)
 
What is the simplest way to do it? Throw additional class name to props and use it:
```javascript
export const Button = ({ text, onClick, className }) => {
  return (
    <button className={cn('button', className)} onClick={onClick}>
      {text}
    </button>
  );
};
```
 I've used [this library](https://www.npmjs.com/package/classnames) to concatenate the className with the _.button_ class

Well, we have a new class:
```css
.secondary-button {
  padding: 20px 32px;
  color: #000000;
}
```
Usage:
```javascript
<Button text="Press me" className="secondary-button" />
```
It's okay, but recently your colleague has changed main button: 
```javascript
export const Button = ({ text, additionalText, onClick, className }) => {
  return (
    <button className={cn("button", className)} onClick={onClick}>
      <span className="button__text">{text}</span>
      <span>{additionalText}</span>
    </button>
  );
};
```
And css:
```css
.button {
  background-color: skyblue;
  font-size: 1rem;
}
.button__text {
  display: inline-block;
  color: #ffffff;
  padding: 12px 26px;
}
```
And what happened with your button? Your styles have broken because your selector isn't so strong as new for text. So, you have a bug.
Yes, you can just pass a new class only for text and everything will be working well, but how long?
I have a more safe and more powerful way to customize your components.

### CSS variables
Everyone knows how to initialize css vars in _:root_ (it's just an alias for `<html>` but more specific):

```css
:root {
  --main-color: #ffffff;
}
``` 
We also can use css vars within other selectors, like a class:
```css
.some-class {
    --main-color: gray;
}
``` 
And these variables also use inheritance like CSS properties.
So, are you thinking the same thing as me? We can use it to customize your component!

```css
.button {
  --button-padding: 12px 26px;
  --button-color: #ffffff;

  padding: var(--button-padding);
  color: var(--button-color);
  background-color: skyblue;
  font-size: 1rem;
}
```
Well, look at the code above. We declare variables and use them in our first button version. Now, if you want to change padding or color, you have to write something like that:
```css 
.secondary-button {
  --button-padding: 20px 32px;
  --button-color: #000000;
}
```
When someone wants to change inner css code of that button, you can be calm - everything will be working well:
```css
.button {
  --button-padding: 12px 26px;
  --button-color: #ffffff;
  background-color: skyblue;
}

.button__text {
  display: inline-block;
  padding: var(--button-padding);
  color: var(--button-color);
}
```
So, we write a low-coupled CSS code, with fewer bugs, and more reusability!

We can use css vars with containers, like this:
```javascript
 export const Button = ({ text }) => {
  return (
    <button className="button">{text}</button>
  );
};
```
```css
.button {
  display: inline-block;
  /* Using default values var(--name, <default value>) */
  background-color: var(--button-bg-color, skyblue);
  color: var(--button-color, #ffffff);
}
```
Now we can initialize variables `--button-bg-color` and `--button-color` in the Button's parent component and that's it!
Let's create a card class and wrap button in:
```css
.card {
  --button-color: #000;
  --button-bg-color: peachpuff;
}
```
```javascript
    <div>
      <Button text="Default button"/>
      <div className="card">
        <Button text="Button into card"/>
      </div>      
    </div>
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fpwkeebewljzeofvkwu0.png)
 

### Conclusion
CSS variables can help you to create reusable components and reduce bugs not only with React, but with other frameworks or without them! Anyway, I hope this article was interesting and you will start to use CSS variables in your work!