seven layers by increasing specificity
ITCSS orders a stylesheet not by file type or component, but by the specificity and reach of every rule. This CSS architecture makes conflicts between global base rules and specific overrides predictable, instead of leaving them to the chance of import order, and stays maintainable across dozens of developers over years.
Table of Contents
- 1. The core problem: specificity without order
- 2. Settings and Tools: the invisible layers
- 3. Generic and Elements: the global foundation
- 4. Objects: layout related, reusable patterns
- 5. Components: the actual UI layer
- 6. Trumps: deliberate, documented exceptions
- 7. Implementing ITCSS with native Cascade Layers
- 8. Introducing ITCSS into an existing project
- 9. ITCSS compared to other organizing principles
- 10. Summary
- 11. FAQ
1. The core problem: specificity without order
ITCSS stands for Inverted Triangle CSS and was developed by Harry Roberts as an answer to a problem most grown stylesheets share, namely specificity that grows chaotically rather than under control as a project ages. Without deliberate architecture, global base rules, component specific adjustments and exceptions for individual edge cases end up in the same file, or in arbitrarily sorted files whose order in the build process decides which rule wins, not the meaning of its content.
The core idea of ITCSS is deceptively simple: a stylesheet is organized into layers that run from generic and broad reaching to specific and explicit, visualized as an inverted triangle. At the very top, the wide side of the triangle, sit rules with very low specificity and broad reach, such as CSS custom properties and reset rules. At the very bottom, the narrow tip, sit highly specific exception rules that are used deliberately and rarely. This CSS architecture turns the order of the stylesheet into a direct mapping of the specificity hierarchy, instead of an arbitrary history of commits.
The practical effect: a developer adding a new rule has to ask which layer it belongs to, not just which file happens to be open. This discipline, applied consistently across an entire project, prevents the typical specificity war where every new rule needs an even more specific one to win. ITCSS solves this problem not through prohibitions, but through a clear map of where every kind of rule belongs.
2. Settings and Tools: the invisible layers
The first layer in ITCSS is called Settings and contains exclusively variables, no actually rendered CSS rules. This is where custom properties for colors, spacing scales, breakpoints and typography values belong. This layer produces no CSS output in the sense of visible declarations by itself, it defines the vocabulary that all subsequent layers use. The benefit: a change to a base value, say the primary brand color, propagates automatically through the entire stylesheet without touching a single component rule.
The second layer, Tools, contains mixins and functions if a preprocessor like Sass is in use, or reusable custom property calculations with plain CSS. This layer also produces no direct output, it provides tools that later layers call. A common rule of thumb in ITCSS: if a layer compiles to empty CSS in isolation, it belongs to Settings or Tools, not to one of the following, output producing layers.
/* 1-settings/_colors.css — variables only, no rendered output */
:root {
--color-brand-500: oklch(0.55 0.18 275);
--color-brand-600: oklch(0.48 0.19 275);
--color-surface: oklch(0.98 0.01 275);
--space-unit: 0.25rem;
--radius-md: 0.5rem;
}
/* 2-tools/_mixins.css — reusable helpers, still no direct output */
@custom-media --viewport-md (width >= 48rem);
/* Example Sass mixin equivalent, if a preprocessor is used:
@mixin focus-ring($color: var(--color-brand-500)) {
outline: 2px solid $color;
outline-offset: 2px;
}
*/
3. Generic and Elements: the global foundation
The third layer, Generic, is the first that actually produces CSS output. This is where reset and normalize rules, box sizing declarations, and broad reaching selectors like * or ::before, ::after belong. These rules affect the entire document equally and deliberately carry minimal specificity, so they can be overridden without friction by every following layer. In ITCSS it matters that this layer contains no class selectors, only type and universal selectors.
The fourth layer, Elements, styles bare HTML elements without any class: h1, a, table, input. This is the level where default typography and default behavior for unstyled content are defined, for example in a CMS generated article body where no classes are available. This CSS architecture ensures that even raw, unclassified HTML looks reasonable without requiring a single class.
/* 3-generic/_reset.css — broad reach, minimal specificity */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
}
/* 4-elements/_typography.css — bare HTML elements, no classes */
h1, h2, h3 {
font-weight: 700;
line-height: 1.2;
}
a {
color: var(--color-brand-600);
text-decoration-thickness: from-font;
}
table {
border-collapse: collapse;
width: 100%;
}
4. Objects: layout related, reusable patterns
The fifth layer, Objects, follows the OOCSS principle by Nicole Sullivan: purely structural, layout related classes without visual styling like color or typography. A typical example is a grid system or a media object pattern that defines structure (say, an image on the left, text on the right) but makes no statement about colors or font sizes. Naming conventions like a leading o- prefix, for example o-media, make it immediately obvious that a class belongs to the Objects layer and is purely structural in intent.
This layer is deliberately separated from Components in ITCSS because it pursues a different kind of reusability. An Objects pattern should work across entirely different visual contexts, a card, a comment, a product snippet can all use the same o-media structure without that structure saying anything about appearance. Anyone who breaks this separation and mixes colors directly into Objects classes loses exactly the reusability benefit this layer is meant to provide.
/* 5-objects/_media.css — structure only, no color, no typography */
.o-media {
display: flex;
align-items: flex-start;
gap: var(--space-unit) * 4;
}
.o-media__figure {
flex-shrink: 0;
}
.o-media__body {
flex: 1 1 auto;
min-width: 0; /* prevents flex overflow with long text */
}
/* Grid object, purely structural */
.o-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: calc(var(--space-unit) * 6);
}
5. Components: the actual UI layer
The sixth layer, Components, is where most day to day development work happens. This is where concrete, named UI building blocks live, like a button, a card or a navigation menu, typically marked with a c- prefix, for example c-button. Unlike Objects, Components carry full visual responsibility, color, typography, shadows and transitions belong here. This layer can internally use Objects, for example a card that uses the o-media pattern for its internal layout, but makes its own color and typography decisions.
In practice, Components is the layer most often combined with BEM or a similar naming convention, because this is where most named, self contained UI units originate. ITCSS makes no requirement about which naming convention is used within the Components layer, it only fixes where these rules sit in the specificity gradient, namely noticeably more specific than Generic and Objects, but below the last two layers.
/* 6-components/_button.css — full visual responsibility */
.c-button {
display: inline-flex;
align-items: center;
gap: calc(var(--space-unit) * 2);
padding-block: calc(var(--space-unit) * 3);
padding-inline: calc(var(--space-unit) * 5);
border-radius: var(--radius-md);
background: var(--color-brand-500);
color: white;
font-weight: 600;
transition: background-color 150ms ease;
}
.c-button:hover {
background: var(--color-brand-600);
}
.c-button--secondary {
background: transparent;
border: 1px solid var(--color-brand-500);
color: var(--color-brand-600);
}
6. Trumps: deliberate, documented exceptions
The seventh and final layer, Trumps, is the most specific in the entire ITCSS system and contains utility classes and, in rare, documented cases, !important declarations. Classes like u-hidden or u-text-center belong here because they are meant to deliberately override every previous layer. The decisive difference from an arbitrary !important scattered somewhere in the code: in Trumps, the high specificity is intentional and concentrated in exactly one, clearly defined place in the stylesheet, instead of spread across the entire project.
A common mistake when starting with ITCSS is putting too many rules into Trumps, because it is the easiest way to solve a specificity problem in the short term. This CSS architecture only works, though, if Trumps stays small and rare, ideally a single digit number of utility classes for genuine, rare layout exceptions. If this layer grows uncontrolled, the whole system loses its benefit, because it once again becomes unclear which of the many highly specific rules wins in which context.
/* 7-trumps/_utilities.css — highest specificity, used sparingly and deliberately */
.u-hidden {
display: none !important;
}
.u-visually-hidden {
position: absolute !important;
width: 1px !important;
height: 1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
}
/* Deliberate, documented override for a rare edge case, not a habit */
.u-no-scroll {
overflow: hidden !important;
}
7. Implementing ITCSS with native Cascade Layers
Since wide browser support for @layer, ITCSS can be enforced not only through file order but natively through CSS Cascade Layers. This solves a subtle problem of the classic ITCSS implementation: without Cascade Layers, the specificity order between layers still depends on the declaration order in the compiled stylesheet. A file imported in the wrong order by mistake can undermine the entire architecture without any error becoming visible, because CSS does not throw a warning for specificity problems.
With explicit layer declarations, the order of layers is guaranteed independent of file order. A layer declared later wins over a layer declared earlier, regardless of how specific the individual selectors within the layers are. This makes ITCSS more robust against build tool quirks and import order mistakes that, experience shows, eventually occur in large projects with many contributors.
/* Layer order is declared once, independent of file import order */
@layer settings, tools, generic, elements, objects, components, trumps;
@import url("./1-settings/colors.css") layer(settings);
@import url("./3-generic/reset.css") layer(generic);
@import url("./4-elements/typography.css") layer(elements);
@import url("./5-objects/media.css") layer(objects);
@import url("./6-components/button.css") layer(components);
@import url("./7-trumps/utilities.css") layer(trumps);
/* Even if imported out of order below, "trumps" always wins over "components" */
8. Introducing ITCSS into an existing project
A full rewrite to ITCSS is rarely realistic for grown projects and usually not necessary either. The most pragmatic entry point is to organize new rules according to the ITCSS scheme from the start, while existing rules are gradually migrated into the right layer whenever they need to be touched anyway. A separate folder for new ITCSS files, imported after the existing legacy stylesheet, allows both systems to coexist during the transition period.
A common first step is establishing the Settings layer, replacing scattered hex color values and magic numbers throughout the existing CSS with custom properties, without immediately changing the structure of the remaining rules. This step alone already delivers measurable benefit, because future color or spacing changes can happen centrally, even before the full ITCSS migration is complete.
9. ITCSS compared to other organizing principles
ITCSS does not compete directly with BEM or Utility First, it is more of a meta level that defines where rules are placed in which layer, independent of the naming convention used within those layers. The following table still compares ITCSS with the most common alternatives for stylesheet organization, to place their respective strengths.
| Approach | Organizing principle | Specificity control | Fit |
|---|---|---|---|
| ITCSS | By specificity and reach | Explicit, seven levels | Large teams, long lived projects |
| By file type | Component, layout, utilities separated | None, purely organizational | Small projects |
| 7-1 pattern (Sass) | By feature folders | Implicit via import order | Sass based projects |
| Atomic Design | By UI complexity (atom to page) | Not directly addressed | Component libraries |
In practice these approaches do not exclude each other. A team can use Atomic Design for component hierarchy and ITCSS for the order of the underlying CSS rules at the same time, because both answer different questions, namely how components are structured versus in what specificity order their rules are loaded.
Mironsoft
CSS architecture, design systems and frontend refactoring
Is your CSS growing uncontrolled with every release?
We restructure grown stylesheets according to ITCSS principles, introduce native Cascade Layers and make specificity in your project predictable again, without a big bang rewrite.
ITCSS migration
Gradual introduction of the seven layers into existing stylesheets
Cascade Layers
Native layer structure for robust, import order independent specificity
Architecture review
Analysis of existing specificity conflicts and a concrete refactoring plan
10. Summary
ITCSS solves the core problem of grown stylesheets by ordering rules by specificity and reach instead of by file type or chance. The seven layers, Settings, Tools, Generic, Elements, Objects, Components and Trumps, together form an inverted triangle running from broad, generic rules to narrow, highly specific exceptions. This CSS architecture makes it predictable which rule wins, without a developer needing to know the entire import history of a project.
Native Cascade Layers strengthen this benefit further, because they guarantee layer order independent of the actual file order in the build. For teams looking to newly adopt ITCSS, a gradual migration is more realistic than a full rewrite, starting with the Settings layer and a clear convention for new rules, while existing code is caught up whenever convenient.
ITCSS: Scalable CSS Architecture — The essentials at a glance
Seven layers
Settings, Tools, Generic, Elements, Objects, Components, Trumps, ordered from generic to specific.
Specificity control
Stylesheet order matches the specificity hierarchy, instead of arbitrary import history.
Cascade Layers
Native @layer declaration makes layer order robust and independent of file order.
Adoption
Gradual migration, starting with Settings, instead of a full rewrite.