KEMBAR78
Scalable CSS Architecture | PDF
Scalable CSS
Architecture
Artur Kot & Michał Pierzchała
Does it even exist?
Scalable CSS?
Maintainable CSS?
What we need
Modularity
Encapsulation
Predictability
What we have
What we really have
Cascade
Global namespace
Selectors specificity
Solution?
–David Heinemeier Hansson
“Convention over configuration”
Like in JavaScript
Embrace the good parts
Throw away the bad parts
Introducing
ITCSS
Inverted
Triangle
CSS
// main.scss
@import 'settings/*';
@import 'tools/*';
@import 'generic/*';
@import 'elements/*';
@import 'objects/*';
@import 'components/*';
@import 'trumps/*';
used with preprocessors
font definitions, colours, variables, etc.
1. Settings
2. Tools
globally used mixins and functions
normalising styles
box-sizing
3. Generic
4. Elements
bare HTML elements
reset lists, anchors, etc
simple & reusable
containers, grids, global animations, etc
5. Objects
6. Components
actual UI
CSS ❤ components
utilities and helper classes
visibility, alternative colours
override anything
7. Trumps
Some constraints
and recommendations
Groups order is crucial
(Inner order doesn’t matter)
Avoid “!important”
Use BEM
(Block Element Modifier)
<section class="c-component c-component--small">
<div class="c-component__bg"></div>
<h2 class="c-component__heading">A component!</h2>
<div class="c-component__child">
Lorem ipsum dolor sit amet, consectetur adipisicing elit
<button class="c-component__grandchild">inside</button>
</div>
</section>
• .[component-name]__[child]—[modifier]
• Remember that it’s on only a convention!
• Use 🍌 instead of __ or 🍓instead —

if you like
• Important: separation of the parent
element and its children.
• Be consistent.
JS hooks
• .js-[name]
• readonly to identify DOM elements for JS
• can’t be styled!
State classes
• .is-[name]
• .has-[name]
• should be used in favour of —modifiers
in case a component changes its state
after the page is loaded
• handy to use with JS
Resist from nesting
Temptation to target tags
.c-my-list li {
[item styles]
}
<ul>
<li>
<div class=”c-some-component-with-a-list”>
<ul>
<li>another list!</li>
<li>
and now you need to override
.c-my-list li with stronger selector...</li>
</ul>
</div>
</li>
</ul>
• You can’t predict the future. It’s possible that a
sneaky designer could design a nested list inside
your element. What to do then? More nesting. :)
• It, obviously, works but what if you’ve got identical
list but with divs instead of lis?
• Usually, nesting is like a domino effect: one
innocent nested selector results in dozen deeper
nested selectors. Avoid when possible.
You can’t entirely avoid
nesting. It’s impossible.
The goal is to minimise it and its side effects.
.c-component {
/* third-party code */
.super-slick-slider {
float: left !important;
}
/* state affects children */
&.is-open {
.c-component__grandchild {
display: block;
}
.c-component__inner {
display: flex;
}
.c-component__inner-most {
color: red;
}
}
}
.c-component {
/* state classes */
&.is-open,
&.has-popup {
display: block;
}
/* state pseudo-selectors */
&:hover,
&:focus,
&:nth-child(2n) {
border-bottom: 1px solid;
}
/* relationships */
+ &, ~ &, > &, * {
display: none;
}
}
Do Repeat Yourself
If it makes your life easier (usually does)
extra bytes will be squashed by gzip anyway…
Tricky MQ nesting
.c-component {
@media {
&.is-cos {
@media {
color: red;
}
}
}
}
.c-component {
color: blue;
@media {
color: red;
}
&.is-cos {
@media {
color: yellow;
}
}
}
BAD GOOD
Keep it tidy
Sync filenames with naming
/* _my-pretty-component.scss: */
.c-my-pretty-cmp {
color: brown;
}
/* _my-pretty-component.scss: */
.c-my-pretty-component {
color: blue;
}
BAD GOOD
Do not mix components with
each other
Not in stylesheets
/* Some time before */
.c-my-box {
width: 320px;
}
.c-my-box__inner {
padding: 20px;
background: blue;
.c-my-other-box {
color: white;
}
}
/* Few weeks later… */
.c-my-other-box {
color: white;
/* Doesn’t work :( */
&--pink {
color: pink;
}
}
Nor in the markup
<div class=”c-boxie c-footer”></div>
.c-boxie {
display: block;
}
.c-footer {
display: flex;
}
What display will it get?
Objects for reusability
Components for explicitness
Use objects for mixing with component!
<div class=”o-boxie c-footer”></div>
.o-boxie {
display: block;
}
Trumps are the new
“!important”
<h3 class=”o-title t-color-blue”>Heading</h3>
.o-title {
font-size: 12px;
color: red;
}
/* trumps/utilities.scss */
.t-color-blue {
color: blue;
}
It’s easier to maintain separated UI components
than ones mixed in HTML markup
Take it serious
It Just Works™
for CSS, SCSS, LESS
Piece of cake
Critical CSS or PRPL?
/* critical.index.scss */
@import 'settings/*';
@import ‘tools/*';
@import 'generic/*';
@import 'elements/*';
@import 'components/colorbar';
@import 'components/header';
@import 'components/hero';
Kinda
Use in existing
messy codebase?
Gradual adoption
Needs pre-/post-processor (sorry CSS 😞)
#create #strongest #selector {
@import 'settings/*';
@import 'tools/*';
@import 'generic/*';
@import 'elements/*';
@import 'objects/*';
@import 'components/*';
@import 'trumps/*';
}
With predefined and ready to use (or remove) components
Featured in Chisel,
our new project generator
ITCSS
IS
AWESOMER
Cool JS-based alternatives
CSS Modules
CSS in JS
Available with
Webpack & Browserify
Thank you.
Artur Kot & Michał Pierzchała

Scalable CSS Architecture