CSS Architecture and Methodology

1. CSS Naming Conventions (BEM, OOCSS, SMACSS)

Methodology Pattern Description Example
BEM (Block Element Modifier) .block__element--modifier Strict naming convention for components .card__title--large
BEM Block .block Standalone component/entity .menu, .button
BEM Element .block__element Part of block, no standalone meaning .menu__item, .button__icon
BEM Modifier .block--modifier Different state or version of block .button--primary, .menu--vertical
OOCSS (Object Oriented CSS) Separate structure and skin Reusable visual patterns as objects .media, .button
SMACSS (Scalable Modular Architecture) 5 categories of rules Base, Layout, Module, State, Theme .l-sidebar, .is-active
ITCSS (Inverted Triangle CSS) Layered architecture Generic to specific, low to high specificity Settings → Tools → Generic → Elements → Objects → Components → Utilities
CUBE CSS Composition, Utility, Block, Exception Modern methodology with design tokens Combine composition classes with utilities

Example: BEM naming convention

/* Block: standalone component */
.card {
    display: flex;
    flex-direction: column;
    background: white;
    border-radius: 8px;
    padding: 1rem;
}

/* Elements: parts of the block */
.card__header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 1rem;
}

.card__title {
    font-size: 1.5rem;
    font-weight: bold;
}

.card__subtitle {
    font-size: 0.875rem;
    color: #666;
}

.card__body {
    flex: 1;
    line-height: 1.6;
}

.card__footer {
    display: flex;
    gap: 0.5rem;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid #eee;
}

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

/* Modifiers: variations */
.card--featured {
    border: 2px solid #007acc;
    box-shadow: 0 4px 8px rgba(0,122,204,0.2);
}

.card--compact {
    padding: 0.5rem;
}

.card__title--large {
    font-size: 2rem;
}

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

.card__button--secondary {
    background: transparent;
    border: 1px solid #007acc;
    color: #007acc;
}

/* HTML structure */
/*
<div class="card card--featured">
    <div class="card__header">
        <h2 class="card__title card__title--large">Title</h2>
    </div>
    <div class="card__body">Content</div>
    <div class="card__footer">
        <button class="card__button card__button--primary">Action</button>
        <button class="card__button card__button--secondary">Cancel</button>
    </div>
</div>
*/

Example: OOCSS (Object Oriented CSS)

/* Separate structure from skin */

/* Structure: layout and positioning */
.media {
    display: flex;
    align-items: flex-start;
}

.media__figure {
    margin-right: 1rem;
}

.media__body {
    flex: 1;
}

/* Skin: visual appearance */
.skin-default {
    background: white;
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 1rem;
}

.skin-primary {
    background: #007acc;
    color: white;
    padding: 1rem;
}

/* Combine structure and skin */
/*
<div class="media skin-default">
    <div class="media__figure">...</div>
    <div class="media__body">...</div>
</div>
*/

/* Separate container from content */
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}

.box {
    padding: 1rem;
    margin-bottom: 1rem;
}

/* Content is independent of container */
.box-content {
    line-height: 1.6;
}

/* Reusable button object */
.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1rem;
    text-align: center;
    text-decoration: none;
}

/* Skin variations */
.btn-primary {
    background: #007acc;
    color: white;
}

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

.btn-large {
    padding: 0.75rem 1.5rem;
    font-size: 1.125rem;
}

Example: SMACSS categories

/* 1. Base: defaults, no classes */
* {
    box-sizing: border-box;
}

body {
    font-family: sans-serif;
    line-height: 1.6;
    color: #333;
}

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

/* 2. Layout: major page sections (prefix: l-) */
.l-header {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 100;
}

.l-sidebar {
    width: 250px;
    float: left;
}

.l-main {
    margin-left: 250px;
}

.l-footer {
    clear: both;
    padding: 2rem 0;
}

/* 3. Module: reusable components */
.card {
    background: white;
    border: 1px solid #ddd;
    border-radius: 4px;
    padding: 1rem;
}

