CSS Architecture — Folders & Files Structure

CSS Architecture — Part 2

Elad Shechter
8 min readJun 3, 2019

One of the essential things in every programming language is architecture, i.e., how the code is divided into file and folders. Somehow, however, CSS was left in the corner, and many developers don’t take the time to plan its architecture properly.

Before we start, some words on who I am:
My name is Elad Shechter and I’ve been developer for 13 years. For the last nine years, my day job is CSS/HTML Architecture.

In this post, I will show my guidelines in defining the CSS architecture, based on my many years of experience.

Side note: nowadays, a proper project uses a CSS preprocessor. In this post, I will be using the SASS preprocessor.

I divided this post into sections corresponding to the main elements of my architecture. My projects’ basic structure consists of a configuration layer and a content layer; the content layer is made up of other layers, the main one being the partials layer. This layer contains elements, components, sequences, and sometimes entities.

Basic Structure

I build my projects using two main files: the configuration file and the content styles file. The configuration file, called _config.scss , references all configuration files, and the content styles file, called _local.scss references all folders & files inside the local folder.

Besides being useful for the separation of concerns, this division will help you build a CSS architecture even when you have more than one website. Architecture for multiple sites is something I will discuss in my next post! You are welcome to follow me on twitter or medium to get updated when it’s published.

The main.scss connects both those files.

Main SASS Folder:

sass/ 
|
|- framework/
|- _config.scss
|- _local.scss
|- main.scss

main.scss file:

@import "config";
@import "local";

Configuration Layer (_config.scss)

The configuration layer is where I define all my SASS/CSS variables and some main root definitions.

To achieve a well-constructed project, I divide the configuration into smaller files according to their logical function.

Example:

  • CDN variables
  • Colors Variables
  • Responsive Design Breakpoints Variables
  • Language Support Variables
  • Main Z-Index layers
  • Other variables which don’t fit into the other parts.

I can’t accommodate all types of configuration, so if you see that your project has more functions, break them into more files.

framework/
|
|- config/
| |- _common.scss
| |- _cdn.scss
| |- _colors.scss
| |- _directions.scss
| |- _breakpoints.scss
| |- _layers.scss
|
|- local/
| |- Folders and Files
|
|- _config.scss
|- _local.scss
|- main.scss

Content Layer (_local.scss)

The content layer, located in _local.scss, is your styles' main content, i.e., this is where you should place all your styles.
This layer should include SASS mixins, CSS Normalize & CSS Resets, fonts, icons, CSS utility classes, common grids, and partials.

framework/
|
|- config/
| |- config files
|
|- local/
| |- _mixins.scss
| |- _resets.scss // normalize + resets + typography
| |- _fonts.scss
| |- _icons.scss // font icons/SVG icons
| |- _utilities.scss
| |- _grids.scss // common layouts
| |- _partials.scss // elements/components/entities/pages
|
|- _config.scss
|- _local.scss
|- main.scss

The content layer contains styles belonging to many different logical parts, such as resets, fonts, icons, etc. Even if we divide it into the minimum number of files, we could get to 7 or 8 files. In some cases, it’s better to divide them into even smaller parts so that the .sass files never get too big, i.e., not more than 50 rows if you write your style definitions in one row per selector, and no more than 200 rows if each definition takes a whole row.

Here are some examples:

Mixins layer

Folder view:

framework/
|
|- local/
|- |- mixins/
| | |- _trim.scss
| | |- _rotation.scss
| | |- _prevent-select.scss
| | |- _break-word.scss
| | |- _scrollbar.scss
| | |- _screen-reader.scss
| |- _mixins.scss

_mixins.scss:

@import "mixins/trim";
@import "mixins/rotation";
@import "mixins/prevent-select";
@import "mixins/break-word";
@import "mixins/scrollbar";
@import "mixins/screen-reader";

Reset Layer

Folder view:

framework/
|
|- local/
|- |- resets/
| | |- _normalize.scss
| | |- _reset.local.scss
| | |- _typography.scss
| |- _resets.scss

_resets.scss

/*resets*/
@import "resets/normalize";
@import "resets/reset.local";
@import "resets/typography";

I Wrote a more detailed post on CSS Reset & CSS normalize — “CSS Normalize or CSS Reset?!”

Partials Layer (_partials.scss)

The _partials.scss is one of the main files in the _local.scss layer. It is where I locate all the components, whether they're small, medium, or big.

framework/
|
|- config/
| |- config files
|
|- local/
| ...
| |- _partials.scss // elements/components/entities/pages
|
|- _config.scss
|- _local.scss
|- main.scss

Because the partials layer is so big, I divide it into smaller logical inner layers, somewhere between to 3–5 files. The number of files can change between projects or at your discretion.

In this layer, the order of the @imports is critical because there are sometimes dependencies between basic layers and more complex components layers. Since the sequence is so important, I give every main layer a prefix number which represents its order of importance, from most generic to most specific.

