🏗️ CSS Architecture

Organizing & Scaling CSS

CSS Architecture & Methodologies

Structure and organize CSS for maintainability, scalability, and team collaboration. These methodologies prevent chaos in large projects.

💻 BEM (Block Element Modifier)

/* BEM Naming Convention */
/* Block: standalone component */
.card { }

/* Element: part of block (double underscore) */
.card__title { }
.card__image { }
.card__description { }
.card__button { }

/* Modifier: variation of block or element (double dash) */
.card--featured { }
.card--large { }
.card__button--primary { }
.card__button--disabled { }

/* Complete example */
<div class="card card--featured">
    <img class="card__image" src="photo.jpg" alt="Photo">
    <h3 class="card__title">Card Title</h3>
    <p class="card__description">Description text</p>
    <button class="card__button card__button--primary">Read More</button>
</div>

/* CSS */
.card {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 1rem;
}

.card--featured {
    border-color: #007bff;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}

.card__image {
    width: 100%;
    border-radius: 4px;
}

.card__title {
    font-size: 1.5rem;
    margin: 1rem 0 0.5rem;
}

.card__description {
    color: #666;
    margin-bottom: 1rem;
}

.card__button {
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.card__button--primary {
    background: #007bff;
    color: white;
}

.card__button--disabled {
    background: #ccc;
    cursor: not-allowed;
}

/* Benefits */
/* - Clear relationship between classes */
/* - No specificity issues */
/* - Easy to understand component structure */
/* - Prevents naming conflicts */

🎯 OOCSS (Object Oriented CSS)

/* Principle 1: Separate structure from skin */

/* Structure (layout, positioning) */
.box {
    display: block;
    padding: 1rem;
    margin-bottom: 1rem;
}

/* Skin (colors, fonts) */
.box-primary {
    background: #007bff;
    color: white;
    border-radius: 4px;
}

.box-secondary {
    background: #6c757d;
    color: white;
    border-radius: 4px;
}

/* Use together */
<div class="box box-primary">Primary Box</div>
<div class="box box-secondary">Secondary Box</div>

/* Principle 2: Separate container from content */

/* Bad - tightly coupled */
.sidebar h3 {
    font-size: 1.5rem;
    color: #333;
}

/* Good - reusable */
.heading-medium {
    font-size: 1.5rem;
    color: #333;
}

/* Media object pattern */
.media {
    display: flex;
    gap: 1rem;
}

.media__image {
    flex-shrink: 0;
}

.media__body {
    flex: 1;
}

/* Reusable in any context */
<div class="media">
    <img class="media__image" src="avatar.jpg" alt="Avatar">
    <div class="media__body">
        <h4>Username</h4>
        <p>Bio text</p>
    </div>
</div>

📐 SMACSS (Scalable and Modular Architecture)

/* Five categories */

/* 1. Base - element selectors */
/* base.css */
html {
    box-sizing: border-box;
}

*, *::before, *::after {
    box-sizing: inherit;
}

body {
    font-family: system-ui, sans-serif;
    line-height: 1.5;
    color: #333;
}

a {
    color: #007bff;
    text-decoration: none;
}

/* 2. Layout - major page sections */
/* layout.css */
.l-header {
    position: sticky;
    top: 0;
    z-index: 100;
}

.l-sidebar {
    width: 250px;
}

.l-main {
    flex: 1;
}

.l-footer {
    margin-top: auto;
}

.l-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

/* 3. Module - reusable components */
/* modules/button.css */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.btn-primary {
    background: #007bff;
    color: white;
}

.btn-large {
    padding: 1rem 2rem;
    font-size: 1.125rem;
}

/* modules/card.css */
.card {
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    padding: 1rem;
}

.card-header {
    border-bottom: 1px solid #eee;
    padding-bottom: 0.5rem;
    margin-bottom: 1rem;
}

/* 4. State - how things look in different states */
/* state.css */
.is-hidden {
    display: none;
}

.is-visible {
    display: block;
}

.is-active {
    font-weight: bold;
    color: #007bff;
}

.is-disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

.is-loading {
    position: relative;
    color: transparent;
}

.is-error {
    border-color: #dc3545;
    color: #dc3545;
}

/* 5. Theme - color schemes */
/* theme.css */
.theme-dark {
    --bg-color: #1a1a1a;
    --text-color: #f0f0f0;
    --border-color: #333;
}

.theme-light {
    --bg-color: #ffffff;
    --text-color: #333333;
    --border-color: #ddd;
}

⚛️ Atomic CSS / Utility-First

/* Single-purpose utility classes */

/* Spacing */
.m-0 { margin: 0; }
.m-1 { margin: 0.25rem; }
.m-2 { margin: 0.5rem; }
.m-3 { margin: 1rem; }
.m-4 { margin: 1.5rem; }

.mt-1 { margin-top: 0.25rem; }
.mr-2 { margin-right: 0.5rem; }
.mb-3 { margin-bottom: 1rem; }
.ml-4 { margin-left: 1.5rem; }

.p-2 { padding: 0.5rem; }
.px-3 { padding-left: 1rem; padding-right: 1rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }

/* Display */
.block { display: block; }
.inline { display: inline; }
.inline-block { display: inline-block; }
.flex { display: flex; }
.grid { display: grid; }
.hidden { display: none; }

/* Flexbox */
.flex-row { flex-direction: row; }
.flex-col { flex-direction: column; }
.justify-center { justify-content: center; }
.justify-between { justify-content: space-between; }
.items-center { align-items: center; }
.gap-2 { gap: 0.5rem; }

/* Text */
.text-center { text-align: center; }
.text-left { text-align: left; }
.text-right { text-align: right; }
.font-bold { font-weight: bold; }
.text-sm { font-size: 0.875rem; }
.text-lg { font-size: 1.125rem; }

/* Colors */
.text-primary { color: #007bff; }
.text-danger { color: #dc3545; }
.bg-white { background: white; }
.bg-gray { background: #f0f0f0; }

/* Borders */
.border { border: 1px solid #ddd; }
.rounded { border-radius: 4px; }
.rounded-full { border-radius: 9999px; }

/* Usage */
<div class="flex items-center gap-2 p-3 border rounded bg-white">
    <img class="rounded-full" src="avatar.jpg" alt="Avatar">
    <div class="flex-1">
        <h3 class="text-lg font-bold m-0">Username</h3>
        <p class="text-sm text-gray-600 m-0">Description</p>
    </div>
</div>

/* Pros: rapid development, consistent spacing, no naming */
/* Cons: verbose HTML, learning curve, harder to read */

📁 File Organization

/* 7-1 Pattern (Sass) */
sass/
├── abstracts/
│   ├── _variables.scss    /* Colors, fonts, spacing */
│   ├── _functions.scss    /* Sass functions */
│   ├── _mixins.scss       /* Reusable mixins */
├── base/
│   ├── _reset.scss        /* CSS reset */
│   ├── _typography.scss   /* Font styles */
│   ├── _base.scss         /* Base element styles */
├── components/
│   ├── _button.scss
│   ├── _card.scss
│   ├── _form.scss
│   ├── _modal.scss
├── layout/
│   ├── _header.scss
│   ├── _footer.scss
│   ├── _sidebar.scss
│   ├── _grid.scss
├── pages/
│   ├── _home.scss
│   ├── _about.scss
│   ├── _contact.scss
├── themes/
│   ├── _dark.scss
│   ├── _light.scss
├── vendors/
│   ├── _normalize.scss
└── main.scss              /* Import all partials */

/* main.scss */
/* Abstracts */
@import 'abstracts/variables';
@import 'abstracts/functions';
@import 'abstracts/mixins';

/* Base */
@import 'base/reset';
@import 'base/typography';
@import 'base/base';

/* Layout */
@import 'layout/header';
@import 'layout/footer';
@import 'layout/sidebar';
@import 'layout/grid';

/* Components */
@import 'components/button';
@import 'components/card';
@import 'components/form';
@import 'components/modal';

/* Pages */
@import 'pages/home';
@import 'pages/about';

/* Themes */
@import 'themes/dark';
@import 'themes/light';

/* Alternative: ITCSS (Inverted Triangle) */
/* Order by specificity (generic to specific) */
styles/
├── settings/      /* Variables, config */
├── tools/         /* Mixins, functions */
├── generic/       /* Reset, normalize */
├── elements/      /* Base element styles */
├── objects/       /* Layout patterns (OOCSS) */
├── components/    /* UI components */
├── utilities/     /* Helper classes */

/* Alternative: Component-based (React/Vue) */
components/
├── Button/
│   ├── Button.jsx
│   ├── Button.module.css
│   └── Button.test.js
├── Card/
│   ├── Card.jsx
│   ├── Card.module.css
│   └── Card.test.js

🎨 CSS-in-JS Patterns

/* Styled Components (React) */
import styled from 'styled-components';

const Button = styled.button`
    padding: 0.5rem 1rem;
    background: ${props => props.primary ? '#007bff' : '#6c757d'};
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    
    &:hover {
        opacity: 0.9;
    }
    
    &:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }
`;

/* Usage */
<Button primary>Primary</Button>
<Button>Secondary</Button>

/* CSS Modules */
/* Button.module.css */
.button {
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.primary {
    background: #007bff;
    color: white;
}

/* Button.jsx */
import styles from './Button.module.css';

function Button({ primary, children }) {
    return (
        <button className={`${styles.button} ${primary ? styles.primary : ''}`}>
            {children}
        </button>
    );
}

/* Tailwind CSS */
<button class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
    Button
</button>

🎯 Best Practices

/* 1. Use consistent naming convention */
/* Choose one: BEM, SMACSS, or utility-first */

/* 2. Keep specificity low */
/* Bad - high specificity */
div#header nav ul li a.active {
    color: blue;
}

/* Good - low specificity */
.nav-link.is-active {
    color: blue;
}

/* 3. Avoid !important */
/* Use proper specificity instead */

/* 4. Group related properties */
.element {
    /* Positioning */
    position: absolute;
    top: 0;
    left: 0;
    
    /* Display & Box Model */
    display: flex;
    width: 100%;
    padding: 1rem;
    margin: 1rem 0;
    
    /* Typography */
    font-size: 1rem;
    line-height: 1.5;
    color: #333;
    
    /* Visual */
    background: white;
    border: 1px solid #ddd;
    border-radius: 4px;
    
    /* Misc */
    cursor: pointer;
}

/* 5. Use CSS variables for theming */
:root {
    --color-primary: #007bff;
    --color-secondary: #6c757d;
    --spacing-unit: 0.5rem;
}

.button {
    background: var(--color-primary);
    padding: calc(var(--spacing-unit) * 2);
}

/* 6. Mobile-first media queries */
/* Base styles (mobile) */
.container {
    width: 100%;
    padding: 1rem;
}

/* Tablet and up */
@media (min-width: 768px) {
    .container {
        padding: 2rem;
    }
}

/* Desktop and up */
@media (min-width: 1024px) {
    .container {
        max-width: 1200px;
        margin: 0 auto;
    }
}

/* 7. Component-based thinking */
/* Each component should be self-contained */

/* 8. Document your CSS */
/**
 * Card Component
 * 
 * A flexible card component with optional header and footer.
 * 
 * @example
 * 
*
Header
*
Content
* *
*/ .card { } /* 9. Use linters and formatters */ /* Stylelint, Prettier for consistent code */ /* 10. Optimize for performance */ /* Minimize file size */ /* Use CSS minification */ /* Leverage caching */ /* Critical CSS for above-the-fold content */

🔍 Practical Example: Complete System

/* Using BEM + SMACSS hybrid */

/* Layout */
.l-page {
    display: grid;
    grid-template-rows: auto 1fr auto;
    min-height: 100vh;
}

.l-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

/* Header Component (BEM) */
.header {
    background: white;
    border-bottom: 1px solid #eee;
    padding: 1rem 0;
}

.header__nav {
    display: flex;
    gap: 2rem;
    list-style: none;
    margin: 0;
    padding: 0;
}

.header__link {
    color: #333;
    text-decoration: none;
}

.header__link:hover {
    color: #007bff;
}

.header__link--active {
    color: #007bff;
    font-weight: bold;
}

/* Card Component (BEM) */
.card {
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    overflow: hidden;
}

.card--featured {
    border: 2px solid #007bff;
}

.card__image {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

.card__content {
    padding: 1rem;
}

.card__title {
    font-size: 1.5rem;
    margin: 0 0 0.5rem;
}

.card__description {
    color: #666;
    margin: 0 0 1rem;
}

.card__footer {
    border-top: 1px solid #eee;
    padding: 1rem;
    display: flex;
    justify-content: space-between;
}

/* Button Component (BEM) */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1rem;
    text-decoration: none;
    text-align: center;
    transition: opacity 0.2s;
}

.btn:hover {
    opacity: 0.9;
}

.btn--primary {
    background: #007bff;
    color: white;
}

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

.btn--outline {
    background: transparent;
    border: 1px solid currentColor;
}

.btn--large {
    padding: 1rem 2rem;
    font-size: 1.125rem;
}

/* State classes (SMACSS) */
.is-hidden {
    display: none;
}

.is-loading {
    opacity: 0.6;
    pointer-events: none;
}

/* Usage */
<div class="l-page">
    <header class="header">
        <div class="l-container">
            <nav>
                <ul class="header__nav">
                    <li><a href="/" class="header__link header__link--active">Home</a></li>
                    <li><a href="/about" class="header__link">About</a></li>
                </ul>
            </nav>
        </div>
    </header>
    
    <main class="l-container">
        <div class="card card--featured">
            <img class="card__image" src="photo.jpg" alt="Photo">
            <div class="card__content">
                <h2 class="card__title">Card Title</h2>
                <p class="card__description">Description text</p>
            </div>
            <div class="card__footer">
                <button class="btn btn--primary">Learn More</button>
                <button class="btn btn--outline">Share</button>
            </div>
        </div>
    </main>
</div>

🎯 Key Takeaways