typography-system.css
1 /* ============================================ 2 TYPOGRAPHY DESIGN SYSTEM 3 4 Theory: Modular scale (Major Third 1.25) 5 Baseline: 8px grid for vertical rhythm 6 Body size: 16px (accessibility minimum) 7 Line length: 45-75 characters optimal 8 9 References: 10 - Bringhurst's "Elements of Typographic Style" 11 - Material Design Typography 12 - Apple Human Interface Guidelines 13 ============================================ */ 14 15 :root { 16 /* ===== Type Scale (Major Third 1.25) ===== */ 17 --text-xs: 10px; /* Level -2: Micro text, legal */ 18 --text-sm: 13px; /* Level -1: Small, captions */ 19 --text-base: 16px; /* Level 0: Body text */ 20 --text-lg: 20px; /* Level 1: Large body, intro */ 21 --text-xl: 25px; /* Level 2: H3, card titles */ 22 --text-2xl: 31px; /* Level 3: H2, section headers */ 23 --text-3xl: 39px; /* Level 4: H1, page titles */ 24 --text-4xl: 49px; /* Level 5: Display, hero */ 25 --text-5xl: 61px; /* Level 6: Large display */ 26 --text-6xl: 76px; /* Level 7: Massive hero */ 27 28 /* ===== Line Heights (matched to use case) ===== */ 29 --lh-none: 1.0; /* Single line, logos */ 30 --lh-tight: 1.25; /* Display, hero (48px+) */ 31 --lh-snug: 1.375; /* Headings (24-48px) */ 32 --lh-normal: 1.5; /* Body text (16-20px) */ 33 --lh-relaxed: 1.625; /* Small text (12-14px) */ 34 --lh-loose: 1.75; /* Dense content, CJK */ 35 36 /* ===== Font Weights (perceptual hierarchy) ===== */ 37 --weight-light: 300; /* Rarely used, luxury brands */ 38 --weight-normal: 400; /* Body text */ 39 --weight-medium: 500; /* Subtle emphasis, UI */ 40 --weight-semibold: 600; /* Strong emphasis, subheadings */ 41 --weight-bold: 700; /* Headings, CTAs */ 42 --weight-black: 900; /* Rarely used, extreme emphasis */ 43 44 /* ===== Letter Spacing (tracking) ===== */ 45 --tracking-tighter: -0.05em; /* Display text (48px+) */ 46 --tracking-tight: -0.025em; /* Headings (24-48px) */ 47 --tracking-normal: 0; /* Body text */ 48 --tracking-wide: 0.025em; /* Small text, all-caps */ 49 --tracking-wider: 0.05em; /* Tiny text, labels */ 50 51 /* ===== Spacing Scale (8px baseline grid) ===== */ 52 --space-0: 0; 53 --space-1: 4px; /* 0.5 × 8 */ 54 --space-2: 8px; /* 1 × 8 */ 55 --space-3: 12px; /* 1.5 × 8 */ 56 --space-4: 16px; /* 2 × 8 */ 57 --space-5: 20px; /* 2.5 × 8 */ 58 --space-6: 24px; /* 3 × 8 */ 59 --space-8: 32px; /* 4 × 8 */ 60 --space-10: 40px; /* 5 × 8 */ 61 --space-12: 48px; /* 6 × 8 */ 62 --space-16: 64px; /* 8 × 8 */ 63 --space-20: 80px; /* 10 × 8 */ 64 --space-24: 96px; /* 12 × 8 */ 65 --space-32: 128px; /* 16 × 8 */ 66 67 /* ===== Semantic Spacing ===== */ 68 --space-heading-to-body: var(--space-3); /* 12px */ 69 --space-paragraph: var(--space-4); /* 16px */ 70 --space-paragraph-loose: var(--space-6); /* 24px */ 71 --space-section-sm: var(--space-12); /* 48px */ 72 --space-section-md: var(--space-16); /* 64px */ 73 --space-section-lg: var(--space-24); /* 96px */ 74 75 /* ===== Image Spacing ===== */ 76 --space-image-top: var(--space-8); /* 32px - after text */ 77 --space-image-bottom: var(--space-4); /* 16px - before caption */ 78 --space-caption-bottom: var(--space-12); /* 48px - after caption */ 79 80 /* ===== Container Padding ===== */ 81 --padding-card: var(--space-8); /* 32px */ 82 --padding-section-v: var(--space-16); /* 64px vertical */ 83 --padding-section-h: var(--space-6); /* 24px horizontal */ 84 --padding-button-v: var(--space-3); /* 12px vertical */ 85 --padding-button-h: var(--space-6); /* 24px horizontal */ 86 } 87 88 /* ============================================ 89 BASE TYPOGRAPHY 90 ============================================ */ 91 92 body { 93 font-size: var(--text-base); 94 line-height: var(--lh-normal); 95 font-weight: var(--weight-normal); 96 letter-spacing: var(--tracking-normal); 97 98 /* Optical improvements */ 99 font-kerning: normal; 100 text-rendering: optimizeLegibility; 101 -webkit-font-smoothing: antialiased; 102 -moz-osx-font-smoothing: grayscale; 103 } 104 105 /* ============================================ 106 HEADINGS 107 ============================================ */ 108 109 h1 { 110 font-size: var(--text-3xl); 111 line-height: var(--lh-tight); 112 font-weight: var(--weight-bold); 113 letter-spacing: var(--tracking-tight); 114 margin-bottom: var(--space-heading-to-body); 115 text-wrap: balance; 116 } 117 118 h2 { 119 font-size: var(--text-2xl); 120 line-height: var(--lh-snug); 121 font-weight: var(--weight-bold); 122 letter-spacing: var(--tracking-tight); 123 margin-top: var(--space-section-md); 124 margin-bottom: var(--space-heading-to-body); 125 text-wrap: balance; 126 } 127 128 h3 { 129 font-size: var(--text-xl); 130 line-height: var(--lh-snug); 131 font-weight: var(--weight-semibold); 132 margin-top: var(--space-section-sm); 133 margin-bottom: var(--space-heading-to-body); 134 text-wrap: balance; 135 } 136 137 h4 { 138 font-size: var(--text-lg); 139 line-height: var(--lh-snug); 140 font-weight: var(--weight-semibold); 141 margin-top: var(--space-8); 142 margin-bottom: var(--space-3); 143 } 144 145 /* ============================================ 146 BODY TEXT 147 ============================================ */ 148 149 p { 150 max-width: 65ch; /* Optimal line length */ 151 margin-bottom: var(--space-paragraph); 152 153 /* Advanced features */ 154 orphans: 2; 155 widows: 2; 156 text-wrap: pretty; 157 } 158 159 /* Intro paragraph */ 160 .lead { 161 font-size: var(--text-lg); 162 line-height: var(--lh-normal); 163 margin-bottom: var(--space-paragraph-loose); 164 } 165 166 /* Small text */ 167 small, .text-small { 168 font-size: var(--text-sm); 169 line-height: var(--lh-relaxed); 170 } 171 172 /* ============================================ 173 LISTS 174 ============================================ */ 175 176 ul, ol { 177 margin-bottom: var(--space-paragraph); 178 padding-left: var(--space-6); 179 } 180 181 li { 182 margin-bottom: var(--space-2); 183 } 184 185 li:last-child { 186 margin-bottom: 0; 187 } 188 189 /* ============================================ 190 IMAGES & FIGURES 191 ============================================ */ 192 193 img { 194 max-width: 100%; 195 height: auto; 196 display: block; 197 } 198 199 figure { 200 margin: var(--space-image-top) 0 var(--space-caption-bottom); 201 } 202 203 figure img { 204 margin-bottom: var(--space-image-bottom); 205 } 206 207 figcaption { 208 font-size: var(--text-sm); 209 line-height: var(--lh-relaxed); 210 color: #666; 211 text-align: center; 212 } 213 214 /* ============================================ 215 LINKS 216 ============================================ */ 217 218 a { 219 color: inherit; 220 text-decoration: underline; 221 text-decoration-thickness: 1px; 222 text-underline-offset: 2px; 223 transition: color 0.2s ease; 224 } 225 226 a:hover { 227 text-decoration-thickness: 2px; 228 } 229 230 /* ============================================ 231 EMPHASIS 232 ============================================ */ 233 234 strong, b { 235 font-weight: var(--weight-semibold); 236 } 237 238 em, i { 239 font-style: italic; 240 } 241 242 /* ============================================ 243 CODE 244 ============================================ */ 245 246 code { 247 font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace; 248 font-size: 0.9em; 249 padding: 2px 6px; 250 background: rgba(0, 0, 0, 0.05); 251 border-radius: 3px; 252 } 253 254 pre { 255 font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace; 256 font-size: var(--text-sm); 257 line-height: var(--lh-relaxed); 258 padding: var(--space-4); 259 background: rgba(0, 0, 0, 0.05); 260 border-radius: 6px; 261 overflow-x: auto; 262 margin-bottom: var(--space-paragraph); 263 } 264 265 pre code { 266 padding: 0; 267 background: none; 268 } 269 270 /* ============================================ 271 UTILITY CLASSES 272 ============================================ */ 273 274 /* Display text */ 275 .text-display { 276 font-size: var(--text-4xl); 277 line-height: var(--lh-tight); 278 font-weight: var(--weight-bold); 279 letter-spacing: var(--tracking-tighter); 280 } 281 282 .text-display-lg { 283 font-size: var(--text-5xl); 284 line-height: var(--lh-tight); 285 font-weight: var(--weight-bold); 286 letter-spacing: var(--tracking-tighter); 287 } 288 289 .text-display-xl { 290 font-size: var(--text-6xl); 291 line-height: var(--lh-tight); 292 font-weight: var(--weight-bold); 293 letter-spacing: var(--tracking-tighter); 294 } 295 296 /* Text wrapping */ 297 .text-balance { 298 text-wrap: balance; 299 } 300 301 .text-pretty { 302 text-wrap: pretty; 303 } 304 305 .text-nowrap { 306 white-space: nowrap; 307 } 308 309 /* Text alignment */ 310 .text-left { text-align: left; } 311 .text-center { text-align: center; } 312 .text-right { text-align: right; } 313 314 /* Font weights */ 315 .font-normal { font-weight: var(--weight-normal); } 316 .font-medium { font-weight: var(--weight-medium); } 317 .font-semibold { font-weight: var(--weight-semibold); } 318 .font-bold { font-weight: var(--weight-bold); } 319 320 /* ============================================ 321 RESPONSIVE TYPOGRAPHY 322 ============================================ */ 323 324 /* Mobile adjustments */ 325 @media (max-width: 640px) { 326 :root { 327 --text-3xl: 32px; /* H1 smaller on mobile */ 328 --text-2xl: 26px; /* H2 smaller on mobile */ 329 --text-xl: 22px; /* H3 smaller on mobile */ 330 } 331 332 p { 333 max-width: 100%; /* Full width on mobile */ 334 } 335 } 336 337 /* Tablet adjustments */ 338 @media (min-width: 641px) and (max-width: 1024px) { 339 :root { 340 --text-3xl: 36px; 341 --text-2xl: 28px; 342 } 343 } 344 345 /* ============================================ 346 DEBUG GRID (Development only) 347 Remove before production 348 ============================================ */ 349 350 body.debug-grid { 351 background-image: 352 repeating-linear-gradient( 353 to bottom, 354 transparent 0, 355 transparent 7px, 356 rgba(255, 0, 0, 0.1) 7px, 357 rgba(255, 0, 0, 0.1) 8px 358 ); 359 } 360 361 /* Usage: Add class="debug-grid" to body to verify 8px rhythm */