Note on Modern CSS Development
Note on Modern CSS Development

Note on Modern CSS Development

CSS Modules
CSS preprocessors
May 3, 2024

CSS-in-JS Library

Using CSS-in-JS libraries such as styled-components or emotion allows you to write CSS directly within JavaScript code. These libraries provide scoped and dynamic styling, meaning styles are applied to components in a way that won't affect other elements and can be adjusted based on component state or props.
Here are some examples of how to use styled-components and emotion, two popular CSS-in-JS libraries:
// =========== Styled-components Example =========== import styled from 'styled-components'; const Button = styled.button` background: ${props => props.primary ? 'palevioletred' : 'white'}; color: ${props => props.primary ? 'white' : 'palevioletred'}; font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; `; // Then you can use it as a React component function App() { return ( <div> <Button primary>Primary Button</Button> <Button>Default Button</Button> </div> ); } // =========== Emotion Example =========== /** @jsxImportSource @emotion/react */ import { css } from '@emotion/react' const color = 'darkgreen' function App() { return ( <div css={css` background-color: hotpink; &:hover { color: ${color}; } `} > Hover to change color. </div> ) }
In both examples, the CSS is scoped to the specific component, and you can use JavaScript to dynamically change styles based on props or state.

CSS Modules with CSS-in-JS library? Nah

While both CSS-in-JS libraries and CSS Modules aim to solve the problem of CSS scope and prevent style conflicts, they do it in different ways. CSS Modules is a CSS file in which all class and animation names are scoped locally by default. It helps you to modularize your CSS code and avoid class name collisions by generating unique class names for each component. On the other hand, CSS-in-JS libraries like styled-components or emotion allow you to write CSS directly within your JavaScript code. That CSS is tied directly to your React components, providing not just local scope, but also enabling dynamic styling based on component state, props or global theme. So while both are useful for managing styles in component-based architectures, they represent different approaches and offer different features.

CSS Preprocessors with CSS-in-JS library? Nah

While you can technically use a CSS preprocessor like Sass alongside a CSS-in-JS library, it's not very common or typically necessary. CSS-in-JS libraries like styled-components and emotion already provide many of the features that Sass offers such as variables, nesting, and mixins. Additionally, these libraries allow you to leverage the full power of JavaScript in your styles, which can often go above and beyond what preprocessors like Sass can do. Therefore, using a CSS preprocessor along with a CSS-in-JS library might lead to unnecessary complexity in your project. It's usually best to choose one approach based on your project's needs and stick with it for consistency.

CSS Preprocessors with CSS Modules? Definitely!

Using CSS preprocessors like Sass (Syntactically Awesome Style Sheets) or LESS with CSS Modules is quite common and can be very beneficial. CSS Modules provide the local scope for the CSS classes to avoid naming collisions, while preprocessors like Sass add useful features that don't exist in pure CSS.
Here's an example of how you might use Sass with CSS Modules in a React project:
// Button.module.scss .button { background-color: $primary-color; &:hover { background-color: darken($primary-color, 10%); } } // Button.js import React from 'react'; import styles from './Button.module.scss'; function Button() { return ( <button className={styles.button}>Click me</button> ); }
In the above example, the Button.module.scss file defines styles using Sass features like variables and functions. These styles are then imported into the Button.js file as a styles object, where they can be applied to elements as class names.

BEM not required

We don’t need to use BEM when we’re making a CSS module. This is for two reasons:
  1. Easy parsing – Code like type.display is just as legible for developers as the BEM-y .font-size__serif--large. Likely even easier to mentally parse when the BEM selectors get long.
  1. Local scope – Say we have a class like .big in one module where it changes the font-size. In another we use the exact same class .big that increases padding and font-size in a different amount. It simply doesn’t matter! They won’t conflict, because the styles are scoped very deliberately. Even if a module imports both stylesheets, then it has a custom name which our build process makes specifically for that class. In other words, specificity issues disappear with CSS Modules.

Further Reading - CSS Methodologies

In this article, the author discusses these CSS methodologies:
  • Object-Oriented CSS (OOCSS)
  • Block, Element, Modifier (BEM)
  • Scalable and Modular Architecture for CSS (SMACSS)
  • Systematic CSS


css-modulesUpdated May 4, 2024