framework/
|
|- local/
| |- partials/
| |- 1-elements/
| |- 2-components/
| |- 3-sequences/
| |- 4-entities/
| |- 5-pages/
| |- _1-elements.scss
| |- _2-components.scss
| |- _3-sequences.scss
| |- _4-entities.scss
| |- _5-pages.scss
| |- _partials.scss // elements/components/entities/pages

_partials.scss:

// from most generic to specific
@import "partials/1-elements";
@import "partials/2-components";
@import "partials/3-sequences";
@import "partials/4-entities";
@import "partials/5-pages";

How to determine where in the _partials.scss layer to put your style

Before placing anything in layers, remember that icons, common grids, fonts, and utility classes don’t belong in this layer! They reside in the layers before.

The definitions in this layer are divided into several types:

Elements- are the basic components of the web. This layer is where I put all the base styles, such as styles for common-link, common-button, common titles, forms styles, tabs, and every basic style that is small and can stand on its own.

It’s important to put every part in its own file. This way, you can easily control these base styles, without worrying that they might affect other parts of the CSS when you want to change those styles.

Example for _1-elements.scss file (part of _partials.scss)

/*common*/
@import "1-elements/common-links";
@import "1-elements/titles";
@import "1-elements/common-popup";
/*Buttons*/
@import "1-elements/common-button";
@import "1-elements/button-icon";
@import "1-elements/button-tabs";
@import "1-elements/tooltip-button";
/*forms*/
@import "1-elements/select-row";
@import "1-elements/forms";
@import "1-elements/search";
@import "1-elements/search-result";
/*tables*/
@import "1-elements/common-table";
@import "1-elements/table-summary";
@import "1-elements/table-links";
@import "1-elements/table-filtering";
/*others*/
@import "1-elements/system-alerts";
......... a lot more...

(Break everything (!) into small parts)

Components- are bigger partials. I use them for parts like main-header, main-footer, navigation, breadcrumbs, etc..

The Components’ HTML can contain Elements partials inside them. Sometimes the component will not affect this Element, and occasionally it will, according to your needs: When you want an existing element to behave differently in a component, you must include the component after defining the element so that in that component, the element will get its new specific definitions. As I wrote before, when I divide the _partials.scss layer into those main layers, I add prefix numbers at the beginning of each layer to indicate that there are dependencies between those layers. In this way, we ensure that cascading styles work correctly.

// from most generic to specific
@import "partials/1-elements";
@import "partials/2-components";
@import "partials/3-sequences";
@import "partials/4-entities";
@import "partials/5-pages";

Sequences- are of a list of articles. They usually appear on news sites, blogs, or any site that has a list of reading items. Sequences may have partials made of elements or components inside it, similar to elements in components that we talked about before.

Entities and Pages partials

Many projects have partials which use an element or a component or a sequence in an un-generic way. For example, in a project that has a generic pop-up, there might be a datepicker that uses a pop-up too, but the datepicker pop-up could differ in some ways from the generic one. In these cases, I use one of two approaches: entities or pages.

Entities- I use these when using elements, components, or sequences whose styles aren’t 100% the same. I add another class name to the element, component, or sequence — in addition to its element, component, or sequence class — and that enables me to apply different styles to it. The class name starts with an ‘e-’ to represent an entity,

My rule of thumb is that you can only add one entity to an element/component/sequence. If there is another case of such an entity differing from the generic one, it is better to create another entity instead!

Example:

<section class="common-popup e-datepicker-popup"> </section>

Other than that, you can add as many CSS utility classes as you want.

<section class="common-popup e-datepicker-popup u-hide"> </section>

Pages- every page on your website can be an entity. In this case, the class should be added to the body element or to the main element that wraps everything. The class name should start with a “p-” for example: “p-homepage” or “p-news” etc.…

This class can affect every element, component, sequence, or entity on the page.

This approach is better avoided if you can, but sometimes in real life you have cases like this.

<body class="p-homepage"></body>

To Summarize

In this post, I showed my CSS Architecture approach for folders and files, based on many things I’ve learned over the years.
This post is the second in a series of articles I’m writing about CSS Architecture, and I will share a new post every few weeks.

If this interests you, you’re welcome to follow me on twitter or medium.

My CSS Architecture Series:

  1. Normalize CSS or CSS Reset?!
  2. CSS Architecture — Folders & Files Structure
  3. CSS Architecture for Multiple Websites
  4. Naming Things in CSS

Final Words

That’s all,
I hope you’ve enjoyed this article and learned from my experience.
If you like this post, I would appreciate applause and sharing :-)

More of my CSS posts:
New CSS Logical Properties!
CSS Position Sticky — How It Really Works!

Who Am I?
I am Elad Shechter, a Web Developer specializing in CSS & HTML design and architecture. I work at Investing.com.

You can contact or follow me:
My Twitter
Facebook
LinkedIn

You Can find me in my Facebook groups:
CSS Masters
CSS Masters Israel

--

--