slides.oddbird.net/conventions/aea1020/

Dissecting the ‘Name-Brand’ CSS Conventions

@ An Event Apart, Fall Summit

OOCSS, ITCSS,
SMACSS, BEM, CUBE

Branded CSS Conventions

Describe how we Write Consistent Code

Describe how we Write Organized Code

Describe how we Write Maintainable Code

Help us Write “Better” Code

CSS Mental Model
Selector Naming
Code Organization

Text Formatting

Text Formatting

(use a linter)

Conventions Are Optional

Headshot of Chris Coyier

I think they are all pretty neat and I see the point, but I’m a bunch of years into this and still generally…

– Chris Coyier, @chriscoyier

Headshot of Chris Coyier

write the selector I need and then style with that.

– Chris Coyier, @chriscoyier

Understand Their Concerns

Understand Their Solutions

Headshot of Chris Coyier

write the selector I need and then style with that.

– Chris Coyier, @chriscoyier

Headshot of Eric Meyer

Once you become experienced, you can break the rules in creative ways.

– Eric Meyer, Structural Naming (2004)

Different Project Needs

Different Team Structures

Just because InstaSalesBook Did It

Doesn’t mean you need to

Headshot of Una Kravets

We often hear “Are you using OOCSS or BEM?” but these things are not mutually exclusive. In fact, most of the time, we’re… mixing them up, customizing them to suit our own needs.

– Una Kravets, Atomic OOBEMITSCSS

Proto-convention… The 🌊 Cascade

Built-in Naming Rules

Built-in Organizing Rules

The 🌊 Cascade Makes CSS Possible

CSS solves a Unique Problem

7 year old Miriam with her hands on her knees

1989 Portrait of The Artist (it me)

Not interested in tech at all

1989 The WorldWideWeb Project

The first world wide website & graphic browser

It is required that HTML be a common language between all platforms

WWW Project

Web for all. Web on everything.

W3C Mission Statement

…This implies no device-specific markup, or anything which requires control over fonts or colors.

WWW Project

The first world wide website & graphic browser
Old IBM desktop
The second browser, a text-only terminal
A zillion different devices of all sizes (original)
Google Home, Amazon Echo, and Apple HomePod
Braille interface and headphones

WWW parsers should ignore tags which they do not understand, and ignore attributes which they do not understand of tags which they do understand.

WWW Project

Compatible Forward & Backward & Sideways

HTML totally eliminates any visual creativity that a document’s designer might have.

– Roy Smith, 1993

Netscape Handbook online tutorial
<CENTER>This text is centered</CENTER>

<MULTICOL COLS="3" GUTTER="25">
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
</MULTICOL>
  <P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>

Cascading HTML style sheets

Håkon Lie, October 1994

The user/browser specifies initial preferences and hands the remaining influence over to the document.

  1. 🎨 Author Branding
  2. 👥 User Preferences
  3. 🖥 User Agent (Browser) Defaults

🗺 Style Origins

An ordered list (cascade) of style sheets … can be referenced from the same document.

– Håkon Lie

Support visual and non-visual media.

– Håkon Lie

Provide hints that the browser may or may not use.

– Håkon Lie

Ignored Selectors

:is(html) {
background: rebeccapurple;
}

Ignored Decalarations

body {
/* display: block; browser default */
display: grid;
}

Websites don’t need to cannot possibly look the same in every browser.

– Me, again

These differences Are a Feature of The Web

We Script Browsers Perform Live

We don’t control styles We Hint & Suggest

The 🌊 Cascade Resolves 💥 Conflicts

The 🌊 Cascade Relies on Semantic Clues

  1. 🎨 Author Branding
  2. 👥 User Preferences
  3. 🖥 User Agent (Browser) Defaults

If conflicts arise the user should have the last word, but one should also allow the author to attach style hints.

– Håkon Lie

important

A balance of power

  1. ❗🖥 User Agent Important
  2. ❗👥 User Important
  3. ❗🎨 Author Important
  4. 🎨 Author Styles
  5. 👥 User Preferences
  6. 🖥 User Agent Defaults

🎯 CSS Selectors

A simple mapping between HTML elements and presentation hints.

– Håkon Lie

<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>
<P><FONT SIZE="4" COLOR="RED"></FONT></P>

CSS Selectors

p {
font-size: 1em;
color: red;
}

💥 Conflict!

button          { background: gray; }
.action { background: darkblue; }
[type=“submit”] { background: darkgreen; }
#send { background: maroon; }

Layers of… 🎯 Selector Specificity

  1. Inline style="…"
  2. Unique #IDs
  3. Reusable .classes & [attributes]
  4. Element types
  5. Universal *

Layers represent Different Goals

universal/type » Global Defaults

attrs/classes » Common Patterns

