You shouldn’t organise CSS by splitting it into separate files any more than you should organise a pane of glass by dropping it on a concrete floor.
Things To Avoid When Writing CSS
Heydon
64162

How to organize CSS in multiple files

An alternative to not splitting your CSS into multiple files, is to learn how to properly organize your CSS in multiple files.

When done properly, this brings many advantages:

  • Your CSS files will be small and easy to navigate. No need to scroll up and down, and your text editor will love you.
  • Your CSS files will be more modular.
  • Your CSS selectors won’t cascade or conflict with other selectors.
  • Your style will be more predictable, even though you can’t predict which file gets included first.

Components

First, you need to think of your page as composed of multiple components. Things that you should keep in mind:

  • A component should be self-contained. This means by using the component, it should include all necessary markup, behavior and styling, in one package.
  • A component should be able to decide for itself how it will look and behave, given the markup.
  • A component should be composable and reusable.
  • A component’s style and behavior should (ideally) not be affected by its surrounding.

There are three parts to solve: Markup, Behavior, and Styling.


Markup and Behavior: React

One way to achieve this is by using and thinking in React.

// MusicPlayerUI.js
class MusicPlayerUI extends Component {
render () {
return (
<div>
<h1>Music Player</h1>
<p>{this.props.currentSong}</p>
<Playlist
songs={this.props.songs}
currentSong={this.props.currentSong}
/>
</div>
)
}
}

When you write idiomatic React code (with stateless components), the only things that can affect the markup and behavior is solely the properties passed to it.

Quoting Heydon:
Javascript function definitions can go either before or after where they are called and HTML modules can be inserted wherever you see fit in the flow of the document.

And it should be the same with styling, by making styles from different files not interfere with each other.


Styling: BEM

One way is to adopt BEM (Block, Element, Modifier) methodology.

BEM is a methodology for creating reusable and independent “blocks” and compose them in a web page. That’s just what we need!

We map them to React component like this:

  • A React component = A BEM Block
  • A React element owned by a component = A BEM element

With that in mind, we follow the BEM rules for assigning class names to HTML elements, which means that every element’s class name must be prefixed by the owning block’s name.

// MusicPlayerUI.js
class MusicPlayerUI extends Component {
render () {
return (
<div className='MusicPlayerUI'>
<h1 className='MusicPlayerUIのtitle'>Music Player</h1>
<p className='MusicPlayerUIのcurrentSong'>
{this.props.currentSong}
</p>
<div className='MusicPlayerUIのplaylist'>
<Playlist
songs={this.props.songs}
currentSong={this.props.currentSong}
/>
</div>
</div>
)
}
}

(Note that I break the naming conventions a bit. I use PascalCase for block name to match with React class name. I use camelCase for element name so it’s a valid JavaScript identifier. I use の as a delimiter because this character by itself indicates possession and thus is more meaningful than __.)

You can see that now every element in your component has a class name beginning with MusicPlayerUI, and outside this component, no one else will use it.

Now there’s no more conflict, no more CSS cascade! That means it doesn’t matter anymore in which order I put the CSS file.

I put the CSS file alongside the JSX file in the same folder, which shows that the CSS file and the JSX file had an intimate relationship:

/* MusicPlayerUI.css */
.MusicPlayerUI {
font: 1.5rem var(--main-font);
}
.MusicPlayerUIのtitle {
color: #8b8685;
}
.MusicPlayerUIのcurrentSong {
color: #353433;
}
.MusicPlayerUIのplaylist {
max-width: 42rem;
margin: 1rem auto 0;
}

Now I can just concatenate these CSS files, without having to worry which files gets inserted first, because they don’t interfere with each other.

You know your CSS is maintainable
when you can include your CSS files in any order
and that has no effect on anything.

You know, I just do this:

@import "global.css";
@import "components/**/*.css";

Even though I put global.css (base style) first, the rules in that file should have very low specificity — to the point that even the most specific rule in global.css will never be as specific as the least specific rule in any other CSS file.


Styling: CSS Modules

Another interesting technique is to use CSS modules. It’s new and shiny! There’s another article that explains it already, so I won’t dive deep into it, but it follows the same principle: Encapsulate the boundary of your stylesheet.


Conclusions

Even though I gave only markup example for React, but you should be able to do it with any library that provides DOM abstraction.

It could be React. It could be Angular directives. It could be Polymer elements or just Web Component elements. It could be Jade mixins, Rails view helpers, or even a simple function that generates markup.

Although you write HTML, you don’t compose them. You abstract them in a component which encapsulates all the necessary markup, behavior, and style.

Now they are autonomous. Now they are reusable. Now they are composable.

Then you compose these components.

Once I develop web applications this way, I never looked back.

I can confidently change any component without fear of breaking any other component, because they all work on its own.