React Styling Techniques

LearnTogether
11 min readJan 20, 2023

--

Creating React applications is not just about creating components, composing components together and make sure that the logic works correctly. This is surely the biggest reason for using React, but another important part is styling those components to make them look good.

Consider for example a very simple application to add To Dos to a list, like this:

This application has no style applied at all. Would you use an application like this? Come on… No one will be going to like it! The look and feel of an application is very important for end users.

However, we can make it look much better ( even if it’s not going to win the best application look award ) adding some simple styling, like this:

How?

As React developers we have different techniques available to add styling to components, each one with its pros and cons:

  • CSS Classes
  • Inline styling
  • Styled Components
  • CSS Modules

Let’s dive deep in each one of these.

CSS Classes

The main benefit of using CSS classes to style React components is that it allows for a clear separation of concerns between the component’s structure and its presentation. Additionally, CSS classes can be reused across multiple components and can be easily overridden by later stylesheets.

When creating a component, you create two files: the *.js or *.jsx file with the definition of the component and its logic and the *.css file containing the classes for styling.

Let’s try to style a generic button component like the one shown in the image above:

We first create the files that will contain the definition and logic of the component and the style classes. By convention they are usually called the same.

Button component files

We then define the button component:

Button.js file content

As you can see in the image above, to use styles defined in the css file, we need to import the file and apply to the button element using the classNameproperty.

Wait a moment… Why are we using classNameand not classhere?

Good question! In React, the use of the className attribute instead of the classattribute is used to avoid conflicts with the class keyword in JavaScript. The classkeyword is a reserved word in JavaScript and is used to define a class in object-oriented programming.

By using classNameinstead of class, React ensures that there are no naming conflicts between the attribute used for styling and the keyword used for defining a class in JavaScript. This allows developers to use the classkeyword for defining components and other JavaScript classes without worrying about any potential naming conflicts with the CSS class.

You might ask now: what is the “button” string assigned to className? Where is it defined?

Obviously, it is defined inside the button.css file:

Button.css file content

I will not focus on the content of CSS classes in this post because it is not a tutorial on CSS, however all you need to know is that the “button” string assigned to the className attribute will apply all the styling properties defined inside the .button { … } object of the css file to the button element.

And what about the .button:* objects?

These are CSS selectors that target an element with the class of "button" when it is in a "focus" or “hover” or “active” state. The styling properties inside the classes will be applied as a intersection with those defined inside the .button class. The common properties are overwritten by those defined later in the file.

Pros

  • Styling using CSS classes, as we already said at the beginning of this paragraph, allows for a clear separation of concerns between the component’s structure and its presentation.
  • Additionally, CSS classes can be reused across multiple components and can be easily overridden by later stylesheets.

Cons

  • One potential downside of using CSS classes is that it can make it more difficult to track the flow of styles throughout a large application. Additionally, it can be challenging to dynamically update the styles of a component based on its state or props.
  • Another disadvantage of using CSS classes is that it can make it difficult to scope styles to a specific component, which can lead to conflicts with styles from other components.

Inline Styling

React inline styling refers to the practice of applying styles directly to a React component, rather than using CSS classes. This can be done using the style attribute on a JSX element, and passing an object containing CSS properties and values as the value of the attribute.

Let’s apply some inline styling to the Button component:

Button.js file with inline styling

As you can see, we are not using the CSS classes anymore, but we are defining a new style property assigning an object with all the style properties that we need. You might have noticed that the properties names are written camelCase and not kebab-case as inside a CSS file. That’s how style properties are written inline.

One benefit of using inline styling in React is that it allows for greater flexibility in terms of dynamic styling. Since the styles are directly tied to the component’s state or props, it’s easy to update the styles of a component based on changes to the component’s state or props.

Let’s say for example that we want to disable the button when a notActive prop is received in input and we want to change the background color to light gray to show the user it is disabled. We can easily do it in this way:

Changing button background color when disabled

As you can see, we can simply use a ternary operator applied to the style props value to get the desired result.

However, adding a lot of styling to a component will make the component a real mess and will reduce the readability. That’s why I personally prefer using CSS classes.

Of course, we can apply both the className and the style prop together on the same element. They are not mutually exclusive.

When both the className and style props are used together on a component, the inline styles take precedence over the styles defined in the CSS class. This allows you to override specific styles for a particular component, while still maintaining the overall design and layout defined in the CSS class.

Pros

  • It allows for greater flexibility in terms of dynamic styling.
  • It makes it easy to scope styles to a specific component, which can help to avoid conflicts with styles from other components.

Cons

  • It can make the component’s code less readable and harder to maintain, as the styles are mixed in with the component’s logic rather than being separated into a separate CSS file.
  • Additionally, inline styles do not have the ability to use CSS cascading and specificity, which can lead to unexpected behavior when multiple styles are applied to the same element.

Styled Components

As we emphasized multiple times, using CSS classes imported as *.css files does not result in those styles being scoped to that component only. That means that if we have any other element anywhere else in the DOM that has the same selector name, the styles would be affected as we will incur into collision issues.

Of course, especially in larger projects, potentially with a lot of developers working on the same code, it could happen that a name is used twice.

