Door 13 – CSS Architectures. BEM, ITCSS, CUBE CSS Compared | CSS Adventskalender
Skip to content

Door 13 – CSS Architectures. BEM, ITCSS, CUBE CSS Compared

Published: at 07:00 AM

CSS can be small and manageable – until a project grows. At the latest when several teams work on a codebase, when components are to be reused, or when branding variants arise, it becomes clear: Without a clear architecture, CSS quickly becomes chaotic.

This door explains three of the most important architectural approaches in modern projects: BEM, ITCSS, and CUBE CSS. And above all: How they differ, where they complement each other, and how to use them consciously.

Why Does CSS Need Architecture at All?

The answer lies in the nature of CSS itself: it acts globally. Every rule can theoretically affect every element on the page, and this becomes a problem as soon as a project exceeds a certain size. Styles can collide without it being obvious. A seemingly local change can have unexpected effects in completely different parts of the application. What was intended as a specific solution for a single problem quickly becomes a source of global conflicts.

Architecture is not an end in itself and not additional complexity for its own sake. It creates concrete, measurable benefits in daily development work. It ensures predictability – developers know where to find styles and how to add new ones without breaking existing code. It creates structure that enables maintaining overview even in large codebases. It helps keep specificity low, so that not every new rule needs to work with !important or nested selectors.

Clear responsibilities emerge when every part of the code has a defined purpose and it’s clear who is responsible for what. And finally, the codebase becomes significantly more scalable – new features can be added without rethinking the entire system. Especially in growing teams where multiple developers work in parallel on different features, a well-thought-out CSS architecture is not optional, but indispensable.

1. BEM

BEM is the abbreviation of “Block, Element, Modifier” and is probably the best-known CSS architecture model. It places a clear focus on naming and the structure of components.

Basic Principle:

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

Example:

.button {}
.button__icon {}
.button--primary {}

Advantages of BEM

The biggest advantage of BEM lies in the clarity of names. A class name like .card__title--featured is immediately understandable, even when seeing the code for the first time. You can recognize at first glance that it’s a title within a card that is additionally marked as “featured”. This self-documentation makes the code more maintainable and significantly reduces onboarding time for new team members.

BEM deliberately avoids deep selector structures. Instead of writing .card .header .title, you simply use .card__title. This has the crucial advantage that specificity remains low. Every class has the same weight, there are no complex cascades and no surprises when overriding styles. This makes the system predictable and reduces the need for !important hacks.

The methodology is strongly component-oriented, which perfectly matches modern frontend frameworks. Each block is self-contained, and dependencies are explicitly visible through naming conventions. This significantly facilitates team collaboration, as conflicts are minimized and everyone immediately understands which styles belong to which component.

Typical Areas of Use

BEM is particularly suitable for classic websites where components are clearly definable and a certain degree of reuse occurs without the system becoming too complex. In component-based systems – whether with React, Vue, or other frameworks – BEM fits excellently, as the naming convention also makes component boundaries visible in CSS. In static or semi-static design systems where consistency is more important than extreme flexibility, BEM has also proven itself.

Disadvantages

The downside of explicit names is comparatively long class names. .navigation__list-item--active is clear but also verbose. In large projects, this can make HTML confusing. Some developers find BEM redundant because information is encoded multiple times – once in the HTML structure, once in the class names.

The biggest disadvantage is the need for strict discipline. BEM only works if everyone involved consistently follows the conventions. A single developer who starts using generic selectors or nested structures can undermine the entire architecture. This requires code reviews, clear guidelines, and shared conviction in the team.

Modern Tool Support: In practice, BEM conventions can today be largely automatically enforced through linters like Stylelint with BEM plugins. These check syntax, naming conventions, and specificity and can be integrated into CI/CD pipelines. AI tools like GitHub Copilot recognize established BEM patterns in the project and automatically suggest compliant class names. This significantly reduces manual review effort, but does not replace the conceptual decision of when something should be a Block, Element, or Modifier.

2. ITCSS

ITCSS is the abbreviation for “Inverted Triangle CSS” and is a structural model for entire stylesheet architectures. It defines order, not naming.

The Layers:

  1. Settings (Variables, Tokens)
  2. Tools (Mixins, Functions)
  3. Generic (Reset, Normalize)
  4. Elements (HTML element styles)
  5. Objects (structural patterns)
  6. Components (component-specific styles)
  7. Utilities (small, highly specific helpers)

Visualized:

Settings
Tools
Generic
Elements
Objects
Components
Utilities

Advantages

The crucial advantage of ITCSS lies in the clear, scalable project structure. The division into layers forces you to think about the reach and responsibility of each style. Settings and Tools are pure definitions without output, Generic and Elements set foundations, Objects define reusable layout patterns, Components contain specific styles, and Utilities provide the final, highly specific adjustments. This hierarchy is not arbitrary but follows the principle of increasing specificity.