ID/style » Singular Overrides

combined… » Components & Parts

Specificity provides A Name-Layering Convention

Use selectors Based on Intent

Use low specificity To Describe Systems

Use high specificity To Describe Details

  1. 🗺 Origin &importance
  2. 🎯 Selector Specificity
  3. ⏭ Source Order

An Organizing Convention

.button { 
background: darkgreen;
}

.button-submit {
background: rebeccapurple;
}

Source Order Is Meaningful

Not safe to shuffle

Sort code From General to Specific

Link States

A:link {color: blue;}        /* specificity = 1,1 */
A:visited {color: purple;} /* specificity = 1,1 */
A:hover {color: magenta;} /* specificity = 1,1 */
A:active {color: red;} /* specificity = 1,1 */
main {
/* display: block; */
display: flex;
display: grid;
display: turtles;
}

Mobile-First

Start generic Fallbacks for Everyone

Add on More Targeted Styles

/* … general … */
@media () {}
@supports () {}

~2004-2006 Broad Conventions

Page Structures

#header {}
#nav {}
#main {}
#footer {}

HTML5

header {}
nav {}
main {}
footer {}

Browser Resets

Shared CSS files

~2006-2010… Major CSS Libraries

YUI, Blueprint, 960gs, etc…

Central Class Library

<div class=" column col6of12 last " >

Can be Massive

Solve Every Problem for Every Project

Often Hard to Customize

Headshot of Natalie Downe

@natbat Natalie Downe

2008 CSS Systems

CSS frameworks decrease the maintainability of code.

– Natalie Downe

CSS Systems Conventions > Frameworks

ClearLeft

Web Consulting Studio

  • High quality code
  • To tight deadlines
  • For handover to external developers
Young Jonny, Carl, and Miriam playing Magic The Gathering

CSS Ordering Based on Specificity

Product label for Cascade, 
with sheeting action for virtually spotless dishes -
subtitled Use the Cascade
  1. Elements grouped by Type
  2. Classes grouped by Effect
  3. IDs grouped by Component

1… General Styles

  • body styles
  • reset
  • links
  • headings
  • other elements, tags

2… Helper Styles

  • forms
  • notifications
  • errors
  • consistant items with normally just one class

3… Page Structure

  • header
  • footer
  • generic layout blocks
  • skeleton including page furniture

4… Page Components

“most of your styles will be in here”

5… Overrides

avoid as much as possible

Modular Sizing

Components & Internals 100% Fluid

Fixed widths Only On Containers

(usually in ems)

max-width: 100%;

(to stop overflow)

Be Afraid Of Heights

(the variable axis for text)

Up & Down Font Size Constantly

Don’t Overly Sandbox

Styles should be reusable

Focus on What Not Where

div#page div.teaser ul.products li p.name
ul.products p.name

Don’t re-engineer Seperate Solutions

Develop in browsers simultaneously

Headshot of Nicole Sullivan

@stubbornella Nicole Sullivan

2009 Object Oriented CSS

Working for e.g. Yahoo! & Facebook

How do you scale CSS For Thousands of Pages?

New pages should Rarely Require New CSS

Use a Component Library

Beyond Reusable Components

Components Share Patterns

Avoid even unique component styles

A CSS “object” is a repeating visual pattern, that can be abstracted into an independent snippet of HTML, CSS, and possibly JavaScript.

– Nicole Sullivan, OOCSS

1. Separate Structure & Skin

Object Structure Minimal & Reusable

Object Skin Multiple Theme Options

Avoid limiting A Class To One Tag

.text is better than p.text or div.text

2. Separate Container & Content

Be Flexible

  • Container sets width \
  • Content sets height

Rarely use Location-Dependent Styles

"Focus on What Not Where"

(from CSS Systems)

Media.
Extending objects, a simple example.
Block with media on left, and text on right.
Block with media on right, and text on left.
Same media blocks, 
with overlayed boxes showing image and text elements
<div class="media">
<img class="fixedMedia" src="myImg.png" />
<div class="text">...</div>
</div>
<figure class="media">
<img class="fixedMedia" src="myImg.png" />
<figcaption class="text">...</figcaption>
</figure>
<li class="media">
<img class="fixedMedia" src="myImg.png" />
<p class="text">...</p>
</li>
<article class="media">
<img class="fixedMedia" src="myImg.png" />
<header class="text">...</header>
</article>

Extend Objects By Applying Multiple Classes

<div class="media media_reverse">
<img class="fixedMedia" src="myImg.png" />
<div class="text">...</div>
</div>

Mix & match Container & Content Objects

To create unique components, without unique CSS

Organized from Simple to Complex Tasks

Mentions Missing Scope

We’ll come back to that…

2009-Present Systems/Objects Repackaged

