Sass Architecture and Organization

Module 7: CSS Preprocessors & Frameworks - Advanced Sass

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

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
graph TD A[main.scss] --> B[abstracts/] A --> C[base/] A --> D[components/] A --> E[layout/] A --> F[pages/] A --> G[themes/] A --> H[vendors/]

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

ITCSS (Inverted Triangle CSS)

ITCSS organizes CSS by specificity and reach, moving from generic, far-reaching styles to more specific, isolated ones.

graph TD A["Settings (Variables)"] --> B["Tools (Mixins, Functions)"] B --> C["Generic (Reset, Normalize)"] C --> D["Elements (Base HTML Elements)"] D --> E["Objects (Design Patterns)"] E --> F["Components (UI Components)"] F --> G["Utilities (Helper Classes)"]
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

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

Atomic Design

Atomic Design breaks interfaces down into five distinct levels: atoms, molecules, organisms, templates, and pages.

graph TD A["Atoms (Basic Elements)"] --> B["Molecules (Simple Components)"] B --> C["Organisms (Complex Components)"] C --> D["Templates (Page Layouts)"] D --> E["Pages (Specific Instances)"]
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

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

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

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:

  1. Tools and helpers (variables, functions, mixins)
  2. Vendor styles (if they need to be overridden)
  3. Base styles (resets, typography, etc.)
  4. Layout components
  5. UI components
  6. Page-specific styles
  7. 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:

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:

Breaking Down Monolithic Styles

For existing large projects, gradually refactor toward a better architecture:

  1. Identify and extract common variables and mixins first
  2. Refactor one component or section at a time
  3. Create a parallel structure and gradually migrate code
  4. Use linting tools to enforce new conventions
  5. Document your progress and roadmap

Practice Activities

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Documentation Creation: Create a comprehensive style guide document for a Sass project, including architecture, naming conventions, and usage examples.

Additional Resources

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

Next Steps

In our next module, we'll explore CSS Frameworks, starting with Bootstrap Fundamentals. Understanding Sass architecture will help you better customize and extend these frameworks for your projects.