When ITCSS is applied correctly, specificity remains low throughout the system because each layer only does what it should do without interfering with the responsibility of the next layer. The clear separation between low-level styles (like resets and element defaults) and high-level styles (like component-specific adjustments) makes the system maintainable and understandable. For large teams and design systems, ITCSS is ideal because different teams can work on different layers without blocking each other.

Disadvantages

However, ITCSS requires considerable discipline. It’s easy to place styles in the wrong layer – for example, component-specific rules in the Objects layer or generic resets in Components. Once established, it’s difficult to correct these errors without refactoring the entire system.

The methodology also requires a build system or at least very clear folder conventions and import orders. In projects without a build pipeline, ITCSS quickly becomes impractical. The methodology is also less intuitive than BEM – while BEM names are self-explanatory, with ITCSS you first need to understand the concept of layers to know where to place a style.

The latter is probably also the reason why this approach is so rarely seen in projects. The learning curve is steep, and especially junior developers are quickly overwhelmed. Especially in teams with changing personnel or different experience levels, ITCSS is often not consistently communicated and quickly implemented inconsistently, which can lead to massive problems.

When ITCSS Makes Sense

ITCSS unfolds its strengths in large codebases where the sheer amount of CSS quickly becomes unmanageable without clear structure. When multiple sub-teams work in parallel, such as one team for the design system foundation, another for marketing components, and a third for product UI, ITCSS offers clear boundaries and responsibilities.

ITCSS is particularly valuable for design systems that must remain consistent over years. The layer architecture makes it easy to make fundamental changes such as to design tokens without affecting higher layers. Even in projects with a lot of legacy CSS, ITCSS helps create order. You can refactor step by step by first cleaning up the lower layers and then working upward.

3. CUBE CSS

CUBE CSS, or spelled out “Composition, Utility, Block, Exception” is more modern and lighter than BEM and ITCSS. Unlike BEM, which focuses on naming and ITCSS, which defines structure, CUBE CSS focuses on four central concepts:

  1. Composition as the foundation for global design patterns
  2. minimally specific blocks for components
  3. pragmatic utilities for recurring adjustments
  4. defined exceptions for consciously marked special cases

These four pillars work together to create a flexible, maintainable system that combines the advantages of utility-first with the clarity of semantic components.

Basic Principle

The four pillars of CUBE CSS build on each other and each define different responsibilities in the system:

Composition forms the foundation of the entire system. This is where global design patterns, typographic scales, spacing systems, and layout logic are defined. Composition also includes design tokens, CSS Custom Properties for colors, font sizes, spacing, and other recurring values. This layer is framework-agnostic and describes the fundamental visual language of the project. Composition defines the “what” and “how” of design at a global level, without concerning itself with specific components.

Utility provides single-class helpers for frequently recurring styling tasks. Classes like .mt-2 (margin-top), .flex (display: flex), or .grid (display: grid) enable adjusting layout and spacing directly in HTML, without having to create a new component or modifier for every little thing. Utilities are deliberately highly specific in their function. A utility class does exactly one thing. This makes them extremely reusable and reduces the need to edit CSS files when you just want to adjust spacing.

Block refers to the actual components such as elements like cards, buttons, or navigations that have specific visual and functional characteristics. Unlike BEM, blocks in CUBE CSS are deliberately kept lightweight. They only define what’s essential and often rely on Composition and Utilities for layout and spacing. A block has clear styles but minimal specificity. There are no deeply nested selectors or complex override logic. Blocks use design tokens from the Composition layer and combine with Utilities for flexibility.

Exception marks conscious deviations from the standard. They are special cases that exist for good reasons. Exceptions are explicitly named (e.g., .is-error, .has-icon, .u-force-wrap) and signal: something extraordinary is happening here. This makes the code self-documenting and prevents special cases from being silently built into blocks. An exception is temporary and context-dependent, meaning it should not become the rule. Through explicit naming, the code remains maintainable because it’s clear where conscious deviations exist.

Example:

/* Utility */
.u-text-center { text-align: center; }

/* Block */
.card {
  padding: var(--space-m);
  border-radius: var(--radius-m);
}

/* Exception */
.card.is-error {
  border-color: var(--error);
}

Advantages

CUBE CSS deliberately uses utilities to keep specificity low. Instead of writing complex selectors, you combine simple single-purpose classes like .flex or .gap-2 with lightweight block styles. The result is CSS that produces fewer conflicts and is easier to override when necessary.

The methodology is very flexible and adapts to different project sizes. It’s modern and lightweight. There are no rigid rules like with BEM, no complex layer hierarchy like with ITCSS. Instead, CUBE CSS promotes a pragmatic approach. Composition for global patterns, Utilities for quick adjustments, Blocks for real components, and Exceptions only where truly necessary. This makes modular systems easier because you don’t have to build a new component for every use case.

