CSS Architecture
Here is a summary and guidelines for how we work with CSS for larger projects. I have tried to summarize both the reasons why and tips on how to do it.
The methods that have most influenced me over the years are
- Object Oriented CSS (OOCSS)
- Scalable and Modular Architecture for CSS (SMACSS)
- Block Element Modifier (BEM)
- ABEM
- Inverted Triangle CSS (ITCSS)
- Composition Utility Block Exception (CUBE CSS)
There are some things that I feel are very important:
- Make use of the cascade in Cascading Style Sheets, i.e. the rules are inherited down the structure. This means we can define and standardize many things in one place and then handle the exceptions separately.
- Maintain separation between CSS rules for the base rules, the layout and the components. Make sure that all components live in their own name space so that you know that you are not affecting anything else when you make changes to the component you are working with.
- Using as few selectors than necessary as it makes the code difficult to read and hard to understand. Do not link rules to specific HTML elements, but rather to classes so that the CSS rules don't become too dependent on the HTML code.
File structure
The structure we have used in recent years has been more or less intact, and has looked something like this:
scss
├── 1-settings.scss
├── 2-mixins.scss
├── 3-base.scss
├── 4-typography.scss
├── 5-layout.scss
├── 6-components.scss
├── print.scss
├── styleguide.scss
└── styles.scss
The numbers are there so you could easily see what order the files are read in, but as the project grows I feel that a partitioning more in line with the one in Sass Guidelines could be preferable, so now I'm imagining that we try with a folder structure instead.
I think that it will be somewhat clearer, and hopefully make the previous little diffuse line between what goes in layout.scss and what should be a block (or module as we called it before) easier to see.
scss
├──abstracts
│ ├── _mixins.scss
│ └── _variables.scss
├──base
│ ├── _reset.scss
│ ├── _base.scss
│ ├── _colors.scss
│ └── _typography.scss
├──blocks
│ ├── _divider.scss
│ ├── _entrance.scss
│ ├── _form.scss
│ ├── _heading.scss
│ ├── _logos.scss
...
│ └── _textcolumns.scss
├──elements
│ ├── _button.scss
│ ├── _contactperson.scss
│ └── _newsitem.scss
├──layout
│ ├── _grid.scss
│ ├── _header.scss
│ ├── _footer.scss
│ ├── _sidebar.scss
│ ├── _forms.scss
│ ├── _navigation.scss
├──pages
│ ├──_home.scss
│ ├──_contact.scss
├──vendors
│ ├── _hljs-nord.scss
│ └── _lity.scss
├── cp.scss // Craft CMS specific styles
├── print.scss // Print CSS
├── styleguide.scss // Styleguide
├── styles-ie8.scss // Desktop styles for old browsers
└── styles.scss
Some comments about the above;
- abstracts/ returns no code, but consists only of mixins and variables,
- base/ sets all base rules (HTML elements, colors and typography),
- blocks/ contains a file for each block (often 1:1 with a block in the CM system),
- elements/ are smaller building blocks than blocks and are often reused,
- layout/ takes care of the structure and layout (header, navigation, footer, etc.),
- pages/ contains rules that are tied to a specific page (new for this year),
- vendors/ are files from 3rd party libraries.
In general it is much like before, but hopefully the division into more files and the addition of pages/ will make it feel more natural where to place all the rules in a project.