SMACSS, BEM, Atomic Design, ITCSS, etc…

2010, Yandex Block Element Modifier

Block Standalone Entity

Meaningful on its own

Element Always Part Of A Block

No standalone meaning

Modifier Change Appearance Or Behavior

A flag on a block or element

Not Size or Complexity Self-Sufficiency & Belonging

Selector Naming

.block { }
.block--modifier { }
.block__element { }
.block__element--modifier { }

Always Flat Specificty

No .combined.selectors

Modifier Exception

.block--modifier .block__element { }

Principle of Single Responsibility

/* Internal & Frame */
.button {
text-align: center;
border: 1px solid black;
}

Parent block provides External Positioning

/* External */
.header__button {
margin: 30px;
}

Open/Closed Principle

Open to modifier classes, closed to direct changes

/* ⚠ Not This */
.header .button {
margin: 30px;
}

2011, Jonathan Snook SMACSS

Scalable and Modular Architecture for CSS

Other Inspirations

Organized on Category

  1. Base (element type)
  2. Layout (use #id)
  3. Module (use .classes)
  4. State (use !important)
  5. Theme (i.e. “skin”)

Layout Styles

#article { float: left; }
.l-flipped #article { float: right; }
.l-fixed #article { width: 600px; }

Related elements within a module use the base name as a prefix.

– Jonathan Snook, SMACSS

.example { }
.example-caption { }

State Types

.is-collapsed, .msg.is-error, .is-hidden

/* Callout Module */
.callout { }

/* Callout Module with State */
.callout.is-collapsed { }
// in module-name.css
.mod { border: 1px solid; }

// in theme.css
.mod { border-color: blue; }

Minimize Depth of Applicability

/* 6 generations */
body.article > #main > #content > #intro > p > b { }
body.article #intro b { }

2013, Brad Frost Atomic Web Design

A design process based on composition

label, input, and button atoms
search form molecule, with label, input, and button
banner organism, with logo, navigation, and search
wireframe of a full page

2014, Harry Roberts Inverted Triangle CSS

Narrow/Broad Reach How Many Elements?

Low/High Specificity What Selector Weight?

Generic to Explicit What Desired Impact?

From p {} through .text-center {}

/* Runs the risk of becoming out of date; not very maintainable. */
.blue { color: blue; }

/* Depends on location in order to be rendered properly. */
.header span { color: blue; }

/* Too specific; limits our ability to reuse. */
.header-color { color: blue; }

/* Nicely abstracted, very portable, doesn’t risk becoming out of date. */
.highlight-color { color: blue; }

2015 BEMIT

Extending the BEM syntax for ITCSS

NameSpaces

  • Components » .c-<name>
  • Objects » .o-<name>
  • Utilities » .u-<name>
  • States » .is-<name>/.has-<name>
  • Media » .<name>@<media>
<div class="o-media@md  c-user  c-user--premium">
<img src="" alt="" class="o-media__img@md c-user__photo c-avatar" />
<p class="o-media__body@md c-user__bio">...</p>
</div>

2014, Glen Maddern Attribute Modules for CSS

<button custom-attribute="anything">...</button>

Custom Attributes Provide Namespacing

Base Attribute

[am-Button]

Attribute Variations

[am-Button~='large']

<a am-Button>Normal button</a>
<a am-Button='large'>Large button</a>
<a am-Button='rounded'>Rounded button</a>
<a am-Button='large rounded'>Large rounded button</a>

Choosing A Prefix

  • data-* Provides JavaScript API
  • *-* Ensures Future-Proofing
  • [data-attr]Presence (even if empty)
  • [data-attr="..."]Exact match
  • [data-attr*="..."]Any match
  • [data-attr~="..."]Space-delimited (like classes)
  • [data-attr|="..."]Hyphen-delimited
  • [data-attr^="..."]Starts with…
  • [data-attr$="..."]Ends with…
  • [data-attr="..." i|s]Case sensativity

CSS-in-JS

Has multiple meanings

Using JS Frameworks Single File Components

Component Styles “Scoped”?

Scope Is About Ownership

Not just Is-Inside-Of

(no lower boundary)

But specifically Is-Owned-By

(clear lower boundaries)

<article-component>
<h2>...</h2>

<sub-component />

<footer>...</footer>
</article-component>
<article-component data-scope='article'>
<h2 data-scope='article'>...</h2>

<sub-component data-scope='article' data-scope='sub'>
<!-- internals of sub only have scope='sub' -->
</sub-component>

<footer data-scope='article'>...</footer>
</article-component>
<style scoped>
article { }
h2 { }
footer { }
</style>
article[data-scope=article] { }
h2[data-scope=article] { }
footer[data-scope=article] { }
<article data-scope="article instance-id">
h2[data-scope~=article] { 
/* all instances */
}
h2[data-scope~=instance-id] {
/* unique instance */
}

Frameworks Don’t Organize CSS

Always Scope Single-File Components

Emotion

render(
<button css={css`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
&:hover {
color:
${color};
}
`
} >...</button>
)
<button class="css-1h3ivcl">...</button>

JS doesn’t understand Lengths & Colors &c.

2015, Yahoo! Atomic CSS

CSS is Painful

Not-quite Inline Styles

<div class="Bgc(#0280ae.5) C(#fff) P(20px)">...</div>
<div class="Pos(a) Bgc(brandColor) W(columnWidth) H(90px)">...</div>

Tachyons

<body class="bg-green black-70 pa4">
<h1 class="f1">...</h1>
</body>

Tailwind CSS

<div class="md:flex">
<div class="md:flex-shrink-0">
<img class="rounded-lg md:w-56" src="..." alt="">
</div>
<div class="mt-4 md:mt-0 md:ml-6">
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">...</div>
</div>
</div>
.btn {
  @apply font-bold py-2 px-4 rounded;
}
.btn-blue {
  @apply bg-blue-500 text-white;
}
.btn-blue:hover {
  @apply bg-blue-600;
}

I don’t Get It ¯\_(ツ)_/¯

Often called Functional CSS

CSS is All About Context

CSS is All About Side Effects

CSS is never Functionally “Pure

It’s all CSS In The End

When you… reduce the amount of time you spend writing and editing CSS… you must instead spend more time changing HTML classes

– Nicolas Gallagher

2020, Andy Bell CUBE CSS

Composition Utility Block Exception

Adjusting OOCSS/BEM to De-Emphasize Blocks

Macro Before Micro

Most of the work is already done for you with global and high-level styles.

– Andy Bell

Composition How Blocks Flow Together

Relies onIntelligent” Selectors

No “intervention by the author”

.flow > * + * {
margin-top: var(--flow-space, 1em);
}

Utilities Have One Job

.wrapper {
margin-inline: auto;
padding-inline: 1rem;
max-width: 60rem;
}
.bg-primary { background: #ff00ff; }
.bg-secondary { background: #ffbf81; }

.color-primary { color: #ff00ff; }
.color-secondary { color: #ffbf81; }

Blocks (Like BEM But Flexible)

Exceptions Variations To A Block

.card[data-state='reversed'] {
display: flex;
flex-direction: column-reverse;
}

Class Grouping

<article
class="[ card ] [ section box ] [ bg-base color-primary ]"
data-state="reversed"
></article>

At OddBird We Mix & Match

Ideas from Systems, OOCSS, ITCSS, AMCSS, CUBE

Context Matters

Work In Layers

(roughly ITCSS)

More layers Using Custom Properties

(with layered fallbacks)

a:link,
a:visited
{
color: var(--theme-link, var(--link-focus, var(--global-link)));
}

a:hover,
a:focus,
a:active
{
--link-focus: var(--theme-focus, var(--global-focus));
}

Prefer Global Styles

Define some constraints. Let the language work out the details.

– Keith J Grant

Use Built-In Attributes When Available

(We ❤ “intelligent” selectors)

is-hidden

[aria-hidden] & [hidden] & ??

is-collapsed

[aria-expanded] & [aria-pressed]

Use Utility Classes Where Meaningful & Common

.visually-hidden | .elide

DRY Code Don’t Repeat Yourself

.warning { border-color: red; }

DSfP Don’t Stretch for Patterns

.bc-r { border-color: red; }

Combine Tokens Into Themes

[data-theme] {
background-color: var(--theme-bg, var(--global-bg, transparent));
color: var(--theme-color, var(--global-color, inherit));
}
[data-theme='light'] {
--theme-bg: var(--neutral-light);
--theme-color: var(--neutral-dark);
--theme-link: var(--primary-dark);
}

[data-theme='dark'] {
--theme-bg: var(--neutral-dark);
--theme-color: var(--neutral-light);
--theme-link: var(--primary-light);
}

Attribute-namespace For Related Classes

.is-success | .is-error [data-msg="success | error"]

A Wider 🌊 Cascade Allows More Nuance in Layering

W3C is working to Update & Extend The Cascade

More 🎯 Nuance

e.g. :where()

Custom Layers

@layer reset {
*, ::before, ::after { box-sizing: border-box; }
html { line-sizing: normal; }
body { margin: 0; }
}

@layer base { }
@layer components { }
@layer utilities { }

The Cascade is Important

The Cascade is Not Going Away

The Cascade is Useful

To guide our conventions

CSS is unlike anything else… designed for the realities of a flexible, multilingual, multi-device web.

– Rachel Andrew