What is SMACSS?

SMACSS (Scalable and Modular Architecture for CSS) is a comprehensive methodology developed by Jonathan Snook that provides a structured approach to organizing CSS code. This architecture system categorizes CSS rules into five distinct types, making stylesheets more maintainable, scalable, and easier to understand for development teams.

Unlike other CSS methodologies that focus primarily on naming conventions, SMACSS emphasizes the categorization and organization of styles based on their purpose and function within the application. This approach helps developers create more predictable and maintainable code bases that can scale effectively as projects grow.

The Five Categories of SMACSS

Base

Default styles for HTML elements without classes or IDs. These are the foundation styles that apply globally.

Layout

Styles that define the major structural components and page sections like headers, footers, and grids.

Module

Reusable, modular components that can be used throughout the application like buttons, cards, and navigation.

State

Styles that describe how modules or layouts look in different states like active, hidden, or expanded.

Theme

Visual appearance styles that can be swapped to change the overall look and feel of the application.

1. Base Rules

Base rules establish the default styling for HTML elements. These styles should be minimal and focus on setting consistent foundations across browsers. Base rules typically include CSS resets, normalization, and default typography settings.

/* Base Rules Example */
* {
box-sizing: border-box;
}

html {
font-size: 16px;
line-height: 1.6;
}

body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, sans-serif;
color: #333;
background-color: #fff;
}

h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: 0.5em;
font-weight: 600;
}

p {
margin-top: 0;
margin-bottom: 1em;
}

a {
color: #2563eb;
text-decoration: none;
}

a:hover {
text-decoration: underline;
}

Base Rules Demo

This text demonstrates the base typography styles. Notice how the font family, line height, and spacing are consistently applied.

Links are styled with a blue color by default, and hover effects are applied consistently.

2. Layout Rules

Layout rules define the major structural components of your page. These rules use ID selectors or class names prefixed with “l-” or “layout-” to distinguish them from other categories. Layout rules should focus on positioning and spacing of major page sections.

/* Layout Rules Example */
.l-header {
background: #2563eb;
color: white;
padding: 1rem;
position: sticky;
top: 0;
z-index: 100;
}

.l-main {
display: flex;
min-height: calc(100vh – 60px);
}

.l-sidebar {
width: 250px;
background: #f3f4f6;
padding: 1rem;
border-right: 1px solid #e5e7eb;
}

.l-content {
flex: 1;
padding: 2rem;
max-width: 1200px;
}

.l-footer {
background: #1f2937;
color: white;
text-align: center;
padding: 2rem;
}

/* Grid Layout System */
.l-grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 1rem;
}

.l-grid-item {
grid-column: span 12;
}

@media (min-width: 768px) {
.l-grid-item–half {
grid-column: span 6;
}

.l-grid-item–third {
grid-column: span 4;
}
}

Layout Rules Demo

Main Content Area

This is where the primary content would be displayed. The layout is flexible and responsive.

3. Module Rules

Module rules are the heart of SMACSS. These are reusable, modular components that can be placed anywhere in your layout. Modules should be designed to be independent and portable, with their own self-contained styling that doesn’t depend on their location within the page.

/* Module Rules Example */
.btn {
display: inline-block;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
text-decoration: none;
font-weight: 500;
font-size: 14px;
transition: all 0.3s ease;
text-align: center;
}

.btn-primary {
background: #2563eb;
color: white;
}

.btn-primary:hover {
background: #1d4ed8;
transform: translateY(-1px);
}

.btn-secondary {
background: #6b7280;
color: white;
}

.btn-secondary:hover {
background: #4b5563;
}

.btn-outline {
background: transparent;
border: 2px solid #2563eb;
color: #2563eb;
}

.btn-outline:hover {
background: #2563eb;
color: white;
}

/* Card Module */
.card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 20px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
transition: box-shadow 0.3s ease;
}

.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.card-header {
font-size: 1.25em;
font-weight: bold;
margin-bottom: 10px;
color: #1f2937;
}

.card-body {
color: #6b7280;
line-height: 1.6;
}

.card-footer {
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #e5e7eb;
}

/* Navigation Module */
.nav {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}

.nav-item {
margin-right: 1rem;
}

.nav-link {
padding: 0.5rem 1rem;
color: #6b7280;
text-decoration: none;
border-radius: 4px;
transition: all 0.3s ease;
}

.nav-link:hover {
background: #f3f4f6;
color: #1f2937;
}

Module Rules Demo

Button Modules



Card Module Example
This is a reusable card component that can be used throughout the application. It includes a header, body, and optional footer.
Another Card
Cards are modular and can contain any type of content while maintaining consistent styling and behavior.

4. State Rules

State rules describe how modules or layouts appear when in different states. States are generally applied with JavaScript and indicate changes like active, inactive, expanded, collapsed, or hidden. State classes are typically prefixed with “is-” to clearly indicate their purpose.

/* State Rules Example */
.is-hidden {
display: none !important;
}

.is-visible {
display: block !important;
}

.is-active {
background: #fef3c7 !important;
border-color: #f59e0b !important;
color: #92400e !important;
}

.is-disabled {
opacity: 0.6 !important;
pointer-events: none !important;
cursor: not-allowed !important;
}

.is-loading {
position: relative;
pointer-events: none;
}

