React Style : 4 ways to apply style to components
Tags: react, css
Published: 2020-05-02 17:38:06

# What's the matter with styling React components ?
React, as you may already know, is a JavaScript library used to build complex web applications by a component architecture. Its paradigm is to provide a total freedom of structure, without requirement nor unique way to achieve something.

Beside this liberty, React offers a wide land of potential mistakes and hard to maintain features if you let yourself fall into laziness of non-testing your code, don't clarify your own folders, or miss opportunities to write reusable code.

And then comes style. Some coders like me use to have nightmares just thinking of CSS, and sadly, React don't show up with a dedicated solution. Well, in fact, there's one, and we will find out!

## Basic styling with React
If you ain't new to React, you're probably used to style components like this :

```jsx
const Pastas = () => {
    return <div style={{ backgroundColor: 'yellow', marginLeft: 15 }}>
        Best meal ever. Don't @ me.
    </div>
};
```
And you are not wrong! This is the way React gives us to style component. And now, you may have so much questions like : *'Okay but how about conditional style like mouse hover or focus ?' 'Should I really use magic numbers EVERYWHERE ?' 'What sauce does he use with his pastas ?'*
And I can't blame you for that, because, it's not possible, without escaping good ol CSS. You just have to pass a POJO to the `style` property of any HTML tag, React applies it (kind of magic isn't it ?)

*Can you get to your point ?*
YES i'll do it.

As React lets you to use any package through the Node universe, I identified for you 4 ways to style properly your components, with reusable, customizable and clean code.

# The 4 ways to the apocalypse
*(because you rock)*
### 1. Pretending to be Angular
*Oh really ? Why not using Angular then ?*
That's an other subject, I may discuss within an other article! But for now, it's time to benchmark!

Angular 2+ creates a shadow DOM for every nodes within its structure, so you'll be able to style your component one by one, using a CSS / SCSS file for each of them.

*That's not a Node package*
Can't you just be nice with me for once ?

Basically, you just have to import your stylesheet directly into your component file, and use class or even id, like this :

```css
.pastas {
    background-color: yellow;
    margin-right: 15px;
}
```
And then :
```jsx
import './pastas.css';

const Pastas = () => {
    return <div className="pastas">
        I use tomato, mushrooms and garlic on it.
    </div>
}
```
Surprisingly easy, but efficient. You retrieve full power of CSS (yes I swear, it is) applied to your now wonderful component.

Warning! Mocking Angular doesn't make a shadow DOM to appear by sorcery. You'll have to be sure you don't override some classes in an other file!

To prevent that, give you a strict class naming (the same you've been doing with your variables, *huh* ?) and build a sweet panel of reusable classes, in your root folder (In `styles/` for example) for buttons, inputs, tables... whatsoever.


### 2. The big three : Material, Bootstrap, Tailwind CSS
*I'm too lazy to write my own CSS framework*
Me too, and that's why some nice gentlemen, pour what we call...

*Some salt on your pastas ?*
**CSS Frameworks**. Please be focus.

There is A LOT of them out there, for different use cases, different paradigms, and different levels of liberty. I selected those I consider to be the big three, mainly used in the industry. If you're curious, check this [CSS census](https://cssauthor.com/css-frameworks/).

#### Material
Instigated by Google designers, [Material](https://material-ui.com/) has its own React package, providing plenty of already designed and reactive components, such as cards, modals, popovers, bread crumbs... Of course, it follows the Material Design guidelines for yourself, and you just have to focus on placing your UI elements together.

#### Bootstrap
You may know [Bootstrap](https://react-bootstrap.github.io/) if you have a Twitter account. Bootstrap main particularity is the use of a grid to place and size elements on screen.
Divided in twelve columns, any component can place its children wherever you want.
You may want to stack elements vertically, and Bootstrap rows are here for that.
There's also a React library to use Bootstrap component.

#### Tailwind CSS
At this point, I never have used [Tailwind CSS](https://tailwindcss.com/), but I will surely give it a try, as it seems to be a convenient way to use classes advantage, without being stuck behind a strong framework, hardly customizable.

To keep it simple, Tailwind CSS use a configuration file, and a classname based syntax to provide style to component. As it is framework agnostic, you don't have to worry, and learn once for all the syntax. I let you visit their website to see what's going on!

### 3. Stylesheets in JS (Styled-components, Emotion, Aphrodite)
*OK cool but my components don't fit with anticipated use cases of CSS Frameworks, what should I do ?*

CSS Frameworks may be too restrictive on their styles, and you might want your app doesn't look the same as every other ones.

Alternatively, you can find Node packages such as [style-components](https://www.npmjs.com/package/styled-components), [aphrodite](https://www.npmjs.com/package/aphrodite) or even [emotion](https://www.npmjs.com/package/emotion) that I particularly like.

Each of those API are different, but are known as CSS in JS (kind of) solutions. You can see them as an improvement of React API, as they simply create Component for you, or just use `className` property.

Again, I can't advise you more to write reusable code, by implementing atomic components, so you can add them where they're needed, and by updated at one place. for example, using emotion :

```jsx
// Button.js
import styled from '@emotion/styled';

export default styled.button({
   backgroundColor: 'yellow'
});
```
```jsx
// Component.js
import Button from './Button';

const Component = () => {
    return <Button>Buy Pastas</Button>
};
```

### 4. Context ?
*Great! What's the forth one ?*
There's no forth one.
*What ? Are you a liar ?*
No, let me get this straight.

What happens if I suddenly want to implement light and dark mode on my application ? How I'm supposed to implement my UI Components with that constraint ?
You can use **React Context**.

*What is React Context ?*
React Context is an amazing API to help developers to avoid props digging hell. If you have already written some components, you might have noticed that 3, 4, 5 or even 10 nested components is a pain when you want to pass a property from the original parent to the last child. That's props digging **hell**.

Fortunately, React developers take care of their users, and implement Context API.

Because this one is off-topic, I'll let you read the documentation.

*Can you provide a link at least ?*
[There you go.](https://reactjs.org/docs/context.html)

So, I want to implement a light/dark mode, I'll build it over my previous example :
```jsx
// AppContext.js
import { createContext, useContext } from 'react';

export const AppContext = createContext({ darkMode: false; });

export function useAppContext() {
    return useContext(Appcontext);
}

// App.js
import { AppContext } from './AppContext';
import Component from './Component';

export default () => {
    return <AppContext.Provider>
        <Component/>
    </AppContext.Provider>
}

// Component.js
import Button from './Button';

export default () => {
    return <Button>Buy Pastas</Button>
}

// Button.js
import { useAppContext } from './AppContext';
import styled from '@emotion/styled';

const StyledButton = styled.button({}, ({ darkMode }) => (
    {
        backgroundColor: darkMode ? 'black' : 'white';
        color: darkMode ? 'white' : 'black';
    }
);

export default ({ children }) => {
    const context = useAppContext(); // = { darkMode }

    return <StyledButton {...context}>
        { children }
    </StyledButton>
```

It will demand you to alter context values with some actions, but this is another story ;)

Although I used emotion in my example, the point here is that you are totally free to use any of the three first methods or packages combined with React Context!

# Conclusion, and personal thoughts
Before concluding, I hope you enjoyed this article, it's my first one on tech, first one in english, and first of a long dynasty of interesting articles, dedicated for students, self taught programmers or curious!

My point with this article is to show that React styles can be complicated to maintain, if you don't take it seriously, but so it is with databases, naming your variables, Angular... 

First method is the closest one to the old way of building websites, with only HTML, CSS and JS. Easy to maintain (especially with SCSS constants!) But not really suitable for React.

CSS Frameworks are good, if you don't want to spend time or money on your design, and focus on programming. I don't recommend them if you already have a mock-up, mostly if it doesn't look the same. Because some of them don't really let you customize shapes, colors, themes, it can be more time consuming implement one than do it yourself, from scratch.

CSS in JS packages are a good solution for this, but, you'll have to relearn them every time, as their API quite diverge.

So keep in mind this table :

Profile | solutions
--- | ---
Boomers | CSS / SCSS files
Noobs / Lazy devs | CSS Frameworks
Designer born | CSS in JS

Thank you for reading me, it has been a pleasure to write this down!

Stay safe, enjoy life, and happy coding!