Maintaining CSS

Keenan Bailles

Atomic CSS, BEM, Suit CSS, SMACSS, OOCSS, Enduring CSS, Systematic CSS, PostCSS, DoCSSa, Constraint CSS, AMCSS

“Writing CSS is easy. Maintaining CSS is hard.”

Talking Points

  1. Two Competing Problems
  2. Everyone Agrees on These
  3. Suggested Conventions
  4. CSS Tips

Two Competing Problems

You can either make things

DRY

or

Reduce Coupling

DRY

  • Reduced size of CSS (both in lines and size)
  • No need to worry about HTML structure
  • Classes highly reusable

DRY

  • Very difficult to remove styles
  • High barrier to entry. Does the class I need already exist? What classes are available to me?

DRY

Example using Atomic CSS:


@std-margin: 16px;

.mt-1 { margin-top: @std-margin; }
.mr-1 { margin-right: @std-margin; }
.mt-2 { margin-top: 2*@std-margin; }

.ov-h { overflow: hidden; }

.d-b {  display: block; }

.va-m {  vertical-align: middle; }

.fl-st { float: @float-start; }
.fl-nd { float: @float-end; }

.fw-b {  font-weight: bold; }

.fs-i {  font-style: italic; }

.headshot {
	width: @headshot-dimension;
}
						

Reduce Coupling

  • Easily remove unused styles
  • Modify styles without fear
  • No barrier to entry

Reduce Coupling

  • Almost no code reuse
  • Increased size of CSS (both in lines and size)

Everyone Agrees on These

  • Enforce some kind of naming convention
  • Organize your files into sensible places
  • Use a CSS pre-processor that supports variables, basic math functions, and allows stylesheet composition
  • Do not write vendor prefixes. Use a build tool such as Autoprefixer
  • Stay away from specificity wars
  • Rarely use location dependent styles
  • Compress and minify your CSS

Suggested Conventions

General

  • DRY structure (box-sizing, float, height, margin, position, width, etc)
  • Decouple skin (background, color, border, text-size, etc)
  • Avoid nesting styles if possible (Overriding libraries is certainly an exception)
  • Do not write vendor prefixes
  • Avoid styling elements (eg h1 {})
  • Besides general styles all styles should be connected to a class
  • Take care in adding new utility classes

Naming Conventions

  • Spinal casing for structure
  • BEM for skin

Intro to BEM

BEM is a naming convention to do away with nesting selectors and increase awareness of the elements that are receiving styles. There are three categories in BEM:

  • Block
  • Element
  • Modifier


Note: Under BEM methodology no style should be attached to an element.

Usual HTML/CSS Example:



							

.ul {}
.ul > li {}
.ul > li > a {}
							

BEM HTML/CSS Example:



							

.menu {}
.menu__item {}
.menu__link {}
							

File Organization

Organize files according to the UI design structure


Build Tasks

  • Utilize Autoprefixer
  • Use a CSS linter to catch unwanted rules

CSS Tips

How the Browser Interprets CSS

Browsers read CSS right to left. Because of this, the rightmost selector is often called the "key selector"


There are four kinds of "key selector's": Id -> class -> tag -> universal. The order here is also the order of efficiency. Id's are much faster to process than a universal selector.

CSS Specificity

If two selectors target the same element the one with the higher specificity will win. If they have the same specificity then cascade.


Greatest specificity to lowest is: Inline -> Id -> Class/Psuedo-Class/Attribute -> Element/Psuedo-Elm. !important trumps everything. !important is only overridden with !important. That is why you should not use it.

Calculating Specificity

Selector Value
Inline 1000
Id 100
Class/Psuedo-Class/Attribute 10
Element/Psuedo-Elm 1

Note: These do not operate as base 10 values. Each level is infinitely more specific than the next. This means, for example, no amount of classes can outweigh an Id.

Calculating Specificity

Example 1


ul#Nav li.active a {}
						

This selector contains 1 Id, 1 class/psuedo-class/attribute, and targets 3 elements. It's specificity would be: 0, 100, 10, 3.

Calculating Specificity

Example 2


#footer *:not(nav) li {}
						

This selector contains 1 Id, 0 class/psuedo-class/attribute (:not is a unique psuedo class in that it adds no specificity. What's inside the parens is what adds to the specificity), and targets 2 elements (Universal selector has a no specificity value). It's specificity would be: 0, 100, 0, 2.

General Tips

  • Descendant selectors are the most expensive kind of selector
  • As soon as a selector fails to match it stops trying. A descendant selector that has no match will be faster if the match fails on the "key selector"
  • CSS is a render blocking resource (there are a few exceptions)
  • All styles will be recalculated for each stylesheet downloaded and parsed by the browser, even if it has been cached

References

BEM
A Look at Some CSS Methodologies
Efficiently Rendering CSS
CSS Tricks - CSS Specificity
The State of Loading CSS