slides.oddbird.net/rws/smashing/systems/

CSS Organizing Conventions

@ Smashing Online

~2007 Major Grid Frameworks

Blueprint, 960gs, etc…

an element on a 12-column grid

👎 Framework Override Hell

  • High quality code
  • On tight deadlines
  • For handover to client

CSS frameworks decrease the maintainability of code.

– Natalie Downe

  • Shared Vocabulary
  • Reusable Patterns
  • Personalized Styles
  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

Layouts with Fluid Internals

#container {
width: /* em values preferred */;
max-width: 100%;
}
.any-internal { /* % values only */ }

Don’t Overly Sandbox Focus on What Not Where

Dont Re-engineer Seperate Solutions

For individual browsers

  1. Define it
  2. Develop it
  3. Maintain it
  4. Communicate it

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

Separate Container & Content

“Rarely use location-dependent styles”

Also from OOCSS Media Object

2009-Present Systems/Objects Repackaged

SMACSS, BEM, Atomic Design, ITCSS, etc…

Object Composition

.person class contains .name & .address classes

p.alert.error

Composed result of p, .alert, & .error functions

The Cascade Is About Balancing Concerns

We Communicate… Relationships & Intent

Clear Semantics Help the Browsers

Make informed decisions

Help other Developers

Read & understand & maintain the code

CSS Systems Based on Specificity

  1. Elements
  2. Classes
  3. IDs

Atomic Design Based on Complexity

  1. Atoms (element type)
  2. Molecules
  3. Organisms
  4. Templates
  5. Pages

SMACSS Based on Category

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

Low/High Specificity What Selector Weight?

Generic to Explicit What Desired Impact?

From p {} through .text-center {}

CSS Systems + OOCSS Updated with Pictures

  1. Tools
  2. Config
  3. Initial
  4. Patterns
  5. Layouts
  6. Components

CSS Systems + OOCSS + ITCSS + Atomic Design + …

Tools Used Across Projects

Sass, Accoutrement, Herman, Cascading Colors…

Config Design Tokens
Tool Configuration

Tokens by Purpose

_colors.scss | _sizes.scss | _fonts.scss

Not by Sass Feature

_variables.scss | _functions.scss | _mixins.scss

Combined as a Single Sass Module

With no CSS output

Initial Global & Element Defaults

Including resets & custom properties

Patterns Reusable Objects & Skins

The majority of our code base…

Layouts Specific Templates

Often composed of existing patterns

Components Specific Functionality

Often composed of existing patterns

  • sass/
    • tools/
    • config/
      • _colors.scss
      • _fonts.scss
      • _sizes.scss
      • _index.scss
    • initial/
    • patterns/
    • layouts/
    • components/
    • style.scss
<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 */
}

Naming Conventions

Not explicit in most…

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__element » .block__element--modifier

👎 Flattening Of Selector Structure

Everything is equal specificity

Combine Selectors To Match Scope & Specificity

In meaningful ways

SMACSS Layer Prefixes

.l-<layout> | .is-<state>

State Types

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

is-collapsed

[aria-expanded] & [aria-pressed]

Namespace Related Selectors

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

Attribute Variations

[data-btn~='success']

  • [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

??? Screen Reader Only

[data-hidden='screen'] | [data-hidden='small-screen']

Use Utility Classes For Meaningful Utilities

.sr-only | .clearfix | .elide-text

And then… There’s Tailwind

All explicit, all the time

DRY Code Don’t Repeat Yourself

.warning { border-color: red; }

DSfP Don’t Stretch for Patterns

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