Disadvantages

CUBE CSS requires conceptual clarity. You need to understand when something is a Composition, a Utility, a Block, or an Exception. This distinction is not always obvious and different developers can come to different conclusions. This can lead to inconsistencies if it’s not clearly communicated which conventions apply.

In teams without solid CSS know-how, CUBE CSS can sometimes seem unfamiliar. While BEM is self-explanatory through its explicit names, CUBE CSS requires a deeper understanding of how CSS works and how to use specificity and composition. Naming is also less strict than with BEM. There’s no fixed schema like block__element--modifier, which means freedom but also leaves room for inconsistency.

Ideal Use

CUBE CSS is ideal for modern component libraries that should work in both traditional projects and framework-based applications. The combination of utilities and lightweight blocks makes the system extremely adaptable.

Teams that prefer utility classes, such as because they’ve already worked with Tailwind or similar frameworks, find a structured middle ground in CUBE CSS. It offers the flexibility of utility-first without sacrificing the semantic clarity of components.

CUBE CSS is particularly valuable for projects that should be both pragmatic and structured. It’s not an all-or-nothing approach like BEM, but allows you to choose the appropriate style depending on the situation: Utilities for simple adjustments, Blocks for reusable components, Exceptions for the few special cases that every project has.

How Do the Approaches Complement Each Other?

The three architectural approaches are not competing philosophies but solve different problems.

BEM solves the problem of naming. It provides a clear answer to the question of how to name components and their parts.

ITCSS solves the problem of structure. It defines how to organize styles in layers while controlling specificity.

CUBE CSS solves the problem of complexity in modular systems. It offers a middle ground between semantic components and pragmatic utilities.

These different focuses make the approaches compatible. In practice, many large teams end up with a hybrid solution that combines the strengths of all three approaches. You use ITCSS for the basic structure of the codebase, the division into Settings, Tools, Generic, Elements, Objects, Components, and Utilities provides a clear order. Within the Components layer, you use BEM for consistent, self-explanatory naming. And for layout adjustments, spacing, and other recurring patterns, you use utilities inspired by CUBE CSS or directly adopted from Tailwind.

A concrete example of this hybrid solution looks like this. In the Settings layer, CSS Custom Properties are defined for all design tokens. Specifically, these would be colors, font sizes, spacing, border radii. In the Utilities layer, abstractions are created for margin, padding, gap, and other frequently used spacing properties. In the Components layer live BEM components like .card, .card__header, .card__title--featured, which access the design tokens. The entire architecture follows the ITCSS layers, so it’s clear in what order the files are loaded and how specificity increases.

This setup is very common in enterprise design systems today because it combines the advantages of all three approaches. Clear structure through ITCSS, understandable naming through BEM, and pragmatic flexibility through utilities. It’s not a theoretical construct, but a proven solution for real, complex projects.

Other Relevant Approaches Overview

The CSS architecture landscape is broader than the three approaches discussed in detail here. Different tools and methods have become established depending on technology stack and project requirements. While BEM, ITCSS, and CUBE CSS represent framework-agnostic principles, there are other approaches that are particularly widespread in certain ecosystems.

CSS Modules

CSS Modules is a build-tool-based approach that automatically isolates styles at the component level. Class names are converted into unique hashes during the build process (e.g., .button becomes .button_3x7sK), making name collisions technically impossible. This is particularly common in React and Vue projects, where each component has its own CSS file. The advantage lies in automatic isolation. You don’t have to worry about global name conflicts. The disadvantage is the dependency on build tools and the fact that generated class names are no longer self-explanatory. CSS Modules works well in combination with BEM-like naming conventions within components.

Utility-First and Tailwind CSS

Utility-First is not an architecture in the classic sense, but a philosophy. Instead of writing semantic component classes, you combine atomic utility classes directly in HTML. Tailwind CSS is the most prominent representative of this approach. Classes like flex, pt-4, bg-blue-500, or hover:opacity-75 are used directly in markup. This significantly speeds up development as you don’t have to switch between HTML and CSS.

The approach is, however, controversial. Proponents appreciate the speed and tight coupling of styles and markup. Critics complain about “cluttered” HTML files and the mixing of presentation and structure. In practice, Utility-First works particularly well for prototyping, marketing sites, and small to medium projects. In very large, long-lived design systems, it’s often combined with component-based approaches such as utilities for layout and spacing, semantic components for complex UI elements.

CSS-in-JS and Styled Components

CSS-in-JS writes styles directly in JavaScript code, often as template literals. Styled Components, Emotion, and similar libraries are particularly widespread in the React ecosystem.

The advantage: Styles can dynamically react to props, and there are no separate CSS files anymore. TypeScript support and automatic critical CSS extraction are additional benefits.