.button {
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
}

.nav {
    list-style: none;
    padding: 0;
}

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

/* 4. State: describe behavior (prefix: is- or has-) */
.is-active {
    font-weight: bold;
    color: #007acc;
}

.is-hidden {
    display: none;
}

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

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

.is-loading {
    cursor: wait;
    opacity: 0.6;
}

/* 5. Theme: color schemes and typography */
.theme-dark {
    background: #1a1a1a;
    color: #f0f0f0;
}

.theme-dark .card {
    background: #2d2d2d;
    border-color: #404040;
}

.theme-large-text {
    font-size: 1.125rem;
}
Note: BEM is most popular for component-based development. Use __ for elements, -- for modifiers. OOCSS focuses on reusability. SMACSS provides categorization. Choose based on team preference and project needs.

2. CSS-in-JS vs CSS Modules vs Utility-first

Approach Description Pros Cons
CSS-in-JS Styles written in JavaScript (styled-components, Emotion) Scoped by default, dynamic styling, no separate files Runtime overhead, larger bundle, no caching
CSS Modules Locally scoped CSS files (styles.module.css) Automatic scoping, standard CSS, build-time processing Extra build step, separate files
Utility-first (Tailwind) Pre-defined utility classes in HTML Fast development, small bundle, consistency HTML clutter, learning curve, harder customization
Traditional CSS Global stylesheets with naming conventions Standard, cacheable, no build needed Global scope, naming conflicts, larger files
CSS Preprocessors (Sass/Less) Extended CSS with variables, nesting, mixins DRY, powerful features, compiles to CSS Build step required, can generate bloat
Atomic CSS Single-purpose utility classes Highly reusable, small CSS, fast Many classes in HTML, specificity issues

Example: CSS-in-JS (styled-components style)

/* JavaScript/TypeScript file */
/*
import styled from 'styled-components';

// Styled component
const Button = styled.button`
    padding: 0.75rem 1.5rem;
    background: ${props => props.primary ? '#007acc' : '#6c757d'};
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 1rem;
    
    &:hover {
        background: ${props => props.primary ? '#005a9e' : '#5a6268'};
    }
    
    &:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }
`;

// Dynamic styles
const Card = styled.div`
    background: white;
    padding: ${props => props.compact ? '0.5rem' : '1rem'};
    border-radius: 8px;
    box-shadow: ${props => props.elevated ? '0 4px 8px rgba(0,0,0,0.1)' : 'none'};
`;

// Extending styles
const PrimaryButton = styled(Button)`
    background: #007acc;
    font-weight: bold;
`;

// Using theme
const ThemedCard = styled.div`
    background: ${props => props.theme.cardBg};
    color: ${props => props.theme.textColor};
    padding: 1rem;
`;

// Usage in JSX
function App() {
    return (
        <Card elevated>
            <Button primary>Primary</Button>
            <Button>Secondary</Button>
            <PrimaryButton>Important</PrimaryButton>
        </Card>
    );
}
*/

/* Advantages:
   - Automatic scoping (no class name conflicts)
   - Dynamic styling based on props
   - Colocated with component logic
   - Dead code elimination
   
   Disadvantages:
   - Runtime overhead
   - No style caching between renders
   - Larger JavaScript bundle
   - Debugging can be harder */

Example: CSS Modules

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

.card-title {
    font-size: 1.5rem;
    margin-bottom: 0.5rem;
    color: #333;
}

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

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

.button-primary {
    background: #007acc;
    color: white;
}

/* Composes (reuse other classes) */
.button-large {
    composes: button;
    padding: 0.75rem 1.5rem;
    font-size: 1.125rem;
}

/* Global styles */
:global(.global-class) {
    /* Not scoped */
}

/* JavaScript usage */
/*
import styles from './styles.module.css';

function Card() {
    return (
        <div className={styles.card}>
            <h2 className={styles.cardTitle}>Title</h2>
            <p className={styles.cardBody}>Content</p>
            <button className={styles.buttonPrimary}>Action</button>
        </div>
    );
}

// Generated HTML:
// <div class="styles_card__Ab3D">
//   <h2 class="styles_cardTitle__Xy2Z">Title</h2>
// </div>
*/

