Creating a sane frontend: CSS file structure

This is a follow on from my thoughts on a robust CSS methodology for big projects, and will be a more actionable post, based on the decisions I’ve made thus far.

How you sort your code is definitely one of the most important considerations when starting any project. And especially with CSS, because the logical divides aren’t as obvious as they might be with HTML or other languages.

Traditionally to reduce http requests, css is pushed into one big monolith of a file. Thankfully between scss and the Rails asset pipeline we’re using on this project, that’s been largely averted. Nevermind the fact that with http2 there is a compelling argument for many smaller files over one big one.

With that in mind, here is what I believe is an efficient breakdown of CSS files and what each one should contain.


Here’s the basic scss structure, in the assets/stylesheets folder. Please bear in mind that this is built with our current project in mind, and makes a fair amount of allowance for maintaining legacy and new code within one project. If you’re just starting a project from scratch, you should be able to eliminate the /legacy folder as well as /overrides/_defence.scss.

  • /libraries
  • /defaults
  • /components
  • /overrides
  • /legacy
  • application.scss


All third-party libraries go here. In our current project that includes Bootstrap, Font Awesome and some Bootstrap plugins.


SCSS files only and handles all the site defaults. This would include setting up color and typography defaults, media mixins, helpers, etc.

These fall into the following files:

  • _colors.scss – holds all color variable names. Both general defaults as well as for all themes.
  • _fonts.scss – just holds any external font inclusions. I find it simpler to separate this from the typography mixins & defaults below.
  • _typography.scss – contains all font stacks, font-weight and letter spacing sass maps (more on this in another post).
  • _helpers.scss – all helper/utility mixins & classes – like sticky,  left/right align, etc
  • _media.scss – media query mixin(s). more on this in another post.


This will hold all component styling. Components are currently divided into 2 primary types:

  1. Simple Components
  2. Complex Components

Depending on the number of files, it might be worth having an _index.scss in each root folder that includes all the components there, so that the application.scss file (see below) doesn’t get too cluttered. I don’t see this really being a requirement with any of the other folders really, unless maybe there are a large number of 3rd-party files in /libraries.

Common Components

These would be all general components not specific to a template file and are usually simple components.

Examples would be buttons, icons, logos, lists, general typography, etc.

All common templates should be in the common folder, ie: ../components/common and saved with the component name, eg _button.scss or _headers.scss

Complex (or Template) Components

Complex components would be any component that has a single purpose made up of any number of common and complex components.

Ideally, all complex component styling should be strongly coupled to the template component itself. The best way to achieve this would be to have the CSS in the same folder or even file as the rest of the component code. I, personally prefer the separation of each code type to its own file as much as possible.

With the rails asset management, as far as I know, all CSS needs to be in the stylesheets folder, so to ensure tight coupling, the folder structure for the SCSS file needs to reflect that of the actual component, even though they’re physically in different places in the codebase.

Additionally, our code base is broken into template based views, that may contain one or many complex components, so because of that I’ve selected to name the folder containing all the complex components ‘templates‘ instead of ‘complex‘ but feel free to use the naming convention that you feel best reflects your project structure.

Naming convention: all component-specific CSS should be in its own file and follow the same folder structure as the component it is styling.

So if a component file is in :


the SCSS file would be:



The overrides folder will hold 3 main file types.

  1. Any third-party library changes
  2. _defence.scss
  3. _shame.scss

Library Overrides

There are times that there’s some weird code in a 3rd-party library that needs to be squished or changed. Rather than messing about with the library code (which is never a good idea), rather create a file and override it here.

Follow the following naming convention append ‘-mod’ to the library you’re changing:

E.g. If you wanted to override some styling in bootstrap-toggle you would create a file called: bootstrap-toggle-mod.

In defence of shame.

defence.css and shame.css – both come from some tips I got from this fantastic video/slideshow by Harry Roberts on refactoring css. I highly recommend you have a watch.


