What are OOCSS's two principles — separating structure from skin, and container from content — and how do they show up in the class names you write?
answer
- two principles, no naming grammar
- box mechanics versus paint
- name the thing, do not name its location
- the media object is the poster child
- variants cost three declarations, not nine
basics
~20 sOOCSS, from Nicole Sullivan, says to split a component's box mechanics (structure) from its paint (skin) so a new variant costs one small rule, and to style objects by their own class rather than by where they sit, so the same class works anywhere.
solid answer
~50 sOOCSS — Object-Oriented CSS — has exactly two rules. **Separate structure from skin**: one class owns the box mechanics (`display`, `padding`, `border-width`, layout), a second owns the paint (`background`, `border-color`, `color`, `box-shadow`). A new visual variant then costs one small rule instead of a copied component, and shared metrics change in one place. In BEM terms this is what makes modifiers small — `.btn` is structure, `.btn--primary` is skin. **Separate container from content**: an object must be styled through its own class, never through where it happens to sit, so you write `.media` rather than `.sidebar h2` and the object drops into any context unchanged. Sullivan's canonical example is the media object — a fixed-size image beside fluid text — which appears in comments, cards and search results without a single context-specific rule. Both principles push the same way: define things once, by their own name, and vary them by adding a class.
code
css · 11 lines/* structure: the box, shared by every variant */
.btn { display: inline-flex; padding: 0.5rem 1rem; border: 1px solid transparent; border-radius: 4px; }
/* skin: paint only, one small rule per variant */
.btn--primary { background: #0057d8; border-color: #0047b3; color: #fff; }
.btn--danger { background: #c92a2a; border-color: #a61e1e; color: #fff; }
/* container-independent object */
.media { display: flex; gap: 1rem; align-items: flex-start; }
.media__figure { flex: 0 0 auto; }
.media__body { flex: 1 1 auto; }go deeper
Be able to state the two principles plainly and give one example of each: shared box styles in one rule with colour variants separate, and styling a class rather than .sidebar h2.
Explain the mechanics of the payoff — why variants shrink from nine declarations to three, and why an ancestor-based rule captures nodes nobody intended and outweighs the component's own rule.
Show where you draw the line in real code: split along the axis that actually varies, recognise a bloated modifier as a misplaced structure/skin boundary, and know when re-implementing beats abstracting.
Own the tradeoff between reuse and readability. Aggressive separation maximises reuse but dissolves the component's identity in the markup, so set a house rule for how far it goes and what a shared object must guarantee before it is promoted.
## Where OOCSS came from Nicole Sullivan's OOCSS predates most other CSS methodologies and is the source of ideas the later ones inherited. It is deliberately small: two principles, no naming grammar, no folder scheme. Understanding it makes BEM's modifier design and the whole "components not pages" idea look inevitable rather than arbitrary. ## Principle 1 — separate structure from skin **Structure** is everything about the box: `display`, `padding`, `border-width`, `border-radius`, sizing, internal layout. **Skin** is everything about how it is painted: `background`, `border-color`, `color`, `box-shadow`, gradients. The unrefactored stylesheet mixes them and then repeats both per variant: ```css /* the problem: every variant re-states the box */ .btn-primary { display: inline-flex; padding: 0.5rem 1rem; border: 1px solid; border-radius: 4px; background: #0057d8; border-color: #0047b3; color: #fff; } .btn-danger { display: inline-flex; padding: 0.5rem 1rem; border: 1px solid; border-radius: 4px; background: #c92a2a; border-color: #a61e1e; color: #fff; } ``` Changing the padding now means finding every variant, and one will be missed. Split along the structure/skin line and the duplication disappears: ```css .btn { display: inline-flex; padding: 0.5rem 1rem; border: 1px solid transparent; border-radius: 4px; } .btn--primary { background: #0057d8; border-color: #0047b3; color: #fff; } .btn--danger { background: #c92a2a; border-color: #a61e1e; color: #fff; } ``` The payoff is asymmetric: the shared metrics live in exactly one rule, and adding the fifth variant costs three declarations rather than nine. This is precisely the discipline that makes BEM modifiers small — a modifier that has to restate the box is a sign the structure/skin line was drawn in the wrong place. ## Principle 2 — separate container from content The second principle attacks a different habit: styling something by where it lives. ```css /* container-dependent: the heading only looks right in the sidebar */ .sidebar h2 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.04em; } ``` Three things go wrong. The design cannot move — putting that heading in the footer means writing the rule again or extending the selector. The rule silently captures every `h2` that ever appears in a sidebar, including ones added years later by someone who never read this file. And it outweighs a plain class rule, so the component's own styles lose to its context. The OOCSS answer is to name the thing and style the name: ```css .section-heading { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.04em; } ``` Now the object is portable, the rule affects only nodes that opted in, and it competes on equal terms with every other single-class rule. ## The media object Sullivan's canonical example is the **media object**: a fixed-size media item (avatar, thumbnail) beside a fluid block of content. It shows up in comment threads, search results, notification lists, chat rows and cards. Written as one context-free object with its own class, it is authored once and reused everywhere; written per context, it is re-implemented five times with slightly different spacing each time. The object is pure structure — it says nothing about colour or typography — which is exactly what makes it composable with any skin. ## The consequence for class names Both principles push toward the same shape of class list: a node carries a name for what it *is*, plus additional classes for its variation, and never relies on an ancestor selector for either. ```html <article class="media comment comment--pinned"> ``` Structure comes from `media`, identity from `comment`, skin variation from `comment--pinned`, and nothing depends on where the node sits. ## Where the principles bite back Separating structure from skin means two or three classes in the markup instead of one, and a designer changing a variant has to know which rule owns which property. Pushed too far, every property ends up in its own class and the component name disappears from the markup entirely — at which point you have traded one problem for another. The judgment call is where to stop: split along the axis you actually vary. If a component has five colour treatments and one box, separate them; if it has one of each, keep it in one rule and split later when the second variant arrives.
- How does OOCSS's structure/skin split relate to BEM's block and modifier?BEM gives it a name grammar. The block rule ends up holding the structure — box mechanics shared by every variant — and the modifiers hold the skin. That is why a well-formed modifier is only a few declarations long: if a modifier is restating padding and display, the structure/skin line was drawn in the wrong place and the component will duplicate as variants multiply.
- What concretely goes wrong with a rule like `.sidebar h2`?Three things. The heading style cannot move to another region without rewriting the selector, every future `h2` placed in a sidebar is captured whether or not that was intended, and the descendant selector outweighs single-class component rules so the component loses to its context. Naming the object and styling the name fixes all three at once.
- How far should the structure/skin separation be pushed?Split along the axis you actually vary. Many colour treatments over one box shape is a clear case for separating them. One of each is not — keep it in a single rule and split when the second variant genuinely arrives. Pushed to the extreme, every property becomes its own class and the component's name vanishes from the markup, which trades one maintenance problem for another.
Structure and skin are a chair's frame and its upholstery: re-covering a chair should not mean rebuilding the frame, and the frame should not assume it is standing in a particular room.
saying these in an interview costs you the question
- Thinks OOCSS is a naming syntax like BEM
- Calls repeated box declarations across variants harmless duplication
- Styles components through ancestor selectors for convenience
- Says the media object is about images rather than a reusable structure
- Splits every single property into its own class as the goal