.is-loading::after {
content: ”;
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border: 2px solid #f3f3f3;
border-top: 2px solid #2563eb;
border-radius: 50%;
animation: spin 1s linear infinite;
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

.is-expanded {
max-height: 1000px !important;
overflow: visible !important;
}

.is-collapsed {
max-height: 0 !important;
overflow: hidden !important;
transition: max-height 0.3s ease;
}

/* Tab-specific states */
.tab.is-active {
background: white;
border-bottom-color: white;
z-index: 1;
}

.tab-content.is-active {
display: block;
}

.tab-content {
display: none;
}

State Rules Interactive Demo



Interactive State Demo
Click the buttons above to see different states applied to this card. Notice how the appearance changes based on the state classes.

5. Theme Rules

Theme rules define the visual appearance and can be swapped to change colors, fonts, and other visual aspects of your site. Themes allow you to create different visual variations without changing the underlying structure or functionality.

/* Theme Rules Example */
/* Default Theme */
.theme-default {
–primary-color: #2563eb;
–secondary-color: #6b7280;
–background-color: #ffffff;
–text-color: #1f2937;
–border-color: #e5e7eb;
}

/* Dark Theme */
.theme-dark {
–primary-color: #3b82f6;
–secondary-color: #9ca3af;
–background-color: #1f2937;
–text-color: #f9fafb;
–border-color: #4b5563;
}

/* Applying theme variables */
.themed-container {
background-color: var(–background-color);
color: var(–text-color);
border: 1px solid var(–border-color);
padding: 20px;
border-radius: 8px;
transition: all 0.3s ease;
}

.themed-button {
background-color: var(–primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}

.themed-card {
background-color: var(–background-color);
border: 1px solid var(–border-color);
border-radius: 8px;
padding: 20px;
color: var(–text-color);
}

/* Alternative approach without CSS custom properties */
.btn-theme-corporate {
background: #1e40af;
color: white;
}

.btn-theme-nature {
background: #059669;
color: white;
}

.btn-theme-sunset {
background: #dc2626;
color: white;
}

.card-theme-corporate {
border-left: 4px solid #1e40af;
}

.card-theme-nature {
border-left: 4px solid #059669;
}

.card-theme-sunset {
border-left: 4px solid #dc2626;
}

Theme Rules Interactive Demo


Themed Container

This container uses CSS custom properties to apply theme colors. Switch between themes to see the visual differences.

Themed Card

Cards also adapt to the selected theme automatically.

File Organization in SMACSS

SMACSS encourages organizing CSS files according to the five categories. This approach makes it easier to locate and maintain styles as your project grows. Here’s a recommended file structure:

styles/
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _base.scss
├── layout/
│ ├── _header.scss
│ ├── _footer.scss
│ ├── _sidebar.scss
│ └── _grid.scss
├── modules/
│ ├── _buttons.scss
│ ├── _cards.scss
│ ├── _navigation.scss
│ ├── _forms.scss
│ └── _modal.scss
├── state/
│ ├── _states.scss
│ └── _animations.scss
├── theme/
│ ├── _default.scss
│ ├── _dark.scss
│ └── _corporate.scss
└── main.scss
/* main.scss – Import order is important */

/* Base styles first */
@import ‘base/reset’;
@import ‘base/typography’;
@import ‘base/base’;

/* Layout styles */
@import ‘layout/grid’;
@import ‘layout/header’;
@import ‘layout/footer’;
@import ‘layout/sidebar’;

/* Module styles */
@import ‘modules/buttons’;
@import ‘modules/cards’;
@import ‘modules/navigation’;
@import ‘modules/forms’;
@import ‘modules/modal’;

/* State styles */
@import ‘state/states’;
@import ‘state/animations’;

/* Theme styles last */
@import ‘theme/default’;
@import ‘theme/dark’;
@import ‘theme/corporate’;

SMACSS Naming Conventions

While SMACSS is more about categorization than naming, it does provide some naming guidelines to help identify the category and purpose of CSS rules:

Category
Naming Convention
Example
Base
HTML element selectors
body, h1, p
Layout
Prefix with “l-” or “layout-“
.l-header, .l-sidebar
Module
Component name + modifiers
.btn, .btn-primary
State
Prefix with “is-“
.is-active, .is-hidden
Theme
Descriptive theme names
.theme-dark, .theme-corporate

Best Practices for SMACSS Implementation

1. Keep Modules Independent

Ensure that modules can function independently regardless of their context. Avoid styling modules based on their parent containers.

/* Good – Module is independent */
.card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 20px;
}

/* Bad – Module depends on parent */
.sidebar .card {
width: 100%;
margin-bottom: 15px;
}

/* Better approach – Use modifier classes */
.card-sidebar {
width: 100%;
margin-bottom: 15px;
}

2. Use Depth of Applicability

Minimize the depth of your CSS selectors. Deep nesting makes styles harder to override and maintain.

/* Good – Shallow nesting */
.nav-item {
padding: 0.5rem;
}

.nav-link {
color: #6b7280;
text-decoration: none;
}

/* Bad – Deep nesting */
.nav .nav-list .nav-item .nav-link {
color: #6b7280;
text-decoration: none;
}

3. Minimize the Use of !important

Use !important sparingly and mainly for state rules where you need to override other styles.

/* Acceptable use in state rules */
.is-hidden {
display: none !important;
}

.is-disabled {
pointer-events: none !important;
opacity: 0.6 !important;
}

/* Avoid in regular module styles */
.btn {
background: #2563eb; /* Don’t use !important here */
}

SMACSS vs Other CSS Methodologies

Comparison with Other Methodologies

<tr style

Methodology Focus Strengths Best For
SMACSS Categorization Clear organization, scalability Large applications
BEM Naming conventions Clear relationships, specificity control Component-based projects
OOCSS Object orientation Reusability, performance Design systems