In the last couple of weeks I looked at how to write a simple React application from scratch and how to test it. Today I looked at how to style it.
I have limited experience of styling websites (I have only used CSS and SASS in the past) so I googled the subject and found many, many solutions. I won’t walk you through all of them as this is not the subject of this post, I will only describe the solution I chose and how I set it up. If you would like to know more I highly recommend this post by Andrew Farmer, it is very informative and very well written.
So after reading up a bit about the different solutions I settled for CSS Modules together with SASS and here is how I set it up in my web application.
CSS Modules
I am new to CSS Modules but I really like the idea behind it:
A CSS Module is a CSS file in which all class names and animation names are scoped locally by default.
CSS classes are scoped globally by default so when your application grows it quickly becomes a nightmare to maintain and keep track of which classes are used where. With CSS modules (and the help of the tool that builds your code) you can import CSS files within a JavaScript file and CSS classes will automatically be scoped locally to that file (if I am not clear you will see in the setup section what I mean).
In the context of React this means that you can easily scope a CSS file to a React component. This goes really well with React philosophy where “componentisation” and isolation is a big deal. By default with React we already define both the structure (JSX) and logic (JavaScript) of a component so, by using CSS Modules, we are adding the style to the mix which completes the definition of the component. I think that’s really cool!
Obviously we are very far from the popular paradigm where the visualisation and logic of a UI component are split but with React we are very far from that anyway so if you are using React you are very likely onboard with that approach :)
CSS Modules Setup
If you have followed my previous posts, you’ll know that I am using webpack as a bundler. It is super easy to configure CSS modules with webpack. All you have to do is install the webpack loader css-loader
and its dependency style-loader
with npm and then add a new rule to webpack config for processing CSS files:
// webpack.config.js
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]'
}
}
]
}
With that configuration in place you can create CSS files and directly import them into React components:
// style.css
.myClass {
// ...
}
// component.js
import style from 'path/to/style.css';
render() {
return <div className={style.myClass}></div>
}
I find it pretty cool :)
SASS
Now, CSS is good but if you use it for a little while you’ll quickly understand why people use preprocessors like SASS. They allow you to write more maintanable style sheets thanks to features such as variables, import and nesting (and others). (If you are new to web development and don’t have much experience with (S)CSS start with bare CSS and see where it takes you, that way it will be easier to understand why I am adding yet another dependency).
Adding support to SASS with webpack is again super easy. All you have to do is install the loader sass-loader
(and its dependency node-sass
) with npm and add it to the list of loaders in webpack config:
// webpack.config.js
loaders: [
{
test: /\.scss$/, // changed from css to scss
use: [
...,
{
loader: 'sass-loader'
}
}
]
Be careful with the order of the loaders. The SASS loader should be last which means it will be processed first. I couldn’t find where it is specified in the documentation of webpack 2 but you can find some information in this stackoverflow post.
Jest and style sheets
If you have read my post about testing a React application you may know that I am using Jest as test runner. If you want to import (S)CSS files into React components you need to make a couple of more changes or Jest can’t even run your test anymore, it fails on the import of (S)CSS files.
What you need to do is described on Jest’s website here: add a dev npm dependency to identity-obj-proxy
and configure Jest to use it:
// jest.config.js
moduleNameMapper: {
'\\.(css|scss)$': 'identity-obj-proxy'
}
Obviously this will fix running your tests not the tests themselves!
And that’s it, I am all set for styling my React application. CSS Modules allows me to easily scope styles to a single component and SASS helps me to write nice maintainable CSS. If you want to see a simple example of how it works, you can check out the code here.