Introduction to CSS Typography
Typography in CSS controls how text appears on your webpage, affecting readability, accessibility, and overall user experience. Mastering CSS typography properties allows you to create visually appealing, readable, and responsive text across all devices. Effective typography establishes hierarchy, guides users through content, and reinforces your brand identity.
Core Typography Concepts
- Font Properties: Control the typeface, size, weight, and style
- Text Properties: Control alignment, spacing, decoration, and transformation
- Responsive Typography: Ensures text scales appropriately across devices
- Font Stacks: Fallback system to ensure consistent display across devices
- Web Fonts: Custom fonts loaded from services or self-hosted files
Essential Font Properties
Font Family
.element {
font-family: 'Helvetica Neue', Arial, sans-serif;
}
- Specifies the typeface to use
- Include fallback fonts (font stack) in case primary font isn’t available
- Generic family (serif, sans-serif, monospace, etc.) should be the last fallback
- Web-safe font combinations:
Arial, Helvetica, sans-serifGeorgia, 'Times New Roman', Times, serif'Courier New', Courier, monospace
Font Size
.element {
font-size: 16px; /* Absolute size */
font-size: 1.25rem; /* Relative to root element */
font-size: 1.2em; /* Relative to parent element */
font-size: 100%; /* Percentage */
font-size: large; /* Keyword */
}
- Common units:
px: Fixed size (not ideal for accessibility)rem: Relative to root element’s font size (recommended)em: Relative to parent element’s font size%: Percentage of parent element’s font size- Keywords:
xx-small,x-small,small,medium,large,x-large,xx-large
Font Weight
.element {
font-weight: normal; /* Keyword */
font-weight: bold; /* Keyword */
font-weight: 400; /* Numeric value */
font-weight: 700; /* Numeric value */
}
- Defines the thickness of characters
- Numeric values: 100 (lightest) to 900 (boldest) in increments of 100
- Common numeric equivalents:
- 400 = normal
- 700 = bold
- Not all weights are available in every font
Font Style
.element {
font-style: normal; /* Default */
font-style: italic; /* Italicized text */
font-style: oblique; /* Slanted text */
}
Font Variant
.element {
font-variant: normal; /* Default */
font-variant: small-caps; /* Small caps */
}
Font Stretch
.element {
font-stretch: normal; /* Default */
font-stretch: condensed; /* Narrower */
font-stretch: expanded; /* Wider */
font-stretch: 50%; /* Percentage (50%-200%) */
}
Shorthand Font Property
.element {
/* font: style variant weight size/line-height family; */
font: italic bold 16px/1.5 'Helvetica Neue', Arial, sans-serif;
}
- Order matters in the shorthand property
font-sizeandfont-familyare required, others are optional
Text Properties
Text Alignment
.element {
text-align: left; /* Default for LTR languages */
text-align: right; /* Default for RTL languages */
text-align: center; /* Centered text */
text-align: justify; /* Text aligned to both left and right edges */
}
Text Decoration
.element {
text-decoration: none; /* No decoration */
text-decoration: underline; /* Underlined text */
text-decoration: overline; /* Line above text */
text-decoration: line-through; /* Strikethrough text */
/* Complex decoration with color and style */
text-decoration: underline dotted red;
}
Text Transform
.element {
text-transform: none; /* Default */
text-transform: capitalize; /* First Letter Of Each Word Capitalized */
text-transform: uppercase; /* ALL LETTERS UPPERCASE */
text-transform: lowercase; /* all letters lowercase */
}
Text Indent
.element {
text-indent: 2em; /* Indents the first line */
text-indent: -2em; /* Negative indent (hanging indent) */
}
Letter Spacing
.element {
letter-spacing: normal; /* Default */
letter-spacing: 0.1em; /* Positive value increases spacing */
letter-spacing: -0.05em; /* Negative value decreases spacing */
}
Word Spacing
.element {
word-spacing: normal; /* Default */
word-spacing: 0.2em; /* Increased space between words */
word-spacing: -0.05em; /* Decreased space between words */
}
Line Height
.element {
line-height: normal; /* Browser default (usually ~1.2) */
line-height: 1.5; /* Unitless value (recommended) */
line-height: 150%; /* Percentage */
line-height: 1.5em; /* Em-based */
line-height: 24px; /* Absolute unit */
}
- Unitless values are recommended (they’re inherited proportionally)
- Ideal line-height for readability: 1.4-1.6
- Different content may require different values:
- Headlines: 1.1-1.3
- Body text: 1.4-1.6
- Long-form content: 1.6-1.8
White Space
.element {
white-space: normal; /* Default - wraps as needed */
white-space: nowrap; /* Prevents wrapping */
white-space: pre; /* Preserves whitespace and line breaks */
white-space: pre-wrap; /* Preserves whitespace, wraps as needed */
white-space: pre-line; /* Preserves line breaks, wraps as needed */
}
Word Break
.element {
word-break: normal; /* Default */
word-break: break-all; /* May break within words */
word-break: keep-all; /* Prevents breaking within words */
}
Text Overflow
.element {
/* Required with text-overflow */
overflow: hidden;
white-space: nowrap;
text-overflow: clip; /* Default - clips overflowing text */
text-overflow: ellipsis; /* Shows "..." for overflowing text */
}
Typography Property Comparison
| Property | Controls | Inheritance | Default | Notes |
|---|---|---|---|---|
| font-family | Typeface | Yes | Browser default | Use font stacks for fallbacks |
| font-size | Text size | Yes | Medium (16px) | Prefer relative units (rem) |
| font-weight | Text thickness | Yes | Normal (400) | Not all weights available in all fonts |
| font-style | Italic/oblique | Yes | Normal | Depends on font having italic version |
| text-align | Horizontal alignment | Yes | Left (LTR) | Applies to block elements |
| line-height | Line spacing | Yes | Normal (~1.2) | Unitless values recommended |
| letter-spacing | Character spacing | Yes | Normal (0) | Affects readability |
| text-decoration | Underline, etc. | No | None | Can specify style, color |
| text-transform | Capitalization | Yes | None | Doesn’t change source text |
Responsive Typography
Fluid Typography with CSS Variables
:root {
--font-size-base: 16px;
--font-size-h1: 2.5rem;
--font-size-h2: 2rem;
}
@media (max-width: 768px) {
:root {
--font-size-base: 14px;
--font-size-h1: 2rem;
--font-size-h2: 1.7rem;
}
}
Fluid Typography with clamp()
h1 {
/* Min: 1.5rem, Preferred: 5vw, Max: 3rem */
font-size: clamp(1.5rem, 5vw, 3rem);
}
Typography Scale
A well-designed type scale creates visual hierarchy:
:root {
/* Scale ratio: 1.25 (major third) */
--text-xs: 0.8rem; /* 12.8px */
--text-sm: 0.9rem; /* 14.4px */
--text-base: 1rem; /* 16px */
--text-lg: 1.25rem; /* 20px */
--text-xl: 1.563rem; /* 25px */
--text-2xl: 1.953rem; /* 31.25px */
--text-3xl: 2.441rem; /* 39.06px */
--text-4xl: 3.052rem; /* 48.83px */
}
Common Typography Challenges & Solutions
Challenge: Maintaining Readable Line Lengths
Problem: Lines that are too long or short reduce readability.
Solution:
.content {
max-width: 65ch; /* Limit width to ~65 characters */
margin: 0 auto;
}
Challenge: Font Loading & FOUT (Flash of Unstyled Text)
Problem: Custom fonts may cause layout shifts during loading.
Solution:
/* Use font-display to control loading behavior */
@font-face {
font-family: 'CustomFont';
src: url('customfont.woff2') format('woff2');
font-display: swap; /* Show fallback until custom font loads */
}
/* Use font-family fallbacks with similar metrics */
body {
font-family: 'CustomFont', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}
Challenge: Inconsistent Font Sizes Across Browsers
Problem: Default font sizes vary between browsers.
Solution:
html {
font-size: 100%; /* Set base font size */
}
body {
font-size: 1rem; /* Use rem for consistent sizing */
font-family: system-ui, sans-serif;
}
Challenge: Text Overflow in Dynamic Content
Problem: Text may overflow containers when content length is unknown.
Solution:
.card-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.card-description {
display: -webkit-box;
-webkit-line-clamp: 3; /* Limit to 3 lines */
-webkit-box-orient: vertical;
overflow: hidden;
}
Best Practices & Tips
- Use a limited set of font weights (usually 400, 600, 700) to keep page weight down
- Set base font size on the html element (typically 100% or 16px)
- Use relative units (rem, em) for responsive text scaling
- Maintain proper contrast ratios for accessibility (WCAG AA: 4.5:1 for normal text)
- Establish a type scale with clear size relationships between headings and body text
- Limit line length to 45-75 characters (about 65ch) for optimal readability
- Test typography across devices to ensure consistent appearance
- Specify font-display to control how custom fonts load
- Use system font stacks for improved performance and native feel:
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
Web Fonts Implementation
Google Fonts
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
body {
font-family: 'Roboto', sans-serif;
}
Self-hosted Fonts with @font-face
@font-face {
font-family: 'CustomFont';
src: url('fonts/customfont.woff2') format('woff2'),
url('fonts/customfont.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
Variable Fonts
@font-face {
font-family: 'Variable';
src: url('fonts/variable.woff2') format('woff2-variations');
font-weight: 100 900;
font-stretch: 75% 125%;
font-style: normal;
}
.element {
font-family: 'Variable';
font-weight: 375;
font-stretch: 110%;
}
Resources for Further Learning
- MDN Web Docs: CSS Fonts
- Google Fonts
- Type Scale Calculator
- Fluid Type Scale Calculator
- Web Font Loading Patterns
- Typography Handbook
- Practical Typography
- Font Pair (Font combination suggestions)
- Contrast Checker
Browser Compatibility Notes
- Modern CSS font features (like
font-display) may not work in older browsers - Variable fonts require modern browser support
clamp()and other CSS functions have limited support in older browsers- Always include fallbacks for advanced typography features
Remember that effective typography enhances both the aesthetics and usability of your website. The right balance of font properties creates a visual hierarchy that guides users through your content while reinforcing your brand identity.
