CSS can be fast, flexible, and pragmatic. But in large organizations, where many teams work on the same codebase for years, CSS must be above all one thing: structured.
Design systems are not a collection of pretty components. They are an infrastructure and CSS forms the technical foundation of this infrastructure. It determines whether a system remains scalable, extensible, consistent, and maintainable.
In this last door of the Advent calendar, we discuss how CSS is used in a professional design system: strategically, systematically, and consciously.
Why CSS is So Important in Design Systems
Design systems are far more than a collection of UI components or style guide documentation. They are the central infrastructure that guarantees the visual and functional consistency of a digital product over years. They define not only how buttons look or which colors are used, but establish fundamental principles about how teams collaborate, how code is structured, and how a product can evolve over time without losing its identity.
In this complex ecosystem, CSS plays a role that is often underestimated. CSS is not simply the tool with which you make things pretty. It is the transversal foundation that connects all levels of a design system. Visual consistency arises through CSS because it is the only language that communicates directly with visual output. Interaction patterns become tangible through CSS because states, hover effects, and animations are defined there. Component-based architecture stands and falls with the way CSS is structured, because poorly organized CSS makes even well-structured components difficult to maintain. Brand management manifests technically in CSS because colors, typography, and visual hierarchy find their implementation there.
A solid CSS architecture guarantees that components remain consistent across different contexts. Whether a component is used in a marketing landing page, an internal admin interface, or a mobile app, it must look and behave the same everywhere. This requires a CSS system that is logically extensible without breaking existing structures. It must be easily maintainable so that changes can be propagated from a central location without manually adjusting hundreds of places in the code. And it must guarantee the independence of components so that one component does not accidentally influence another just because both are rendered on the same page.
If this technical foundation is missing, technical debt accumulates exponentially. A design system without thoughtful CSS architecture becomes fragile over time. Developers start building workarounds because the existing structure no longer covers their requirements. New variants emerge as special cases instead of systematic extensions. Visual consistency erodes because teams develop different solutions for similar problems. In the end, there is a system that no longer deserves the name design system because it is neither systematic nor consistent.
1. Design Tokens – The Central Building Block
Design tokens form the abstraction layer between design and code and are thus the heart of every modern design system. They solve a fundamental problem that repeatedly occurs in large organizations and that is the discrepancy between what designers define in their design tools and what developers implement in code. Without tokens, design decisions exist only as visual artifacts in Figma, Sketch, or Adobe XD. Colors are noted as hex values, spacing as pixel measurements, typography as font sizes. These values are then manually transferred into code, which is error-prone and offers no guarantee of consistency.
Design tokens fundamentally change this model. They define design decisions as semantic, named values that are used in both the design tool and in code. A color is no longer #3B82F6, but --color-primary. A spacing is no longer 16px, but --space-m. This naming creates a common language between design and engineering and makes design systems machine-readable. Tools can automatically synchronize tokens, pipelines can transform them, and systems can automatically check their consistency.
The most important categories of design tokens cover all areas that define visual consistency. Color tokens define not only individual colors but semantic color hierarchies like --color-text, --color-surface, --color-border. Typography tokens include font sizes, line heights, font weights, and font families. Spacing tokens establish a rhythmic system of distances that is consistently used for margins, paddings, and gaps. Radii tokens define the rounding of corners and thus create visual consistency across all components. Shadow tokens define elevation levels and spatial hierarchies. Motion tokens define animation speeds and easing functions. Grid and layout tokens define breakpoints, container widths, and layout structures.
In modern CSS, tokens are implemented as custom properties, which gives them enormous flexibility:
:root {
--color-surface: oklch(0.98 0.01 0);
--color-text: oklch(0.2 0.02 260);
--space-s: 0.5rem;
--space-m: 1rem;
--space-l: 2rem;
--radius-s: 4px;
--radius-m: 8px;
--radius-l: 16px;
--shadow-card: 0 4px 16px rgba(0,0,0,0.08);
}
These tokens are not static but can be overridden depending on context. A dark mode can define different color tokens, a compact layout can use different spacing tokens, and different brands can have their own primary colors. The components themselves remain unchanged because they only reference the token names, not the concrete values. This decoupling makes design systems maintainable and enables systematic changes to be made centrally without having to touch thousands of components.
2. Layers for Consistent Priority
CSS Layers are one of the most important innovations for design systems in recent years. They solve a problem that has plagued large codebases since time immemorial and that is the unpredictability of the cascade. In classic CSS, the priority of rules is determined by a combination of specificity, source code order, and !important. In complex systems, this often leads to chaos because the order in which stylesheets are loaded can decide which rule wins. A utility stylesheet that is loaded too early can suddenly be overridden by a component stylesheet, even though utilities should by definition have the highest priority.
CSS Layers establish an explicit hierarchy that is independent of source code order and specificity. You define the layers of the system once and the browser guarantees that rules from higher layers always take precedence, no matter how they are defined or where they are in the code. This explicit control is fundamental for design systems because it creates predictability.
A typical layer setup for a design system looks like this:
@layer reset, tokens, base, components, utilities, overrides;
These six layers form a logical hierarchy that reflects the architecture of the entire system.
-
The reset layer contains normalizing CSS and systemic browser defaults. It stands first because it should have the lowest priority. Everything else overrides it.
-
The tokens layer defines design tokens as custom properties. These values form the foundation but should be overridable by all other layers.
-
The base layer contains fundamental styles for HTML elements like typography, lists, links. These base styles apply globally and define the typographic foundation.
-
The components layer is the heart and contains all reusable components like buttons, cards, inputs, navigations. Components should not be able to override each other, which is why they all exist in the same layer.
-
The utilities layer contains atomic helper classes like
.flex,.grid,.text-center, which should intentionally have high priority because they serve as an override mechanism. -
The overrides layer finally provides space for project-specific adjustments that can override all other rules.
This layer structure systematically prevents arbitrary rules from overriding other rules. A component can never accidentally override a utility because utilities are in a higher layer. A reset can never accidentally override a component because components are in a higher layer. The layer defines the power, not the file order, not the specificity. This predictability makes design systems maintainable and dramatically reduces debugging time.
3. Component Structure
The question of the right CSS methodology for design systems is as old as design systems themselves. For years, various approaches have been established, each with its own strengths and philosophies.
-
BEM (Block Element Modifier) brought structure and predictability to CSS class names.
-
SMACSS (Scalable and Modular Architecture for CSS) established category-based architectures.
-
OOCSS (Object-Oriented CSS) propagated reusability through separation of structure and skin. Utility-first frameworks like Tailwind demonstrated the power of atomic classes.
-
CUBE CSS (Composition Utilities Blocks Exceptions) combined multiple paradigms into a pragmatic hybrid.
The reality of modern design systems is that no single methodology covers all requirements. Large organizations therefore increasingly rely on hybrid structures that combine the strengths of different approaches. BEM remains the backbone for components because its naming conventions guarantee clarity and maintainability. CUBE CSS or utility-first patterns complement BEM for atomic helpers and layout primitives. ITCSS or CSS Layers define the global architecture and establish clear hierarchies.
The following structure shows how different paradigms work together elegantly:
@layer components {
.button {
padding: var(--space-s) var(--space-m);
border-radius: var(--radius-m);
background: var(--color-primary);
color: var(--color-text-on-primary);
}
.button--secondary {
background: var(--color-secondary);
}
.button__icon {
margin-inline-end: var(--space-s);
}
}
This structure combines multiple principles. The layer isolates components from other system parts. The BEM naming convention makes the relationships between classes immediately recognizable: .button is the block, .button--secondary a modifier, .button__icon an element. The use of design tokens (var(--space-s), var(--color-primary)) decouples values from their implementation. Logical properties like margin-inline-end guarantee internationalization and bidirectionality.
Each component is thus isolated, understandable, and maintainable. A developer who encounters .button--secondary for the first time immediately understands that it is a variant of the button block. A developer who sees .button__icon knows that this element is part of the button component.
The structure is self-documenting, which is crucial in large teams with high turnover. No one has to read long documentation to understand how the system works. The structure itself tells the story.
4. Theming for Multi-Brand Systems
Modern design systems must be increasingly flexible because they are used in contexts that go far beyond a single product. Corporations with multiple brands want to use a common technical foundation, but each brand should retain its own visual identity. White-label products must seamlessly fit into the brand identity of their customers. Platforms with multi-tenancy require individual themes per customer. Partner portals should reflect the look and feel of the partner, not that of the platform itself.
These requirements are difficult to implement with traditional CSS. In the past, multi-brand support often meant separate stylesheets per brand, which exponentially complicated maintenance. Every change had to be replicated in every brand stylesheet, which was error-prone and accumulated technical debt. CSS custom properties have fundamentally changed this paradigm and made theming a first-class feature.
The principle is elegant. Components reference only tokens, never concrete values. The tokens themselves are then defined depending on context:
[data-brand="blue"] {
--color-primary: oklch(0.62 0.14 230);
}
[data-brand="green"] {
--color-primary: oklch(0.65 0.14 135);
}
These few lines of CSS enable complete brand flexibility. A button that uses background: var(--color-primary) automatically adapts to the brand context. The JavaScript code that renders the button needs to know nothing about brands. The component itself remains unchanged. Only the token definitions change, and from this automatically follows the entire brand theme.
This decoupling has far-reaching consequences. New brands can be added without touching existing components. A new customer no longer means weeks of customization work but merely defining new token values. Brand switches can occur at runtime by simply changing the data-brand attribute. A/B tests with different themes become trivial. The entire complexity of multi-brand support collapses into a manageable amount of token definitions, while the components themselves remain brand-agnostic.
5. Component Encapsulation via Variables
Component-specific custom properties enable an elegant form of encapsulation where components remain adaptable depending on context without their basic structure being changed. The base component defines local variables with fallback values:
.card {
background: var(--card-bg, var(--color-surface));
color: var(--card-text, var(--color-text));
padding: var(--space-m);
border-radius: var(--radius-m);
}
Through this structure, the component can inherit its colors from the global token system (fallback values) while allowing local overrides. Variants can then specifically adjust only the relevant properties:
.card--highlight {
--card-bg: var(--brand-100);
--card-text: var(--brand-800);
}
This approach offers several advantages. Components adapt flexibly to different contexts without creating additional specificity. New variants do not require complete class redefinitions, only the targeted overriding of the relevant tokens. The component remains lean and maintainable because its basic structure remains unchanged and only the visual values are adjusted depending on context.
6. Motion Tokens and Animation Governance
Animations and movements are a frequently underestimated aspect of design systems. While colors, spacing, and typography are carefully defined in every design system, animations are often left to chance. The result is inconsistent timings, arbitrary easing functions, and a UX that feels different depending on the component. One transition takes 100ms, another 300ms, a third 500ms, without any recognizable system behind it. Some components use ease-in-out, others linear, still others have no defined easing functions at all.
Professional design systems treat motion just as systematically as all other design decisions. Motion tokens define speeds and easing functions centrally and thus make them consistent and reusable:
:root {
--motion-fast: 120ms;
--motion-medium: 180ms;
--motion-slow: 250ms;
--easing-standard: cubic-bezier(.4, 0, .2, 1);
}
These tokens establish a motion system with three speed levels. --motion-fast is used for small, immediate feedback animations, such as hover states or icon transitions. --motion-medium is the standard for most UI transitions like accordion openings or modal displays. --motion-slow is reserved for large, significant transitions, such as page changes or complex layout shifts. The easing function --easing-standard is based on Material Design’s motion principles and ensures naturally-looking movements.
Components then reference these tokens instead of defining their own values:
.card {
transition: box-shadow var(--motion-medium) var(--easing-standard);
}
The result is a UX that feels consistently coherent. All components move with consistent speeds and timings. The interface thus appears more professional and thoughtful because movements are no longer arbitrary but follow a recognizable system. Users unconsciously develop a feeling for how long transitions take, which improves perceived performance. The interface feels more predictable, which creates trust and reduces cognitive load.
7. Accessibility as a Systemic Duty
Accessibility is not an optional addition but a fundamental requirement for every professional design system. Accessibility is not a feature that you add later but a quality characteristic that must be built into the architecture from the beginning. Design systems that do not systematically address accessibility fail at their basic task: providing robust, universally usable components.
A central aspect is the definition of consistent focus states. Focus states are essential for keyboard navigation but are often implemented inconsistently. Some components have blue outlines, others orange, still others none at all. Stroke width varies, spacing differs. The result is a UX that is frustrating for keyboard users. Design systems solve this problem through central definition:
:root {
--focus-outline: 3px solid oklch(0.8 0.2 240);
}
:focus-visible {
outline: var(--focus-outline);
}
This approach guarantees that all interactive elements have the same focus state. Using :focus-visible instead of :focus is crucial because it prevents unwanted outlines from appearing on mouse clicks. The 3px stroke width meets WCAG requirements for visible focus indicators. The color is contrasty enough to be visible on all backgrounds.
Contrast ratios are another critical point. WCAG requires a minimum contrast ratio of 4.5:1 for normal text and 3:1 for large text or UI components. Design systems must guarantee that all color combinations meet these requirements. This means that color tokens cannot be defined in isolation but must always be validated in combination with their backgrounds. Tools like Figma plugins or automated tests can perform this validation already in the design process and prevent non-compliant combinations from getting into the code.
Zoom capability and relative units are fundamental for accessibility. Users with visual impairments often enlarge the browser’s default font size. Design systems must be able to handle these enlargements without breaking. This requires the consistent use of relative units like rem and em instead of fixed pixel values. Layouts must be flexible enough to remain functional even at 200% magnification.
Respecting prefers-reduced-motion is essential for users with vestibular disorders or motion sensitivity. Too much movement can cause nausea or disorientation in these users. Design systems must accommodate these needs:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
This rule effectively disables all animations for users who have activated prefers-reduced-motion. Using 0.01ms instead of 0ms is a technical workaround that ensures transition events are still triggered, which can be important for JavaScript-based components.
Minimum sizes for touch targets are particularly critical for mobile interfaces. WCAG recommends a minimum size of 44x44 pixels for interactive elements. Design systems should anchor this requirement in their component definitions and ensure that buttons, links, and other interactive elements meet these minimum sizes or at least have a sufficiently large clickable area, even if the visible element is smaller.
8. Flexible Layouts via Grid & Container Queries
Modern design systems rely on CSS Grid and Container Queries as the foundation for flexible, context-independent layouts. Grid enables intrinsically responsive structures that automatically adapt to available space:
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: var(--space-l);
}
This definition automatically creates as many columns as possible, with each being at least 260px wide. No media queries are necessary because the grid intrinsically responds to available space. The gap property uses token values and thus guarantees consistent spacing across all layout contexts.
Container Queries extend this principle and make components truly responsive by responding to their own size rather than the viewport size:
.card {
container-type: inline-size;
}
@container (min-width: 450px) {
.card {
display: grid;
grid-template-columns: 120px 1fr;
}
}
Through Container Queries, components function in any environment independent of the page layout. A card can remain compact in a narrow sidebar and automatically switch to a multi-column layout in a wide main area. The component knows its context and adapts intelligently without the surrounding layout needing to know about it. This decoupling makes components truly reusable.
9. Governance: Rules for Scaling and Maintainability
A design system without governance is like a city without building codes. In the beginning, it may work because a small team intuitively understands how things should be done. But as soon as the system grows, teams get bigger, new developers join, and the codebase becomes more complex, inconsistencies inevitably arise. Everyone solves problems in their own way, patterns are duplicated, best practices are ignored, and technical debt accumulates exponentially. Governance rules prevent this decay by establishing clear, enforceable principles.
The first and most important rule is the strict prohibition of inline styles. Inline styles have the highest specificity in CSS and can only be overridden by !important, which triggers a cascade of problems. They are not reusable, not maintainable, and make it impossible to manage styles centrally. In design systems, inline styles are an anti-pattern that must be consistently avoided. All styles should be defined in stylesheets or via CSS classes.
The second rule prohibits the use of IDs in CSS selectors. IDs have extremely high specificity that is difficult to override and destabilizes the entire cascade. A single ID selector can disrupt an entire design system because it overrides all class-based rules. IDs should only be used for JavaScript targeting or ARIA references, never for styling.
The third rule limits the nesting depth of selectors. Deep nesting like .sidebar .nav .item .link .icon leads to high specificity, difficult reusability, and fragile dependencies. Components should be structured flatly, ideally with a maximum of one level of nesting. BEM naming conventions help eliminate the need for deep nesting.
The fourth rule requires that components exclusively use design tokens, never concrete values. A component should never contain color: #3B82F6, but always color: var(--color-primary). This decoupling makes components reusable, themeable, and maintainable. Changes to colors, spacing, or other design decisions can be made centrally without touching components.
The fifth rule defines that component variants should be implemented exclusively via token overrides, not via new classes with duplicated styles. Instead of writing a new complete class for each variant, you specifically override the relevant tokens. This reduces code duplication and makes variants more maintainable.
The sixth rule requires that the layer hierarchy be strictly maintained. Components may not be defined in the utilities layer, utilities not in the components layer. This discipline guarantees the predictability of the cascade and prevents specificity problems.
The seventh rule recommends keeping utility classes minimal but using them strategically. Utility classes are powerful for layout primitives and atomic styles but should not be used inflationarily. A good design system finds the balance between component-based CSS and utility-first patterns.
These governance rules are not theoretical principles but practical guardrails that reduce technical debt in the long term. They make design systems maintainable, extensible, and understandable. Teams that consistently enforce these rules build systems that remain stable over years, while teams without governance sink into a swamp of technical debt.
10. Documentation and Communication
A design system is more than code. It is a living ecosystem that only unfolds its value when people understand it, apply it correctly, and actively develop it further. The best CSS architecture in the world is worthless if teams don’t know how to use it, if components are ambiguously documented, or if changes are introduced quietly without anyone knowing about them. Documentation and communication are not side activities but fundamental components of a successful design system.
Clear documentation is the foundation. Each component needs precise, understandable documentation that explains what it is intended for, which props or classes it accepts, which variants exist, and how it is correctly used. This documentation should live directly next to the code, ideally in the same file or directory, so that it is automatically maintained when changes occur. Separate documentation wikis quickly become outdated because no one thinks to update them when the code changes.
Code examples are essential because they show how components are used in practice. Abstract descriptions are often ambiguous, but a concrete example immediately shows how a component looks in real contexts. These examples should be copy-pasteable and cover common use cases. Storybook has established itself as the de facto standard for component libraries because it offers exactly that: interactive, explorative documentation with live examples.
Guidelines define best practices and usage principles. When should a button be used, when a link? How much spacing is appropriate between different components? What typographic hierarchies exist? Guidelines answer these questions and thus create a common language between design and engineering. They prevent each team from developing its own interpretations and thereby fragmenting the system.
Changelogs are indispensable for communicating changes. Each new version of a design system should have a detailed changelog that explains what has changed, which new features have been added, which bugs have been fixed, and whether there are breaking changes. This transparency enables teams to adopt updates in a controlled manner and detect potential problems early.
Versioning follows from changelogs and makes updates predictable. Semantic Versioning (SemVer) has established itself as the standard: major versions for breaking changes, minor versions for new features, patch versions for bugfixes. Teams can thus decide for themselves when to upgrade to newer versions and know exactly what risks an update entails.
Visual tests guarantee that changes to CSS do not unintentionally change the appearance of components. Tools like Chromatic or Percy automatically create screenshots of all components and compare them with each commit. Deviations become immediately visible, which prevents visual regressions from entering production unnoticed. This automated quality assurance is particularly valuable in large teams where no one can keep track of all components and their visual states anymore.
The interplay of CSS architecture, documentation, and tooling is crucial. A brilliant architecture without documentation is just as problematic as great documentation without a solid technical foundation. Successful design systems invest in both dimensions simultaneously and thus create an ecosystem that is not only technically robust but also humanly accessible and understandable.
Conclusion
CSS for design systems is far more than a collection of technical tricks or isolated best practices. It is a discipline that combines strategic thinking, technical excellence, and organizational foresight. A professional design system is not a code library that you write once and then forget, but a living infrastructure that evolves over years with the requirements of an organization. CSS forms the technical foundation of this infrastructure and fundamentally determines whether a system remains scalable, maintainable, and future-proof or whether it collapses under the weight of its own complexity.
The architecture of a design system is a strategic interplay of many dimensions. Design tokens create the abstraction layer between design and code and make design decisions machine-readable, consistent, and centrally maintainable. CSS layers establish explicit hierarchies and eliminate the unpredictability of the cascade. Component structures like BEM bring order to naming and make code self-documenting. Theming systems enable multi-brand flexibility without duplicating components.
Modern layout systems with Grid and Container Queries make components context-independent and truly responsive. Motion guidelines and animation governance ensure that movements are consistent and professional. Accessibility is not an afterthought but systemically anchored and guaranteed in every component. Governance rules prevent technical debt and keep the system maintainable in the long term.
These dimensions do not exist in isolation but interlock and reinforce each other. Tokens work best with layers because layers guarantee that token definitions have the right priority. Components benefit from theming because they become more reusable. Motion tokens are complemented by accessibility rules that ensure users can disable animations. Governance rules make documentation more effective because they guarantee that code is consistently structured and thus easier to understand and document.
Those who think CSS on this level do not simply build websites or interfaces. You build systems that can survive decades because they are based on solid principles rather than fragile hacks. You build systems that can be flexibly developed because their architecture enables extensions without having to rewrite everything. You build a reliable foundation for products, brands, and teams that guarantees consistency, increases efficiency, and minimizes technical debt.
This is the essence of professional CSS engineering in the context of design systems. It is not about knowing the latest features or applying the cleverest tricks. It is about building systems that are robust, maintainable, understandable, and future-proof. It is about not treating CSS as a side activity but as a strategic infrastructure decision with far-reaching consequences for the entire organization.
This ends our CSS Advent Calendar. 24 doors full of concepts, tools, strategies, and best practices for modern, professional CSS. From the fundamentals like the cascade and specificity through modern features like Container Queries and Cascade Layers to advanced topics like Houdini and design systems, we have traversed the entire range of contemporary CSS engineering. The journey has shown that CSS today is more powerful, more elegant, and more strategic than ever before. It is a language that deserves to be used with respect, care, and technical depth.
Merry Christmas and have fun implementing these concepts in your own projects!
Comments