The disadvantages: Runtime overhead - styles are generated and injected at runtime -, larger bundle sizes, and the fact that CSS is no longer written in pure CSS. CSS-in-JS is heavily framework-dependent and makes sense when you’re already deeply embedded in the React ecosystem and want to leverage the benefits of JavaScript integration. For framework-agnostic design systems, it’s less suitable.

Historical Foundations: OOCSS and SMACSS

Before BEM, ITCSS, and CUBE CSS became popular, OOCSS (Object-Oriented CSS) and SMACSS (Scalable and Modular Architecture for CSS) shaped thinking about CSS architecture. OOCSS introduced the idea of separating structure and skin and creating reusable “objects”. SMACSS defined categories like Base, Layout, Module, State, and Theme. Both approaches are less directly found in projects today, but have strongly influenced BEM, ITCSS, and modern architectures. Those who want to understand the fundamentals should know both. In practice, however, their further developments are more commonly used today.

A Possible Example from a Project

A team worked on a UI library with over 120 components that was used in multiple products. The original CSS had grown organically and showed all typical problems of an unplanned architecture. It was highly specific, with nested selectors and !important cascades that had emerged because developers no longer knew how to safely override styles. The structure was poor, files contained arbitrary mixes of global resets, component styles, and utilities. The system was full of overrides. Every new requirement led to existing styles being overridden with even more specific rules. The result was confusing and difficult to maintain.

The team decided on a gradual transition to a hybrid architecture. First, ITCSS was introduced as a structural model. A clear folder structure with Settings for design tokens, Tools for Sass mixins, Generic for resets, Elements for HTML element defaults, Objects for layout patterns, Components for the actual components, and Utilities for helper classes. In parallel, BEM naming was introduced for all components, which immediately improved readability and maintainability. CUBE CSS utilities were used for recurring layout, spacing, and typographic adjustments, eliminating the need to build a new component variant for every little thing. Custom Properties were consistently used for all design tokens, significantly simplifying theming and global adjustments.

The result was impressive. The total amount of CSS was reduced by about 40 percent because redundancies were eliminated and utilities were reused. Merge conflicts became significantly rarer because the clear structure enabled everyone to know where new styles belong. Collaboration between design and engineering improved because the design tokens in the Settings layer provided a common language. And the development of new components became faster because the team could rely on established patterns and utilities instead of starting from scratch each time.

When to Choose Which Approach?

Choose BEM if:

BEM is the right choice when components are at the center of your project and you need a clear, self-explanatory naming convention. If you work in a team where not everyone has deep CSS knowledge, BEM helps through its explicitness. One look at the class name is enough to understand what an element does and where it belongs.

Naming consistency is essential with BEM. If your team is willing to enforce this consistency, it pays off. BEM works particularly well in medium-sized teams where enough developers are involved that structure is necessary, but not so many that a more complex system like ITCSS would be justified. If your project has a manageable number of components and you don’t expect extreme scaling, BEM offers exactly the right balance between structure and simplicity.

Choose ITCSS if:

ITCSS is the right choice for large projects where the sheer amount of CSS becomes unmanageable without clear structure. When multiple teams work in parallel on different parts of the application, such as a design system team, a marketing team, and several feature teams, ITCSS offers clear layers and responsibilities that minimize conflicts.

When styles are globally distributed and don’t just live in isolated components, ITCSS helps create order and control specificity. ITCSS is particularly valuable when a design system exists that must be maintained over years. The layer hierarchy makes it possible to make fundamental changes to design tokens or resets without affecting component styles. ITCSS is not a quick win, but a long-term investment in architecture.

Choose CUBE CSS if:

CUBE CSS is ideal when you build modern, flexible components while wanting to stay pragmatic. If utility-first makes sense for your team, such as because you’ve already experimented with Tailwind or appreciate the idea of reusable single-purpose classes, CUBE CSS offers a structured framework without sacrificing the semantic clarity of components.

If you want little specificity and want to avoid conflicts through intelligent composition and utilities, CUBE CSS is an excellent choice. It suits teams that want neither the rigidity of BEM nor the complexity of ITCSS but still need a recognizable architecture. CUBE CSS is particularly valuable when you want to work pragmatically. You choose the appropriate approach for each situation instead of adhering to a rigid set of rules.

Conclusion

CSS architecture is the basis for long-term maintainability. Whether BEM, ITCSS, or CUBE CSS, it is important that you choose an approach consciously, implement it consistently, and understand it not as a rigid set of rules, but as a guideline.


☕ Buy me a coffee

If you enjoy my articles and they help you in your work, I would appreciate a "coffee" and a few kind words from you.

Buy me a coffee

Previous Post
Door 14 – CSS Cascade Layers
Next Post
Door 12 – State Styling without JavaScript

Comments