Introduction to Sass Architecture
As projects grow in size and complexity, organizing your Sass code becomes crucial for maintainability, scalability, and collaboration. A well-planned Sass architecture helps prevent CSS specificity issues, reduces redundancy, and makes your codebase easier to understand and extend.
Analogy: Sass Architecture as City Planning
Think of Sass architecture as city planning. Just as cities have residential zones, commercial districts, and industrial areas with clear boundaries and transportation routes connecting them, a well-organized Sass project has distinct sections for different types of styles (base styles, layouts, components) with a clear system for how they interact. Without good planning, both cities and Sass projects can grow into chaotic, inefficient messes that are difficult to navigate and maintain. Good architecture creates order, promotes efficient resource usage, and accommodates future growth.
Key Benefits of Good Sass Architecture
- Maintainability: Easier to update and debug
- Scalability: Gracefully handles project growth
- Modularity: Components can be reused or modified independently
- Team Collaboration: Clear organization aids team understanding
- Performance: Well-organized code minimizes duplication and bloat
- Consistency: Enforces design and coding standards
Common Sass Architecture Methodologies
The 7-1 Pattern
One of the most popular Sass architecture patterns is the 7-1 pattern: 7 folders, 1 file. It's excellent for large projects with many components and pages.
sass/
|
|– abstracts/ # Sass tools, helpers, variables, functions, mixins
| |– _variables.scss # Global variables
| |– _functions.scss # Custom functions
| |– _mixins.scss # Mixins and utilities
| |– _placeholders.scss # Placeholder selectors for @extend
|
|– base/ # Foundational styles
| |– _reset.scss # CSS reset/normalize
| |– _typography.scss # Typography rules
| |– _animations.scss # Animations
| |– _base.scss # Base HTML element styles
|
|– components/ # Reusable UI components
| |– _buttons.scss # Buttons
| |– _cards.scss # Cards
| |– _forms.scss # Forms
| |– _modals.scss # Modals
| |– _navigation.scss # Navigation
|
|– layout/ # Layout components
| |– _header.scss # Header
| |– _footer.scss # Footer
| |– _grid.scss # Grid system
| |– _sidebar.scss # Sidebar
|
|– pages/ # Page-specific styles
| |– _home.scss # Home page
| |– _about.scss # About page
| |– _contact.scss # Contact page
|
|– themes/ # Theme-specific styles
| |– _default.scss # Default theme
| |– _dark.scss # Dark theme
| |– _admin.scss # Admin theme
|
|– vendors/ # Third-party styles
| |– _bootstrap.scss # Bootstrap customization
| |– _jquery-ui.scss # jQuery UI customization
|
|– main.scss # Main Sass file that imports everything
The main.scss file typically imports all partials in the correct order:
// main.scss
// 1. Abstracts (no CSS output)
@import 'abstracts/variables';
@import 'abstracts/functions';
@import 'abstracts/mixins';
@import 'abstracts/placeholders';
// 2. Vendors (third-party CSS)
@import 'vendors/bootstrap';
@import 'vendors/jquery-ui';
// 3. Base styles
@import 'base/reset';
@import 'base/typography';
@import 'base/animations';
@import 'base/base';
// 4. Layout styles
@import 'layout/header';
@import 'layout/footer';
@import 'layout/grid';
@import 'layout/sidebar';
// 5. Components
@import 'components/buttons';
@import 'components/cards';
@import 'components/forms';
@import 'components/modals';
@import 'components/navigation';
// 6. Page-specific styles
@import 'pages/home';
@import 'pages/about';
@import 'pages/contact';
// 7. Themes
@import 'themes/default';
@import 'themes/dark';
@import 'themes/admin';
When to Use the 7-1 Pattern
- Large-scale projects with many unique pages and components
- Team environments where clear organization is crucial
- Projects that require multiple themes or complex layouts
ITCSS (Inverted Triangle CSS)
ITCSS organizes CSS by specificity and reach, moving from generic, far-reaching styles to more specific, isolated ones.
sass/
|
|– settings/ # Variables, config
| |– _colors.scss # Color variables
| |– _typography.scss # Typography variables
| |– _spacing.scss # Spacing/sizing variables
|
|– tools/ # Functions and mixins
| |– _functions.scss # Global functions
| |– _mixins.scss # Global mixins
|
|– generic/ # Ground-zero styles
| |– _normalize.scss # CSS normalize
| |– _reset.scss # CSS reset
| |– _box-sizing.scss # Global box sizing
|
|– elements/ # HTML element styling
| |– _headings.scss # h1-h6 styles
| |– _links.scss # a styles
| |– _lists.scss # ul, ol, dl styles
| |– _forms.scss # form element styles
|
|– objects/ # Design patterns/objects
| |– _container.scss # Container object
| |– _media.scss # Media object
| |– _grid.scss # Grid object
|
|– components/ # UI components
| |– _buttons.scss # Buttons
| |– _cards.scss # Cards
| |– _modals.scss # Modals
|
|– utilities/ # Utility/helper classes
| |– _spacing.scss # Margin/padding helpers
| |– _text.scss # Text helpers
| |– _display.scss # Display helpers
| |– _visibility.scss # Visibility helpers
|
|– main.scss # Main Sass file
When to Use ITCSS
- Projects where controlling CSS specificity is a priority
- Situations where you need to integrate with existing CSS
- Large codebases with many contributors
SMACSS (Scalable and Modular Architecture for CSS)
SMACSS categorizes CSS rules into five categories: Base, Layout, Module, State, and Theme.
sass/
|
|– base/ # Base rules
| |– _reset.scss # Reset/normalize
| |– _base.scss # Base element styles
|
|– layout/ # Layout rules
| |– _grid.scss # Grid system
| |– _header.scss # Header
| |– _footer.scss # Footer
|
|– modules/ # Module rules
| |– _buttons.scss # Buttons
| |– _cards.scss # Cards
| |– _navigation.scss # Navigation
|
|– states/ # State rules
| |– _states.scss # States (active, hover, etc.)
|
|– themes/ # Theme rules
| |– _theme.scss # Theme variables and overrides
|
|– main.scss # Main Sass file
When to Use SMACSS
- When the project has clear distinctions between layout and modules
- When you need separate state management for interactive components
- Medium-sized projects with a focus on component reusability
Atomic Design
Atomic Design breaks interfaces down into five distinct levels: atoms, molecules, organisms, templates, and pages.
sass/
|
|– atoms/ # Fundamental building blocks
| |– _buttons.scss # Button atoms
| |– _inputs.scss # Form input atoms
| |– _typography.scss # Typography atoms
|
|– molecules/ # Combinations of atoms
| |– _search-form.scss # Search form molecule
| |– _navigation-item.scss # Nav item molecule
| |– _card-header.scss # Card header molecule
|
|– organisms/ # Complex components
| |– _header.scss # Header organism
| |– _product-grid.scss # Product grid organism
| |– _footer.scss # Footer organism
|
|– templates/ # Layout templates
| |– _product-page.scss # Product page template
| |– _article-page.scss # Article page template
|
|– pages/ # Specific page instances
| |– _home.scss # Home page
| |– _about.scss # About page
|
|– main.scss # Main Sass file
When to Use Atomic Design
- Design systems and pattern libraries
- Projects with many reusable and nested components
- When you want to encourage component reuse and composition
Choosing an Architecture
The best architecture depends on your project's specific needs:
| Factor | Best Architecture |
|---|---|
| Small project with few components | Simplified 7-1 or SMACSS |
| Large project with many pages | 7-1 Pattern |
| Design system or pattern library | Atomic Design |
| Legacy project with specificity issues | ITCSS |
| Component-based framework (React, Vue) | Component-centric (see next section) |
You can also combine aspects of different architectures. For example, you might use the folder structure of 7-1 but organize your CSS files with ITCSS principles of increasing specificity.
Modern Component-Based Architecture
With the rise of component-based frameworks like React, Vue, and Angular, Sass architecture has evolved to complement these approaches.
Component-Centric Organization
In component-based applications, styles are often organized alongside the components they style:
src/
|
|– components/
| |– Button/
| | |– Button.jsx # Component code
| | |– Button.scss # Component styles
| | |– index.js # Export
| |
| |– Card/
| | |– Card.jsx # Component code
| | |– Card.scss # Component styles
| | |– index.js # Export
| |
| |– Header/
| |– Header.jsx # Component code
| |– Header.scss # Component styles
| |– index.js # Export
|
|– styles/
|– abstracts/
| |– _variables.scss
| |– _mixins.scss
|
|– base/
| |– _reset.scss
| |– _typography.scss
|
|– main.scss # Imports global styles (not component styles)
This approach keeps component styles encapsulated and co-located with their corresponding component code, making it easier to maintain and update components.
CSS Modules and Scoped Styles
Modern frameworks often offer ways to scope styles to specific components, reducing the need for complex naming conventions:
// Button.module.scss
.button {
padding: 10px 15px;
border-radius: 4px;
&.primary {
background-color: #0066cc;
color: white;
}
&.secondary {
background-color: transparent;
border: 1px solid #0066cc;
color: #0066cc;
}
}
// In React with CSS Modules
import styles from './Button.module.scss';
function Button({ variant = 'primary', children }) {
const buttonClass = `${styles.button} ${styles[variant]}`;
return ;
}
Global Styles in Component-Based Architecture
Even in component-based architectures, you'll typically still have global styles for things like variables, resets, and utility classes:
// _variables.scss (global)
$primary-color: #0066cc;
$secondary-color: #f5f5f5;
$border-radius: 4px;
$font-family: 'Inter', sans-serif;
// Component-specific file
@import '../../styles/abstracts/variables';
.card {
border-radius: $border-radius;
font-family: $font-family;
// Component-specific styles
}
Naming Conventions and Methodologies
Consistent naming conventions make your code more predictable and easier to maintain.
BEM (Block, Element, Modifier)
BEM is a naming convention that divides components into Blocks, Elements, and Modifiers:
/* Block component */
.card {
background: white;
border-radius: 4px;
}
/* Element that depends on the block */
.card__title {
font-size: 18px;
font-weight: bold;
}
.card__content {
padding: 15px;
}
/* Modifier that changes the style of the block */
.card--featured {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
.card--dark {
background: #222;
color: white;
}
BEM works particularly well with Sass nesting:
.card {
background: white;
border-radius: 4px;
// Elements
&__title {
font-size: 18px;
font-weight: bold;
}
&__content {
padding: 15px;
}
// Modifiers
&--featured {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}
&--dark {
background: #222;
color: white;
.card__title {
color: #f5f5f5;
}
}
}
SUIT CSS Naming Convention
SUIT CSS is another naming methodology that uses PascalCase for components, camelCase for variants, and dashes for modifiers:
/* Component */
.Button { }
/* Component variant */
.Button--primary { }
.Button--large { }
/* Component descendant */
.Button-icon { }
/* Component state */
.Button.is-disabled { }
OOCSS (Object-Oriented CSS)
OOCSS focuses on separating structure from skin and container from content:
/* Structure */
.module {
padding: 15px;
border-radius: 4px;
}
/* Skin */
.module-light {
background: white;
color: #333;
}
.module-dark {
background: #222;
color: white;
}
/* Usage */
Utility-First Approach (like Tailwind CSS)
Utility-first CSS uses small, single-purpose classes applied directly in the HTML:
/* Instead of custom component classes */
.card {
background: white;
padding: 15px;
border-radius: 4px;
margin-bottom: 15px;
}
/* Use utility classes */
In Sass, you can generate utility classes using loops:
// Generate padding utilities
$spacings: (
0: 0,
1: 0.25rem,
2: 0.5rem,
3: 1rem,
4: 1.5rem,
5: 3rem
);
@each $key, $value in $spacings {
.p-#{$key} {
padding: $value;
}
.px-#{$key} {
padding-left: $value;
padding-right: $value;
}
.py-#{$key} {
padding-top: $value;
padding-bottom: $value;
}
}
Hybrid Approaches
Many projects combine multiple naming conventions based on their needs:
// Component with BEM
.card {
&__title { /* ... */ }
&__content { /* ... */ }
&--featured { /* ... */ }
}
// General utilities
.mb-4 { margin-bottom: 1rem; }
.text-center { text-align: center; }
// Usage
Title
Content
File Organization Best Practices
Index Files for Folder Imports
Use index files to simplify imports from folders:
// abstracts/_index.scss
@forward 'variables';
@forward 'functions';
@forward 'mixins';
@forward 'placeholders';
// main.scss
@use 'abstracts' as *;
// Instead of:
// @use 'abstracts/variables' as *;
// @use 'abstracts/functions' as *;
// @use 'abstracts/mixins' as *;
// @use 'abstracts/placeholders' as *;
File Naming Conventions
- Use a leading underscore for partials:
_filename.scss - Use kebab-case for file names:
_button-styles.scss - Be descriptive and specific:
_form-validation.scssinstead of_forms.scss - Group related files with prefixes:
_util-spacing.scss,_util-typography.scss
Keep Files Small and Focused
Each file should have a single responsibility:
// Bad: One large file
// _forms.scss (500+ lines covering all form elements, validation, states)
// Better: Multiple focused files
// _form-elements.scss (inputs, selects, textareas)
// _form-layout.scss (form layout and structure)
// _form-validation.scss (validation states and messages)
// _custom-inputs.scss (custom checkboxes, radio buttons, etc.)
Order of Imports
Import files in order of dependency, from most generic to most specific:
- Tools and helpers (variables, functions, mixins)
- Vendor styles (if they need to be overridden)
- Base styles (resets, typography, etc.)
- Layout components
- UI components
- Page-specific styles
- Themes and overrides
Documentation
Document your architecture with a README file:
# Sass Architecture
This project uses a modified 7-1 pattern for Sass organization.
## Folder Structure
- **abstracts/**: Variables, mixins, functions, and placeholders
- **base/**: Reset, typography, animations, and base element styles
- **components/**: Self-contained, reusable UI components
- **layout/**: Structural layout components
- **pages/**: Page-specific styles
- **themes/**: Theme variations
- **vendors/**: Third-party styles
## Naming Conventions
We use BEM naming convention:
- `.block` for components
- `.block__element` for component parts
- `.block--modifier` for variations
## Utilities
Utility classes are prefixed with their category:
- `.m-*` for margins
- `.p-*` for padding
- `.text-*` for text utilities
## Breakpoints
Mobile-first approach with breakpoints at:
- 576px (sm)
- 768px (md)
- 992px (lg)
- 1200px (xl)
Sass Tools for Better Organization
Using @use and @forward (Modern Sass)
Modern Sass (since Dart Sass 1.23.0) offers @use and @forward
to replace @import with better namespacing and encapsulation:
// abstracts/_colors.scss
$primary: #0066cc;
$secondary: #f5f5f5;
// abstracts/_index.scss
@forward 'colors';
@forward 'typography';
@forward 'spacing';
// components/_button.scss
@use '../abstracts' as a;
.button {
background-color: a.$primary;
color: white;
padding: a.$spacing-md;
}
Configuration with Maps
Use Sass maps to organize related configuration values:
// _variables.scss
// Instead of many individual variables
$font-size-xs: 0.75rem;
$font-size-sm: 0.875rem;
$font-size-md: 1rem;
$font-size-lg: 1.125rem;
$font-size-xl: 1.25rem;
// Use a map for better organization
$font-sizes: (
'xs': 0.75rem,
'sm': 0.875rem,
'md': 1rem,
'lg': 1.125rem,
'xl': 1.25rem
);
// Access with map-get
$body-font-size: map-get($font-sizes, 'md');
Themes with CSS Custom Properties
Combine Sass organization with CSS custom properties for flexible theming:
// _themes.scss
// Define theme values in Sass
$themes: (
'light': (
'bg-color': #ffffff,
'text-color': #333333,
'primary-color': #0066cc
),
'dark': (
'bg-color': #121212,
'text-color': #f5f5f5,
'primary-color': #4d9fff
)
);
// Generate CSS custom properties
:root {
// Default theme (light)
--bg-color: #{map-get(map-get($themes, 'light'), 'bg-color')};
--text-color: #{map-get(map-get($themes, 'light'), 'text-color')};
--primary-color: #{map-get(map-get($themes, 'light'), 'primary-color')};
}
// Dark theme
.theme-dark {
--bg-color: #{map-get(map-get($themes, 'dark'), 'bg-color')};
--text-color: #{map-get(map-get($themes, 'dark'), 'text-color')};
--primary-color: #{map-get(map-get($themes, 'dark'), 'primary-color')};
}
// Usage in components
body {
background-color: var(--bg-color);
color: var(--text-color);
}
.button {
background-color: var(--primary-color);
color: white;
}
Shared Config Files
For large projects, create a central configuration file that can be imported everywhere:
// config.scss
$grid-columns: 12;
$grid-gutter: 30px;
$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px
);
$colors: (
'primary': #0066cc,
'secondary': #f5f5f5,
'success': #28a745,
'danger': #dc3545,
'warning': #ffc107,
'info': #17a2b8
);
$font-families: (
'heading': ('Roboto', sans-serif),
'body': ('Open Sans', sans-serif),
'mono': ('Source Code Pro', monospace)
);
// Functions to access config
@function color($key) {
@return map-get($colors, $key);
}
@function breakpoint($key) {
@return map-get($breakpoints, $key);
}
@function font-family($key) {
@return map-get($font-families, $key);
}
Real-World Examples
Bootstrap Sass Organization
Bootstrap, one of the most popular CSS frameworks, uses a well-organized Sass architecture:
bootstrap/
|
|– scss/
| |– _functions.scss
| |– _variables.scss
| |– _mixins.scss
| |– _root.scss
| |– _reboot.scss
| |– _type.scss
| |– _images.scss
| |– _grid.scss
| |– _forms.scss
| |– _buttons.scss
| |– _transitions.scss
| |– _dropdown.scss
| |– _nav.scss
| |– _navbar.scss
| |– ...more component files
| |– _utilities.scss
|
|– _utilities/
| |– _api.scss
| |– ...utility api files
|
|– mixins/
| |– _breakpoints.scss
| |– _grid.scss
| |– _buttons.scss
| |– ...more mixin files
|
|– bootstrap.scss
|– bootstrap-grid.scss
|– bootstrap-reboot.scss
Shopify's Polaris Design System
Shopify's Polaris design system uses a component-based architecture with shared styles:
polaris/
|
|– styles/
| |– foundation/
| | |– _colors.scss
| | |– _spacing.scss
| | |– _typography.scss
| |
| |– global/
| | |– _reset.scss
| | |– _base.scss
| |
| |– shared/
| |– _buttons.scss
| |– _forms.scss
|
|– components/
|– Button/
| |– Button.scss
| |– Button.tsx
| |– index.ts
|
|– Card/
| |– Card.scss
| |– Card.tsx
| |– index.ts
|
|– ...more component folders
Material-UI Sass Architecture
Material-UI uses a theme-based approach with consistent variables:
material-components-web/
|
|– theme/
| |– _functions.scss
| |– _variables.scss
| |– _constants.scss
| |– _mixins.scss
| |– _color-palette.scss
|
|– button/
| |– _variables.scss
| |– _mixins.scss
| |– _functions.scss
| |– mdc-button.scss
|
|– card/
| |– _variables.scss
| |– _mixins.scss
| |– mdc-card.scss
|
|– ...more component folders
Managing Large-Scale Projects
Style Guide and Documentation
For large teams, create a comprehensive style guide:
- Document your architecture and folder structure
- Include naming conventions and coding standards
- Provide examples for common patterns
- Keep a living component library (using tools like Storybook)
Scalable Folder Structure for Large Projects
For very large projects, consider a modular approach:
src/
|
|– core/ # Core styles shared across features
| |– abstracts/
| |– base/
| |– components/
| |– layout/
|
|– features/ # Feature-specific styles
| |– auth/ # Authentication feature
| | |– components/
| | |– pages/
| |
| |– products/ # Product feature
| | |– components/
| | |– pages/
| |
| |– checkout/ # Checkout feature
| |– components/
| |– pages/
|
|– themes/ # Theme variations
| |– default/
| |– dark/
|
|– vendors/ # Third-party styles
|
|– main.scss # Main entry point
Performance Optimization
Keep your compiled CSS lean:
-
Code Splitting: Split CSS into smaller, feature-specific files
// main.scss @import 'core'; // Conditionally import only the features needed @import 'features/products'; @import 'features/checkout'; -
Purge Unused CSS: Use tools like PurgeCSS to remove unused styles
// postcss.config.js module.exports = { plugins: [ require('autoprefixer'), require('@fullhuman/postcss-purgecss')({ content: ['./src/**/*.html', './src/**/*.js'], defaultExtractor: content => content.match(/[\w-/:]+(? - Critical CSS: Extract and inline critical styles for faster rendering
Breaking Down Monolithic Styles
For existing large projects, gradually refactor toward a better architecture:
- Identify and extract common variables and mixins first
- Refactor one component or section at a time
- Create a parallel structure and gradually migrate code
- Use linting tools to enforce new conventions
- Document your progress and roadmap
Practice Activities
- Architecture Comparison: Choose two different Sass architecture methodologies (e.g., 7-1 Pattern and ITCSS) and create folder structures for both. Explain the pros and cons of each approach for a specific project scenario.
- Project Refactoring: Take a small existing CSS project (or create one) with disorganized styles and refactor it using a structured Sass architecture. Document your process and the improvements made.
- Component Library Setup: Create a simple component library using an atomic design approach. Include at least one component from each level (atom, molecule, organism) and organize the Sass files appropriately.
- Theme System Design: Implement a theme system that allows for multiple color schemes (light, dark, high contrast) using Sass variables, maps, and CSS custom properties.
- Documentation Creation: Create a comprehensive style guide document for a Sass project, including architecture, naming conventions, and usage examples.
Additional Resources
- Sass Guidelines - A comprehensive guide to writing better Sass
- Bootstrap Sass Code - Real-world example of Sass organization
- CSS Namespaces - Advanced naming techniques
- CSS Architectures for UI Components
- Atomic Design Methodology - Brad Frost's original article
- Shopify Polaris - Open-source design system with Sass
Key Takeaways
- A well-planned Sass architecture is crucial for maintainability and scalability
- Common methodologies include the 7-1 Pattern, ITCSS, SMACSS, and Atomic Design
- Choose an architecture based on your project size, team, and requirements
- Modern component-based applications often use a hybrid approach
- Consistent naming conventions like BEM help organize your code
- Use Sass features like maps, modules, and partials to better organize your code
- Document your architecture and standards for better team collaboration
- Optimize performance by reducing unused CSS and code splitting