Using styled components is one approach to scope components styles and avoid this problem.

React Styled Components is an external library that allows you to write CSS styles in JavaScript, which are then applied to React components. This approach combines the best of both worlds by allowing you to use the power and flexibility of JavaScript to write styles, while still keeping the styles scoped to individual components.

To get started, we need to install the styled components package into our project through the command:

npm install --save styled-components

How do we use this package?

The official page https://styled-components.com contains all the documentation to learn how to use the library.

Now, let’s refactor our button component to use styled-components library:

We first need to import the styled object from the styled-components library.

Then we can define the Button component using this weird syntax:

const Button = styled.button` ... `;

Chances are you have never seen this syntax before…

This is called a Tagged Template Literal. It’s a default JS feature ( not specific to react and can be used in any JS project ). What does it do? you may ask…

It defines a method called button on the styled object. It’s just a special kind of method that instead of be called using parenthesis it’s called using backticks ( ALT + 96 on Windows ).

Everything we pass inside the backticks is passed to the button method in a special way. But now I don’t want to waste you time going deeper on this specific argument, so let’s focus our attention on the styling again.

All we need to know is that the button method will return a new button component with all the styles provided between the backticks applied. The styled object has methods for all the HTML elements.

We don’t need to specify anymore selector names. And for pseudo selectors like focus active and so on, we can use the & to refer to the component it belongs.

Now, we can use our styled Button component everywhere we want as any other component:

import Button from "./Button";

const OtherComponent = () => {
...
return <Button />;
}

Add Dynamic Styling to Styled Components

Styled Components make also easy to pass props and state to your styles, which can allow for dynamic styling based on the component’s current state.

Let’s say for example that we want to change the color and background-color properties of our button dynamically, passing props to the component. We can do it like this:

Pros

  • Scoped styling: Styles are scoped to the component, which helps to prevent unintended style leaks and makes it easy to see what styles are being applied to a specific component.
  • Dynamic styling: It’s easy to pass props and state to your styles, which can allow for dynamic styling based on the component’s current state.
  • Reusability: You can create a component that can be used in multiple places and can be composed with other components to create new components.
  • Easy to read and maintain: Styles are written in JavaScript and are close to the component they style, which can make it easier to understand and maintain the code.
  • Server-side rendering support: It can be used in server-side rendering environments and it helps to avoid the problems of flash of unstyled content (FOUC).

Cons

  • Learning curve: It requires a different way of thinking and writing styles, so it might take some time to get used to it.
  • Additional library: It requires an additional library to be added to the project, which can add complexity and an extra dependency.
  • Size: It can increase the bundle size, as the CSS styles are included in the JavaScript bundle.
  • Specificity issues: Because of the nature of inline styles, it might be harder to control the specificity of the styles, this means that it can be harder to override styles from parent components.

Overall, React Styled Components is a powerful tool for styling React components, but it’s important to consider the specific needs of your project and the trade-offs that come with using it.

CSS Modules

If we want to stick to the CSS approach, keeping the separation between the logic and the style of a component, like I personally prefer, and have scoped styles at the same time, we can choose CSS Modules.

CSS Modules is unfortunately available only in projects configured to support it, because it needs a code transformation that comes in action before the code runs in the browser.

The good thing is that all React projects created with create-react-app are already configured to support CSS Modules.

Using CSS Modules is super super simple. All we have to do is to define our CSS classes and selectors as usual in a separate .css file. This time though the file has to be named as:

componentname.module.css

What really changes is inside the .js file. The import is slightly different.

Let’s apply CSS Modules to our Button component and see how it works:

Rename .css file to componentname.module.css
Button.module.css content
Button.js using CSS Modules

As you can see, it is very simple to use CSS Modules. All we need to do is to import an object with the name we prefer ( in this case we called it styles ) and access the style class name as a property of the object.

That’s it! Now we have scoped styles and separation of logic and style at the same time!

Pros

  • Scoping: CSS Modules automatically scope class names to a specific component, which helps to prevent naming conflicts and makes it easier to reason about the CSS in your application.
  • Reusability: You can import and reuse CSS classes across different components, which can make it easier to maintain your styles.
  • Dynamic styling: CSS Modules allow you to use JavaScript to generate class names, which can be useful for implementing dynamic styles.

Cons

  • Additional setup: Using CSS Modules requires some additional setup and configuration, which can be time-consuming.
  • Limited browser support: CSS Modules currently have limited browser support, which means you may need to use a tool like Babel to transpile your code.
  • Limited tooling: There is limited tooling available for working with CSS Modules, which can make it difficult to debug and troubleshoot issues.

Bonus

When using scoped styled for our React components, by using the styled-components approach or the CSS Modules, when inspecting the DOM in the browser you will see that the name of the classes assigned to our components will contain a random weird string. That is generated purposely to make that class unique and prevent collision.

For example, let’s inspect our Button component when using the CSS Modules approach, we’ll see something like that:

Button unique class name in DOM

The class name contains the name of our component, plus a unique string part appended.

--

--

LearnTogether
LearnTogether

Written by LearnTogether

I'm a passionate Computer Engineer interested in a lot of fields of science and technology. Currently working as a React software engineer for a big company.

No responses yet