OOCSS
oocss oocss (object-oriented css), articulated by nicole sullivan at yahoo, separates structure from skin and container from content. staff engineers
Introduction
OOCSS (Object-Oriented CSS), articulated by Nicole Sullivan at Yahoo, separates structure from skin and container from content. Staff engineers reference OOCSS when auditing bloated CSS bundles — thousands of rules that differ only in padding or border-color because every page component was styled as a unique snowflake.
OOCSS is not a naming convention like BEM — it is a design principle that predicts where duplication will appear before the bundle hits 500 KB gzip.
Business problem
Business pressure: Yahoo's frontend at peak had CSS bundles that duplicated button, media, and grid rules across hundreds of page templates. Each redesign required touching hundreds of selectors. OOCSS reduces redundant rules — directly shrinking download time and maintenance cost.
- Performance: Smaller CSS improves FCP on mobile — every duplicate rule is wasted bytes.
- Redesign velocity: Swap skin classes globally instead of per-component hunt.
- Consistency: One media object pattern — image + body — across news, products, comments.
Why this feature exists
Platform history: Pre-flexbox, pre-component-framework era — authors styled pages as documents, not objects. Sullivan's media object and grid object became reference implementations proving 10× rule reduction on real Yahoo pages.
- Problem solved: Structural CSS reused; cosmetic variation applied via composable skin classes.
- Rejected alternative: Page-specific CSS files — unmaintainable and uncacheable across routes.
- Modern role: OOCSS thinking underlies utility-first CSS and design-system primitives.
Browser rendering perspective
Rendering impact: Fewer unique rules mean smaller CSSOM and faster style recalc on large DOMs. Composable classes can increase HTML class count — trade rule deduplication for slightly larger HTML parse.
- Chrome (Blink): Shared rules apply to many nodes — single style computation reused.
- Memory: Large class lists per node marginally increase attribute storage — usually net win vs duplicate rules.
Internal browser workflow
Workflow: Identify repeating structures (media, grid, button) → extract structure object → attach skin classes for color/border → never tie width to a named component like #sidebar .promo.
- Structure: Layout, spacing rhythm, float/flex/grid skeleton.
- Skin: Colors, borders, shadows — swappable per theme.
- Composition: Multiple objects on one node —
media btn-skin-primary.
Feature deep dive
Two principles: (1) Separate structure and skin — structure classes define size/layout; skin classes define look. (2) Separate container from content — objects should work in any parent; avoid .sidebar .list location-dependent rules.
- Media object: Image + content body — avatar lists, comments, cards.
- Grid object: Equal-height columns before Grid layout was universal.
- Button skin:
.btnstructure +.btn-skin-warningskin.
/* Structure */.media { display: flex; align-items: flex-start; gap: 1rem; }.media__img { flex-shrink: 0; }.media__body { flex: 1; min-width: 0; }/* Skin — swappable */.skin-border { border: 1px solid var(--border); }.skin-shadow { box-shadow: 0 2px 8px rgba(0,0,0,.08); }.skin-accent { color: var(--accent); }/* Compose */<div class="media skin-border skin-shadow"><img class="media__img" src="…" alt=""><div class="media__body skin-accent">…</div></div>
Syntax
No mandated delimiter — OOCSS is principle-driven. Teams often combine with BEM for element naming inside objects. Skin classes are typically generic (skin-muted) or prefixed (theme-dark).
Examples
Button object — structure reused across portal:
.btn { display: inline-flex; align-items: center; padding: 0.5rem 1rem;border-radius: 6px; font-weight: 500; border: 1px solid transparent; }.btn-skin-primary { background: var(--primary); color: #fff; }.btn-skin-ghost { background: transparent; border-color: var(--border); }
Real-world use
Bootstrap 3's component + modifier model inherits OOCSS DNA. Tailwind's separation of layout utilities (structure) and color utilities (skin) is OOCSS at atomic scale. SMACSS "module" objects and ITCSS "objects" layer explicitly cite Sullivan's work.
Real production example
Pattern: News portal extracts 12 layout objects — media, flag, pack, island — documented in design system. Page templates only compose objects + skins; page-specific CSS forbidden.
- Metric: CSS bundle size tracked per release — new page must not add >2KB unique rules.
- Audit: stylelint bans id selectors and qualified selectors in object layer.
Enterprise use case
Enterprise: Carbon's layout classes and Atlassian's spacing primitives embody container/content separation — components do not assume sidebar width.
- Material: Elevation skins swappable without changing component structure.
- Polaris: Token-driven skins on stable component shells.
Accessibility considerations
A11y: Skin classes that only change color must maintain contrast pairs — document allowed skin combinations in token matrix. Structure objects must not remove semantic elements.
- Focus skin:
skin-focus-ringapplied consistently across button objects.
Performance considerations
Performance: Rule deduplication shrinks CSSOM — primary win. Avoid composing 15 skin classes per node; batch into semantic theme class when HTML weight grows.
- Purge: Generic skin names need safelist discipline —
skin-*pattern.
SEO considerations
SEO: Smaller CSS improves mobile crawl efficiency marginally. Content must not be hidden via skin utilities — skin-hidden on primary copy is an SEO and a11y failure.
Scalability considerations
Scale: Object libraries need versioning — changing .media flex gap affects every comment thread. Visual regression on core objects is mandatory.
- Theme: Skins map to token sets — dark theme swaps skin definitions, not structure.
Common production issues
Production failures: "Object explosion" — 40 margin utilities instead of one spacing scale. Or skins that encode structure (skin-width-200) — principle violated.
- Regression: Container-dependent rule sneaks back —
.checkout .mediabreaks cart in mini-cart dropdown.
Debugging guide
Debug: Coverage tab — which rules are unused? Duplicate structure rules in Coverage indicate missed object extraction.
- DevTools: Toggle skin classes live to verify structure independence.
Best practices
- Extract third repetition of a pattern into an object.
- Never use location selectors on objects —
.main .mediaforbidden. - Map skins to design tokens — not raw hex in skin classes.
- Version core objects — breaking change requires major DS release.
Anti-patterns
- Page-specific overrides on global objects — fork object instead.
- Skin classes that set width/height — structure leak.
- IDs for layout — defeats reuse and specificity explodes.
Trade-offs
- Benefit: smaller CSS, faster redesigns, predictable objects.
- Cost: HTML carries more classes; mental model for new devs.
- vs utilities: OOCSS objects are semantic chunks; utilities are atomic — often merged in mature systems.
Architecture review questions
- Which page patterns qualify as objects vs one-off components?
- How do skins map to theme tokens in our DS?
- What selector rules ban container coupling?
- How do we version breaking object changes?
Interview questions
State the two OOCSS principles.(Beginner)
Separate structure from skin; separate container from content. Structure handles layout and size; skin handles color, border, shadow. Objects must not depend on parent location selectors.
Follow-up: Give an example of violating container/content separation.
How does OOCSS relate to Tailwind?(Intermediate)
Tailwind atomizes structure and skin into utilities — same separation at finer granularity. OOCSS media object might become flex + gap + shrink utilities composed in HTML.
Follow-up: When is an object layer still worth it over utilities?
Hands-on exercise
Exercise: Audit a page CSS file. Extract media and button objects. Measure rule count and gzip before/after.
- Document 3 skin classes mapped to tokens.
- Remove one container-dependent selector.
Staff engineer notes
- OOCSS is the "why" behind object layers in ITCSS and SMACSS — cite principles, not just layer names.
- If skins encode dimensions, you've recreated component-specific CSS with extra steps.
Common pitfalls
- Object library without governance — 12 conflicting button objects.
Try it yourself
Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.
Try it yourself
Summary
OOCSS teaches composable CSS objects with swappable skins — reducing duplication and location-dependent selectors. Staff engineers apply its two principles when auditing bundle bloat and designing design-system primitives.
Key takeaways
- Separate structure from skin and container from content.
- Reusable objects shrink CSS bundles and speed redesigns.
- Principles underpin ITCSS objects layer and utility-first systems.