/* Advantages:
   - Automatic local scoping
   - Standard CSS syntax
   - Build-time processing
   - Works with preprocessors
   
   Disadvantages:
   - Build step required
   - Import in every component
   - Separate files to maintain */

Example: Utility-first (Tailwind CSS style)

/* Configuration (tailwind.config.js) */
/*
module.exports = {
    theme: {
        extend: {
            colors: {
                primary: '#007acc',
            }
        }
    }
}
*/

/* HTML with utility classes */
/*
<div class="bg-white rounded-lg shadow-md p-4 max-w-md mx-auto">
    <h2 class="text-2xl font-bold mb-2 text-gray-800">Card Title</h2>
    <p class="text-gray-600 leading-relaxed mb-4">
        Card content with consistent spacing and typography.
    </p>
    <div class="flex gap-2">
        <button class="bg-primary text-white px-4 py-2 rounded hover:bg-blue-700 transition">
            Primary
        </button>
        <button class="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600 transition">
            Secondary
        </button>
    </div>
</div>

<!-- Responsive utilities -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
    <!-- Content -->
</div>

<!-- State variants -->
<button class="bg-blue-500 hover:bg-blue-700 active:bg-blue-800 focus:ring-2 focus:ring-blue-300">
    Button
</button>
*/

/* Custom utilities (if needed) */
@layer utilities {
    .text-balance {
        text-wrap: balance;
    }
    
    .bg-grid {
        background-image: 
            linear-gradient(#e5e5e5 1px, transparent 1px),
            linear-gradient(90deg, #e5e5e5 1px, transparent 1px);
        background-size: 20px 20px;
    }
}

/* Component extraction */
@layer components {
    .btn-primary {
        @apply bg-primary text-white px-4 py-2 rounded hover:bg-blue-700 transition;
    }
    
    .card {
        @apply bg-white rounded-lg shadow-md p-4;
    }
}

/* Advantages:
   - Very fast development
   - Small CSS bundle (unused purged)
   - Consistent design system
   - No naming required
   
   Disadvantages:
   - Many classes in HTML
   - Learning curve for syntax
   - Harder to read HTML
   - Customization requires config */

Example: Comparison of approaches

/* Traditional CSS */
.button {
    padding: 0.5rem 1rem;
    background: #007acc;
    color: white;
    border: none;
    border-radius: 4px;
}

/* HTML: <button class="button">Click</button> */

/* CSS Modules (button.module.css) */
.button {
    padding: 0.5rem 1rem;
    background: #007acc;
    color: white;
    border: none;
    border-radius: 4px;
}

/* JS: import styles from './button.module.css' */
/* HTML: <button className={styles.button}>Click</button> */

/* CSS-in-JS (styled-components) */
/*
const Button = styled.button`
    padding: 0.5rem 1rem;
    background: #007acc;
    color: white;
    border: none;
    border-radius: 4px;
`;

HTML: <Button>Click</Button>
*/

/* Utility-first (Tailwind) */
/* HTML: <button class="px-4 py-2 bg-blue-600 text-white rounded">Click</button> */

/* Decision matrix:
   - Large team, consistency → Utility-first (Tailwind)
   - React/component focus → CSS-in-JS or CSS Modules
   - Simple sites, fast load → Traditional CSS
   - Build complexity tolerance → Any modern approach
   - Dynamic theming needs → CSS Variables + any approach */
Warning: CSS-in-JS has runtime cost. CSS Modules require build step. Utility-first creates HTML bloat. Choose based on team, project size, and performance needs. Modern approaches: CSS Modules + CSS Variables, or Tailwind with @apply for extraction.

3. Component-scoped CSS Strategies

Strategy Technique Scope Mechanism Use Case
Shadow DOM Web Components encapsulation Browser-native isolation True component isolation, framework-agnostic
CSS Modules Build-time class name hashing Unique class names per component React, Vue, Angular projects
Scoped Styles (Vue) Add unique attribute to elements Attribute selectors Vue single-file components
CSS-in-JS Generate unique class names at runtime Automatic hashing React applications
@scope NEW Native CSS scoping rule Lexical scoping boundaries Modern browsers, framework-agnostic
BEM Convention Strict naming methodology Manual namespacing Any project, no build required
CSS Cascade Layers @layer for specificity control Layer-based isolation Organize component styles by priority

Example: Shadow DOM component scoping

/* Web Component with Shadow DOM */
/*
class MyCard extends HTMLElement {
    constructor() {
        super();
        const shadow = this.attachShadow({ mode: 'open' });
        
        shadow.innerHTML = `
            <style>
                /* Styles are completely isolated */
                :host {
                    display: block;
                    background: white;
                    border-radius: 8px;
                    padding: 1rem;
                    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
                }
                
                .title {
                    font-size: 1.5rem;
                    margin-bottom: 0.5rem;
                }
                
                .content {
                    line-height: 1.6;
                }
                
                ::slotted(button) {
                    padding: 0.5rem 1rem;
                    background: #007acc;
                    color: white;
                    border: none;
                    border-radius: 4px;
                }
            </style>
            
            <div class="card">
                <h2 class="title"><slot name="title"></slot></h2>
                <div class="content"><slot></slot></div>
                <slot name="actions"></slot>
            </div>
        `;
    }
}

customElements.define('my-card', MyCard);

// Usage:
<my-card>
    <span slot="title">Card Title</span>
    <p>Card content</p>
    <button slot="actions">Action</button>
</my-card>
*/

/* Advantages:
   - True encapsulation
   - No style leaking
   - Framework-agnostic
   - Browser-native
   
   Challenges:
   - Cannot style from outside
   - Limited global theme support
   - Learning curve */

Example: CSS @scope (modern native scoping)

/* Native CSS scoping (Chrome 118+) */

/* Scope styles to .card component */
@scope (.card) {
    /* Only applies inside .card */
    h2 {
        font-size: 1.5rem;
        margin-bottom: 0.5rem;
    }
    
    p {
        line-height: 1.6;
        color: #666;
    }
    
    button {
        padding: 0.5rem 1rem;
        background: #007acc;
        color: white;
        border: none;
        border-radius: 4px;
    }
}

/* Scope with exclusion boundary */
@scope (.card) to (.nested-card) {
    /* Applies inside .card but NOT inside .nested-card */
    p {
        color: #333;
    }
}

/* Multiple scopes */
@scope (.header) {
    nav {
        display: flex;
        gap: 1rem;
    }
}

@scope (.footer) {
    nav {
        display: block;  /* Different nav styling */
    }
}

/* Using :scope pseudo-class */
@scope (.card) {
    :scope {
        /* Styles the .card itself */
        background: white;
        padding: 1rem;
        border-radius: 8px;
    }
    
    :scope > h2 {
        /* Direct child h2 of .card */
        border-bottom: 2px solid #007acc;
    }
}

/* Practical example: Modal component */
@scope (.modal) {
    :scope {
        position: fixed;
        inset: 0;
        display: flex;
        align-items: center;
        justify-content: center;
        background: rgba(0,0,0,0.5);
    }
    
    .modal-content {
        background: white;
        padding: 2rem;
        border-radius: 8px;
        max-width: 500px;
        width: 90%;
    }
    
    h2 {
        margin-top: 0;
    }
    
    button {
        margin-top: 1rem;
    }
}

Example: Vue scoped styles

/* Vue Single File Component */
/*
<template>
    <div class="card">
        <h2 class="card-title">{{ title }}</h2>
        <p class="card-content">{{ content }}</p>
        <button class="card-button">Action</button>
    </div>
</template>

<style scoped>
.card {
    background: white;
    padding: 1rem;
    border-radius: 8px;
}

.card-title {
    font-size: 1.5rem;
    margin-bottom: 0.5rem;
}

.card-content {
    line-height: 1.6;
    color: #666;
}

.card-button {
    padding: 0.5rem 1rem;
    background: #007acc;
    color: white;
    border: none;
    border-radius: 4px;
}

/* Generated HTML:
<div class="card" data-v-f3f3eg9>
    <h2 class="card-title" data-v-f3f3eg9>...</h2>
</div>

Generated CSS:
.card[data-v-f3f3eg9] { ... }
.card-title[data-v-f3f3eg9] { ... }
*/

/* Deep selector for child components */
.card :deep(.child-component) {
    margin-top: 1rem;
}

/* Slotted content */
.card :slotted(button) {
    margin-left: 0.5rem;
}

/* Global styles within scoped */
:global(.global-class) {
    /* Not scoped */
}
</style>
*/

Example: Cascade layers for component organization

/* Define layer order (low to high priority) */
@layer reset, base, components, utilities, overrides;

/* Reset layer (lowest priority) */
@layer reset {
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
}

/* Base layer */
@layer base {
    body {
        font-family: sans-serif;
        line-height: 1.6;
        color: #333;
    }
    
    a {
        color: #007acc;
    }
}

/* Components layer */
@layer components {
    .card {
        background: white;
        padding: 1rem;
        border-radius: 8px;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    
    .button {
        padding: 0.5rem 1rem;
        border: none;
        border-radius: 4px;
        cursor: pointer;
    }
    
    .button-primary {
        background: #007acc;
        color: white;
    }
}

/* Utilities layer */
@layer utilities {
    .text-center {
        text-align: center;
    }
    
    .mt-1 {
        margin-top: 0.5rem;
    }
    
    .hidden {
        display: none;
    }
}

/* Overrides layer (highest priority) */
@layer overrides {
    .force-visible {
        display: block !important;
    }
}

/* Unlayered styles have highest priority */
.emergency-override {
    color: red;
}

/* Import layers */
@import url('reset.css') layer(reset);
@import url('components.css') layer(components);

/* Nested layers */
@layer components {
    @layer cards, buttons, forms;
    
    @layer cards {
        .card { /* ... */ }
    }
    
    @layer buttons {
        .button { /* ... */ }
    }
}
Note: Use Shadow DOM for true isolation, CSS Modules for React/build tools, @scope for modern native scoping. Cascade layers organize component priority. BEM works everywhere without tooling.

4. CSS Reset vs Normalize vs Modern-normalize

Approach Philosophy Size Use Case
CSS Reset (Meyer/Universal) Remove ALL browser defaults ~1-2 KB Start from absolute zero, full control
Normalize.css Preserve useful defaults, fix bugs ~8 KB Consistent cross-browser styling
Modern-normalize Normalize for modern browsers only ~2 KB Modern browsers (no IE support)
Sanitize.css Normalize + opinionated defaults ~10 KB Good defaults out of the box
Custom Reset Minimal project-specific reset <1 KB Tailored to specific needs

Example: CSS Reset (Meyer style)

/* Classic CSS Reset - removes everything */
* {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}

/* HTML5 display-role reset */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
    display: block;
}

body {
    line-height: 1;
}

ol, ul {
    list-style: none;
}

blockquote, q {
    quotes: none;
}

blockquote:before, blockquote:after,
q:before, q:after {
    content: '';
    content: none;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

/* Modern universal reset */
*, *::before, *::after {
    box-sizing: border-box;
}

* {
    margin: 0;
    padding: 0;
}

html, body {
    height: 100%;
}

body {
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

img, picture, video, canvas, svg {
    display: block;
    max-width: 100%;
}

input, button, textarea, select {
    font: inherit;
}

p, h1, h2, h3, h4, h5, h6 {
    overflow-wrap: break-word;
}

/* Advantages:
   - Complete control
   - Minimal file size
   - No surprises
   
   Disadvantages:
   - Must rebuild everything
   - Removes useful defaults */

Example: Modern-normalize (modern browsers)

/* Modern-normalize highlights (simplified) */

/* Document */
*, *::before, *::after {
    box-sizing: border-box;
}

html {
    line-height: 1.15;
    -webkit-text-size-adjust: 100%;
    tab-size: 4;
}

body {
    margin: 0;
    font-family: system-ui, -apple-system, sans-serif;
}

/* Sections */
h1 {
    font-size: 2em;
    margin: 0.67em 0;
}

/* Grouping content */
hr {
    height: 0;
    color: inherit;
}

/* Text-level semantics */
abbr[title] {
    text-decoration: underline dotted;
}

b, strong {
    font-weight: bolder;
}

code, kbd, samp, pre {
    font-family: ui-monospace, monospace;
    font-size: 1em;
}

small {
    font-size: 80%;
}

/* Forms */
button, input, optgroup, select, textarea {
    font-family: inherit;
    font-size: 100%;
    line-height: 1.15;
    margin: 0;
}

button, select {
    text-transform: none;
}

button, [type='button'], [type='reset'], [type='submit'] {
    -webkit-appearance: button;
}

/* Interactive */
summary {
    display: list-item;
}

/* Advantages:
   - Keeps useful defaults
   - Cross-browser consistency
   - Well-documented
   - Small size for modern browsers */

Example: Custom minimal reset (modern approach)

/* Minimal modern reset - best practices */

/* Box sizing */
*, *::before, *::after {
    box-sizing: border-box;
}

/* Remove default margin */
* {
    margin: 0;
}

/* Body defaults */
body {
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/* Media defaults */
img, picture, video, canvas, svg {
    display: block;
    max-width: 100%;
}

/* Form element font inheritance */
input, button, textarea, select {
    font: inherit;
}

/* Text overflow */
p, h1, h2, h3, h4, h5, h6 {
    overflow-wrap: break-word;
}

/* Remove list styles on ul, ol with role="list" */
ul[role='list'], ol[role='list'] {
    list-style: none;
}

/* Root stacking context */
#root, #__next {
    isolation: isolate;
}

/* Focus visible */
:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

/* Remove animations for people who've turned them off */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* Additional useful resets */
a {
    color: inherit;
    text-decoration: none;
}

button {
    cursor: pointer;
    background: none;
    border: none;
    padding: 0;
}

/* This reset:
   - Minimal but effective
   - Modern best practices
   - Accessibility-aware
   - Easy to customize */

Example: Comparison and decision guide

/* Decision matrix:

1. Use CSS Reset (Meyer/Universal) when:
   - You want absolute control
   - Building from scratch
   - Don't need semantic defaults
   - Want smallest possible base

2. Use Normalize.css when:
   - Need cross-browser consistency
   - Want to preserve useful defaults
   - Supporting older browsers
   - Standard approach

3. Use Modern-normalize when:
   - Only supporting modern browsers
   - Want normalize benefits but smaller
   - No IE11 support needed
   - Modern project (2020+)

4. Use Custom/Minimal Reset when:
   - Have specific requirements
   - Want to understand every line
   - Very small footprint needed
   - Project-specific needs

5. Use Sanitize.css when:
   - Want opinionated defaults
   - Need forms to look consistent
   - Want normalize + extras
   - Don't want to set common styles
*/

/* Recommended modern approach: */
/* 1. Start with modern-normalize or minimal reset */
/* 2. Add project-specific base styles */
/* 3. Use CSS custom properties for tokens */
/* 4. Build component styles on top */

/* Example base after reset */
:root {
    --font-sans: system-ui, -apple-system, sans-serif;
    --font-mono: ui-monospace, monospace;
    --color-text: #1a1a1a;
    --color-bg: #ffffff;
    --spacing-unit: 0.5rem;
}

body {
    font-family: var(--font-sans);
    color: var(--color-text);
    background: var(--color-bg);
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
    line-height: 1.2;
}

code, pre {
    font-family: var(--font-mono);
}

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

a:hover {
    text-decoration: underline;
}
Warning: Don't use both reset and normalize together. CSS Reset removes useful defaults that you'll need to rebuild. Modern projects should use modern-normalize or custom minimal reset. Always include box-sizing: border-box.

5. Critical CSS and Above-fold Optimization

Technique Description Impact Implementation
Critical CSS Inline above-fold styles in HTML Eliminates render-blocking CSS Extract and inline critical styles
CSS Splitting Separate critical from non-critical Faster initial render Build tool configuration
Async CSS Loading Load non-critical CSS asynchronously Non-blocking page load Media query trick or JS
Preload Hint browser to load CSS early Faster CSS discovery <link rel="preload">
CSS Containment Isolate subtrees for rendering Better paint performance contain: layout paint
Content-visibility Skip rendering off-screen content Faster initial render content-visibility: auto

Example: Critical CSS inline pattern

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- Critical CSS inlined -->
    <style>
        /* Only above-the-fold styles */
        body {
            margin: 0;
            font-family: system-ui, sans-serif;
            line-height: 1.6;
        }
        
        .header {
            background: #fff;
            border-bottom: 1px solid #e0e0e0;
            padding: 1rem 2rem;
        }
        
        .hero {
            min-height: 60vh;
            display: flex;
            align-items: center;
            justify-content: center;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }
        
        .hero h1 {
            font-size: clamp(2rem, 5vw, 4rem);
            margin: 0;
        }
        
        /* Loading state for below-fold */
        .below-fold {
            min-height: 100px;
            background: #f5f5f5;
        }
    </style>
    
    <!-- Preload full stylesheet -->
    <link rel="preload" href="/styles/main.css" as="style">
    
    <!-- Async load non-critical CSS -->
    <link rel="stylesheet" href="/styles/main.css" media="print" onload="this.media='all'">
    <noscript><link rel="stylesheet" href="/styles/main.css"></noscript>
</head>
<body>
    <header class="header">
        <!-- Header content -->
    </header>
    
    <section class="hero">
        <h1>Welcome</h1>
    </section>
    
    <main class="below-fold">
        <!-- Rest of content -->
    </main>
</body>
</html>

/* Tools for extracting critical CSS:
   - Critical (npm package)
   - PurgeCSS
   - Critters (Next.js/Angular)
   - Penthouse
   - Online tools: criticalcss.com
*/

Example: Async CSS loading patterns

<!-- Method 1: Media query trick (most compatible) -->
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

<!-- Method 2: JavaScript loading -->
<script>
    function loadCSS(href) {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = href;
        document.head.appendChild(link);
    }
    
    // Load when DOM is ready
    if (document.readyState === 'complete') {
        loadCSS('/styles/main.css');
    } else {
        window.addEventListener('load', () => loadCSS('/styles/main.css'));
    }
</script>

<!-- Method 3: Preload + async apply -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

<!-- Method 4: LoadCSS library (polyfill) -->
<script>
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
(function(w){
    "use strict";
    var loadCSS = function(href, before, media){
        var doc = w.document;
        var ss = doc.createElement("link");
        var ref;
        if(before){
            ref = before;
        } else {
            var refs = (doc.body || doc.getElementsByTagName("head")[0]).childNodes;
            ref = refs[refs.length - 1];
        }
        
        var sheets = doc.styleSheets;
        ss.rel = "stylesheet";
        ss.href = href;
        ss.media = "only x";
        
        function ready(cb){
            if(doc.body){
                return cb();
            }
            setTimeout(function(){
                ready(cb);
            });
        }
        
        ready(function(){
            ref.parentNode.insertBefore(ss, (before ? ref : ref.nextSibling));
        });
        
        var onloadcssdefined = function(cb){
            var resolvedHref = ss.href;
            var i = sheets.length;
            while(i--){
                if(sheets[i].href === resolvedHref){
                    return cb();
                }
            }
            setTimeout(function(){
                onloadcssdefined(cb);
            });
        };
        
        function loadCB(){
            if(ss.addEventListener){
                ss.removeEventListener("load", loadCB);
            }
            ss.media = media || "all";
        }
        
        if(ss.addEventListener){
            ss.addEventListener("load", loadCB);
        }
        ss.onloadcssdefined = onloadcssdefined;
        onloadcssdefined(loadCB);
        return ss;
    };
    
    if(typeof exports !== "undefined"){
        exports.loadCSS = loadCSS;
    } else {
        w.loadCSS = loadCSS;
    }
}(typeof global !== "undefined" ? global : this));

// Usage
loadCSS("/path/to/stylesheet.css");
</script>

Example: Content-visibility optimization

/* Optimize rendering of off-screen content */

/* Skip rendering until near viewport */
.article-section {
    content-visibility: auto;
    contain-intrinsic-size: auto 500px;  /* Estimated height */
}

/* Critical above-fold content */
.hero {
    content-visibility: visible;  /* Always render */
}

/* Below-fold content */
.comments-section {
    content-visibility: auto;
    contain-intrinsic-size: auto 800px;
}

.related-articles {
    content-visibility: auto;
    contain-intrinsic-size: auto 400px;
}

/* Long list optimization */
.long-list-item {
    content-visibility: auto;
    contain-intrinsic-size: auto 100px;
}

/* Performance gains:
   - Faster initial render
   - Reduced layout calculation
   - Lower memory usage
   - Smoother scrolling
*/

/* CSS Containment for isolated components */
.card {
    contain: layout paint;
    /* Layout and paint isolated from rest of page */
}

.widget {
    contain: layout style paint;
    /* Even more isolated */
}

/* Full containment */
.independent-component {
    contain: strict;
    /* Maximum isolation, but requires size */
    width: 300px;
    height: 400px;
}

/* Use for:
   - Independent widgets
   - List items
   - Cards
   - Modals
   - Sidebars
*/

Example: Build-time optimization strategies

/* webpack.config.js or similar build config */
/*
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
    optimization: {
        minimizer: [
            new CssMinimizerPlugin(),
        ],
        splitChunks: {
            cacheGroups: {
                styles: {
                    name: 'styles',
                    type: 'css/mini-extract',
                    chunks: 'all',
                    enforce: true,
                },
            },
        },
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash].css',
        }),
    ],
};
*/

/* PostCSS configuration */
/*
module.exports = {
    plugins: [
        require('autoprefixer'),
        require('cssnano')({
            preset: ['default', {
                discardComments: {
                    removeAll: true,
                },
            }],
        }),
        require('@fullhuman/postcss-purgecss')({
            content: ['./src/!**!/!*.html', './src/!**!/!*.js'],
            defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
        }),
    ],
};
*/

/* Critical CSS extraction (Node.js) */
/*
const critical = require('critical');

critical.generate({
    base: 'dist/',
    src: 'index.html',
    target: 'index-critical.html',
    inline: true,
    width: 1300,
    height: 900,
    minify: true,
});
*/

/* Performance checklist:
   1. Inline critical CSS (<14KB gzipped)
   2. Async load non-critical CSS
   3. Remove unused CSS (PurgeCSS)
   4. Minify CSS (cssnano)
   5. Use content-visibility for long pages
   6. Add CSS containment to components
   7. Preload key stylesheets
   8. Split CSS by route/page
   9. Use HTTP/2 server push (optional)
   10. Monitor CSS bundle size
*/

CSS Architecture Best Practices

  • Choose naming convention early: BEM for components, prefixes for SMACSS
  • CSS Modules or @scope for automatic scoping in modern apps
  • Utility-first (Tailwind) for rapid development, extract components with @apply
  • Use modern-normalize or custom minimal reset for modern browsers
  • Inline critical CSS (<14KB), async load rest for best performance
  • Apply content-visibility: auto to off-screen sections
  • Use contain: layout paint on independent components
  • Organize with cascade layers (@layer) for predictable specificity
  • Split CSS by route/page, preload critical resources
  • Monitor bundle size, remove unused CSS with PurgeCSS