This file is specifically used when one needs to override the old site styling (which we inherited) before writing new styling on top of it. The reason for this is so that the new css is clean and remains unaffected by any old code that’s still hanging about. In all honesty, this has had limited use so far, and I find it simpler to, where possible, rather remove the old css. However I’m sure there will be cases where this won’t be possible (because of reliance on old styling in other parts of the app that we haven’t yet addressed), and that’s why I’m keeping it around. The idea is to scrap it as soon as we move entirely away from the old css files.


Similar to _defence.scss, shame is there for all the quick and dirty and old-browser tricks you might need to do but hate doing and really don’t want to muddle your squeaky clean CSS with – all that crabby (!important, etc) code goes here. It’s named in a way that would hopefully push any self-respecting dev to use it as a last resort – it always should be – but sometimes you need a place to hide the shitty code, and making provision for it means that you can rest easy knowing everything else is sexy af.


This is where all the legacy css would go. I don’t really want to talk about it.


This bad boy ties all the other things together and is a staple of the Rails asset flow. It basically serves as an index of all of the above files.

As a general rule, here’s how the files are imported:

  • All library files, with the css reset loaded first.
  • all.css – all legacy css would go here.
  • Any library overrides in the /overrides folder
  • overrides/defence – a fat layer of normalising css on top of the old inherited code.
  • All /default files.
  • All /components/common
  • All /components/templates/…
  • overrides/shame – sits on top and overrides everything.


Wow, that was a lot more than I expected when starting out with this.. hehe.

Thoughts on robust CSS methodologies for big projects.

There has already been a lot said about ways to handle CSS in growing projects and as frontend development has been my career nomenclature for many years now it is something I’ve mulled over and had to practically implement more than just a few times already.

I think the best solution I’ve found, is react-css-modules. Unfortunately, it is rather deeply tied into the tech stack that it is built on.

Why I like ReactCSSModules

  1. All CSS is strongly coupled to the components it describes.
  2. Presuming 100% adherance to the methodology, there is no chance of unwanted styles creeping in.
  3. Because each file only contains the css for the component it is describing, it’s very easy to find where to make changes (or fix bugs)
  4. The possible downsides like code repetition can be averted with a few good tooling options (ala PostCSS) and gzipping the output.
  5. Closely follows the standard CSS/HTML implementation (implementation into the HTML code was as simple as using ‘styleName’ instead of ‘class’).
  6. Ease of use – there is very limited ‘brain-drain’ or cognitive load with no need for naming conventions (I’ve found naming components takes up a considerable amount of mental effort as well as time when building out any new components) or having to worry that my carefully named component conflicts with some other component built 6 months before.

This was the case with the previous project we worked on at Ekaya, where we were able to build everything mostly from the ground up, using a Node & React stack and (once we got it all setup and running) it was glorious.

when you can’t use the perfect stack…

However, our latest project is an inherited Rails behemoth which we’re now both refreshing the styling and building in new functionality and moving away from the standard Bootstrap-based component structure, which means that we will need to start relying on our own naming conventions & ‘framework’ going forward.

I had a look at the non-react version of cssModules, but it messes with the way CSS is added to the DOM a little too much for my liking, which has pushed me back to having to attempt to build out as much of the happy-sauce found in cssModules, but manually and ideally in a way that makes it easy for new devs to quickly get up and running.

What I need in a solution

As I consider a solution, I’m looking to ensure:

  • a solid naming convention – I’m leaning towards something BEM-inspired
  • the separation of CSS into SCSS files by component to reflect the code base as closely as possible
  • sane defaults to reduce cognitive load and ensure consistent styling across the app.
  • A balance between class names as style descriptors and class names as component definitions (think class=”button button-blue button-outline button-large button-no-drop-shadow” (Bootsrap-esque) vs class=”widget–stats–button-outline” (more BEM-like) )

And there are a bunch of things that will need some deeper consideration, like

  • the nature of the project means we need to handle theming,
  • Would need to work with the inherited Bootstrap framework where possible (Grid system, etc) and
  • Finding a way not to have it all devolve into css-soup in a month or two (or as soon as there’s more than just me working on the codebase).

That’s it (for now)

That’s as far as I’ve gotten in my thinking on it (well in a way that is communicatable), but this is definitely an ongoing journey, which I’ll keep posting on until I have some sort of usable solution…

Feel free to weigh in if you have any thoughts <3