CSSタイポグラフィプロパティ:完全リファレンス
CSS Typography Properties: The Complete Reference
Typography is at the heart of every well-designed web experience. Whether you're fine-tuning the reading experience of a long-form article or crafting a bold display headline for a landing page, CSS gives you an extensive toolkit for controlling how text looks, feels, and reads. This guide walks through every major CSS typography property, from the foundational font-family and font-size to the nuanced control of OpenType features through font-feature-settings.
By the end of this reference, you'll have a complete mental model of what each property does, when to use it, and how the pieces fit together into a coherent typographic system.
Font Properties: family, size, weight, style, stretch
These are the core building blocks. Before you can think about spacing or alignment, you need to establish the typeface, its size, its weight, and its style.
font-family
The font-family property defines the typeface used to render text. CSS uses a priority list — if the first font is unavailable, the browser falls back to the next, and so on.
body {
font-family: 'Inter', 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;
}
h1, h2, h3 {
font-family: 'Playfair Display', Georgia, 'Times New Roman', serif;
}
code, pre {
font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
}
The final value in your stack should always be a CSS generic family: serif, sans-serif, monospace, cursive, or fantasy. These map to the user's system preferences and guarantee that something sensible renders even when no other font is available.
When referencing multi-word font names, wrap them in single or double quotes. Single-word names like Roboto or Georgia need no quotes, though including them is harmless.
font-size
Font size controls the computed size of text. You can specify it in multiple units: px, rem, em, %, or viewport units like vw.
/* Base size using rem for accessibility */
html {
font-size: 16px; /* 1rem base */
}
body {
font-size: 1rem; /* 16px */
}
h1 {
font-size: 2.5rem; /* 40px */
}
h2 {
font-size: 2rem; /* 32px */
}
.small-print {
font-size: 0.875rem; /* 14px */
}
/* Using em — relative to the parent element */
.card {
font-size: 1.125em; /* 18px if parent is 16px */
}
.card .meta {
font-size: 0.8em; /* 14.4px — 80% of the card's 18px */
}
The rem unit is generally preferred for font sizes in production systems because it stays relative to the root html element, making your entire type scale respond predictably when users change their browser's default font size setting. See px vs rem vs em for a deep dive into choosing units.
font-weight
Font weight controls the visual heaviness of text. The specification defines numeric values from 100 to 900 in increments of 100.
.thin { font-weight: 100; }
.extra-light { font-weight: 200; }
.light { font-weight: 300; }
.regular { font-weight: 400; } /* default */
.medium { font-weight: 500; }
.semi-bold { font-weight: 600; }
.bold { font-weight: 700; }
.extra-bold { font-weight: 800; }
.black { font-weight: 900; }
/* Keyword equivalents */
p { font-weight: normal; } /* 400 */
strong { font-weight: bold; } /* 700 */
Named keywords are also valid: normal (equivalent to 400) and bold (equivalent to 700). The relative keywords lighter and bolder adjust weight relative to the inherited value, following a lookup table defined in the spec.
If a font family doesn't include the requested weight, the browser synthesizes it — which can produce poor results. Always check what weights your chosen font actually includes. Inter, Roboto, and Source Sans 3 all ship with the full 100–900 range.
font-style
Font style primarily controls whether text is rendered in italic or oblique form.
em {
font-style: italic;
}
blockquote {
font-style: italic;
}
.reset-italic {
font-style: normal;
}
/* Oblique with a specific angle (variable fonts) */
.slanted {
font-style: oblique 15deg;
}
The difference between italic and oblique is meaningful: italic is a separate, specially designed face where the letterforms themselves are different (particularly visible in lowercase a, e, and g). Oblique is simply a slanted version of the regular face, produced either by the font or by the browser synthetically.
When a font has a true italic face, font-style: italic will use it. When it doesn't, the browser falls back to oblique synthesis.
font-stretch
Font stretch selects the width of the face — from ultra-condensed to ultra-expanded.
.condensed-heading {
font-stretch: condensed;
}
.normal-width {
font-stretch: normal;
}
.wide-display {
font-stretch: expanded;
}
/* Percentage values (useful for variable fonts) */
.tight-body {
font-stretch: 85%;
}
.airy-display {
font-stretch: 125%;
}
Valid keyword values: ultra-condensed, extra-condensed, condensed, semi-condensed, normal, semi-expanded, expanded, extra-expanded, ultra-expanded. Percentage values (50% to 200%) are also accepted.
This property only works when the font actually includes condensed or expanded variants. For variable fonts, it maps directly to the wdth axis, which can accept any value within its defined range.
Text Properties: align, transform, decoration, indent
Once you've established the typeface, you need to control how text is arranged and styled on the page.
text-align
Controls horizontal alignment of inline content within a block.
.center-heading {
text-align: center;
}
article p {
text-align: left; /* best for reading in LTR languages */
}
.pull-quote {
text-align: center;
}
.price {
text-align: right;
}
/* Justified text — use with care */
.column-text {
text-align: justify;
hyphens: auto; /* Prevent rivers of whitespace */
}
/* start/end for logical properties (respects writing direction) */
.intro {
text-align: start;
}
Avoid justified text (text-align: justify) for body copy on the web unless you also enable hyphens: auto. Without hyphenation, the browser creates uneven word spacing that produces "rivers" of whitespace, degrading readability significantly.
text-transform
Controls capitalization of text characters.
/* Navigation labels */
nav a {
text-transform: uppercase;
letter-spacing: 0.1em; /* Capitals need extra spacing */
}
/* Proper names */
.author-name {
text-transform: capitalize; /* Capitalizes first letter of each word */
}
/* Reset inherited transform */
.no-transform {
text-transform: none;
}
/* Full-width characters (useful for East Asian contexts) */
.fullwidth {
text-transform: full-width;
}
One important gotcha: capitalization applied via CSS is purely visual. Screen readers typically read the underlying HTML content, so avoid using text-transform: uppercase as a substitute for semantic meaning. It's purely a presentational tool.
text-decoration
Controls underlines, overlines, strikethroughs, and their styling.
/* Remove underline from links in navigation */
nav a {
text-decoration: none;
}
/* Custom underline styling */
a {
text-decoration: underline;
text-decoration-color: #4f46e5;
text-decoration-thickness: 2px;
text-underline-offset: 3px;
}
/* Dotted underline for abbreviations */
abbr[title] {
text-decoration: underline dotted;
cursor: help;
}
/* Strikethrough for deleted content */
del {
text-decoration: line-through;
text-decoration-color: #ef4444;
}
/* Multiple decorations */
.fancy {
text-decoration: underline overline;
text-decoration-style: wavy;
text-decoration-color: hotpink;
}
The text-underline-offset property is particularly valuable for readability — pushing the underline down slightly from the baseline prevents it from overlapping descenders (letters like g, p, q, y). A value of 3–4px is a good starting point.
text-indent
Adds indentation to the first line of a text block.
/* Classical print-style paragraph indentation */
.prose p + p {
text-indent: 1.5em;
margin-top: 0; /* Remove space between paragraphs when using indent */
}
/* Negative indent for hanging punctuation effect */
.hanging {
text-indent: -0.5em;
padding-left: 0.5em;
}
/* Hide text accessibly (for image replacement) */
.logo-text {
text-indent: -9999px;
}
On the web, most designs use margin-based paragraph separation rather than indentation, but text-indent is still useful for print stylesheets and highly literary-style content.
Spacing: line-height, letter-spacing, word-spacing
Spacing is where reading comfort lives. The right line-height, letter-spacing, and word-spacing can be the difference between text that feels inviting and text that feels claustrophobic or scattered.
line-height
Line height controls the vertical space between lines of text within a paragraph. It's one of the most impactful properties for readability.
/* Unitless is best — inherits proportionally */
body {
line-height: 1.6;
}
/* Tighter for headings */
h1, h2, h3 {
line-height: 1.15;
}
/* Loose for captions or small text */
.caption {
line-height: 1.4;
}
/* Fixed value — useful for precise control */
.compact-ui {
font-size: 14px;
line-height: 20px;
}
/* Normal keyword resets to browser default */
.reset {
line-height: normal;
}
Always prefer unitless line-height values (like 1.6) over fixed units. A unitless value is a multiplier — it scales proportionally with the font-size of the element and any child elements that inherit it. If you use 24px directly, child elements with different font-sizes won't scale correctly.
For body text in a reading context, values between 1.4 and 1.7 are generally considered ideal by readability research. Display headings can be much tighter, often 1.1 to 1.2.
letter-spacing
Controls the horizontal space added between individual characters (also called tracking in print typography).
/* Uppercase labels need generous tracking */
.label {
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 0.75rem;
}
/* Tight tracking for large display type */
.hero-headline {
font-size: clamp(3rem, 8vw, 7rem);
letter-spacing: -0.03em;
}
/* Loose tracking for small caps */
.small-caps {
font-variant: small-caps;
letter-spacing: 0.05em;
}
/* Reset letter-spacing */
.normal-spacing {
letter-spacing: normal;
}
The unit em is best for letter-spacing because it scales with the font size. As a rule of thumb: uppercase text needs positive tracking (0.05em to 0.15em), large display text often benefits from negative tracking (-0.02em to -0.05em), and body text is best left at normal or very slightly adjusted.
word-spacing
Controls the extra space added between words. Use sparingly — browser defaults are usually well-calibrated.
/* Tighten word spacing for display type */
.display-text {
word-spacing: -0.05em;
}
/* Wider spacing for a spread-out feel */
.spaced-ui {
word-spacing: 0.1em;
}
/* Reset to normal */
.body-text {
word-spacing: normal;
}
Unlike letter-spacing, word-spacing is rarely needed in practice. It becomes most useful for justified text where you want to add slight space, or for display contexts where you're pushing visual design to extremes.
Advanced: font-variant, font-feature-settings
These properties give you access to the OpenType feature set of a typeface — things like small caps, old-style numerals, ligatures, and more.
font-variant
The font-variant property (and its sub-properties) control access to typographic alternates baked into the font.
/* Classic small-caps */
.small-caps {
font-variant-caps: small-caps;
}
/* Petite caps (smaller than small caps) */
.petite-caps {
font-variant-caps: petite-caps;
}
/* Old-style figures (numbers that have ascenders/descenders) */
.old-style-nums {
font-variant-numeric: oldstyle-nums;
}
/* Tabular figures for tables */
table {
font-variant-numeric: tabular-nums;
}
/* Both old-style AND tabular */
.financial-data {
font-variant-numeric: oldstyle-nums tabular-nums;
}
/* Proportional lining figures */
.modern-nums {
font-variant-numeric: lining-nums proportional-nums;
}
/* Common ligatures (usually on by default) */
.ligatures {
font-variant-ligatures: common-ligatures;
}
/* Discretionary ligatures (fi, fl, ffi, ffl, etc.) */
.rich-ligatures {
font-variant-ligatures: common-ligatures discretionary-ligatures;
}
font-feature-settings
This is the low-level escape hatch for OpenType features. While font-variant provides a semantic interface, font-feature-settings lets you specify any feature tag directly.
/* Enable small caps via feature tag */
.small-caps {
font-feature-settings: 'smcp' 1;
}
/* Old-style figures */
.onum {
font-feature-settings: 'onum' 1;
}
/* Tabular lining figures */
.tnum {
font-feature-settings: 'tnum' 1, 'lnum' 1;
}
/* Swash characters */
.swash {
font-feature-settings: 'swsh' 1;
}
/* Stylistic set 01 (font-specific alternates) */
.alt-style {
font-feature-settings: 'ss01' 1;
}
/* Multiple features */
.refined-typography {
font-feature-settings:
'kern' 1, /* Kerning */
'liga' 1, /* Ligatures */
'calt' 1, /* Contextual alternates */
'onum' 1; /* Old-style figures */
}
/* Reset all feature settings */
.reset-features {
font-feature-settings: normal;
}
Common OpenType feature tags worth knowing:
- kern — Kerning (adjustment of spacing between specific letter pairs)
- liga — Standard ligatures (fi, fl, ff)
- dlig — Discretionary ligatures
- onum — Old-style numerals
- lnum — Lining numerals
- tnum — Tabular numerals
- pnum — Proportional numerals
- smcp — Small capitals
- c2sc — Capitals to small capitals
- sups — Superscript
- subs — Subscript
- frac — Fractions
- ordn — Ordinals (1st, 2nd)
- calt — Contextual alternates
- ss01 through ss20 — Stylistic sets
Note that font-feature-settings should be used as a last resort. The CSS working group recommends using the higher-level font-variant sub-properties whenever possible, because font-feature-settings overrides all other feature settings on the element, which can cause subtle cascade problems.
Shorthand: The font Property
The font shorthand property lets you set multiple font properties in a single declaration.
/* Syntax: font-style font-variant font-weight font-stretch font-size/line-height font-family */
/* Basic usage */
p {
font: 400 1rem/1.6 'Inter', sans-serif;
}
/* With style and weight */
blockquote {
font: italic 300 1.125rem/1.7 'Lora', Georgia, serif;
}
/* With all properties */
.display {
font: italic small-caps 700 condensed 3rem/1.1 'Playfair Display', serif;
}
/* System font values */
button {
font: -apple-system-body; /* Matches system UI body font */
}
.system-ui-example {
font-family: system-ui; /* The CSS generic for system fonts */
}
The font shorthand has strict ordering rules. The required values are font-size and font-family — everything else is optional. However, if you include line-height, it must immediately follow font-size separated by a slash. Font-size and line-height must appear together in this position.
One important gotcha: the font shorthand resets any font properties you don't explicitly specify back to their initial values. This makes it less useful in inheritance-heavy component systems. Prefer individual properties in those contexts.
System font keywords are also valid values for the entire font property: caption, icon, menu, message-box, small-caption, status-bar. These adopt the font used by the corresponding OS UI element.
CSS Custom Properties for Typography
CSS custom properties (variables) are the foundation of a maintainable type system. They let you define your scale once and reference it everywhere.
Defining a Type Scale
:root {
/* Base size */
--font-size-base: 1rem;
/* Type scale using a 1.25 major third ratio */
--font-size-xs: 0.64rem; /* 10.24px */
--font-size-sm: 0.8rem; /* 12.8px */
--font-size-base: 1rem; /* 16px */
--font-size-md: 1.25rem; /* 20px */
--font-size-lg: 1.563rem; /* 25px */
--font-size-xl: 1.953rem; /* 31.25px */
--font-size-2xl: 2.441rem; /* 39px */
--font-size-3xl: 3.052rem; /* 48.83px */
/* Line heights */
--line-height-tight: 1.15;
--line-height-snug: 1.35;
--line-height-normal: 1.5;
--line-height-relaxed: 1.65;
--line-height-loose: 1.8;
/* Font families */
--font-sans: 'Inter', 'Helvetica Neue', Arial, sans-serif;
--font-serif: 'Lora', Georgia, 'Times New Roman', serif;
--font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
/* Font weights */
--font-weight-light: 300;
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* Letter spacing */
--tracking-tight: -0.025em;
--tracking-normal: 0em;
--tracking-wide: 0.025em;
--tracking-wider: 0.05em;
--tracking-widest: 0.1em;
}
Using Custom Properties in Components
/* Apply the system */
body {
font-family: var(--font-sans);
font-size: var(--font-size-base);
line-height: var(--line-height-normal);
font-weight: var(--font-weight-regular);
}
h1 {
font-size: var(--font-size-3xl);
line-height: var(--line-height-tight);
font-weight: var(--font-weight-bold);
letter-spacing: var(--tracking-tight);
}
h2 {
font-size: var(--font-size-2xl);
line-height: var(--line-height-snug);
font-weight: var(--font-weight-semibold);
letter-spacing: var(--tracking-tight);
}
.lead {
font-size: var(--font-size-md);
line-height: var(--line-height-relaxed);
font-weight: var(--font-weight-light);
}
code {
font-family: var(--font-mono);
font-size: 0.875em; /* Slightly smaller than surrounding text */
}
Responsive Typography with Custom Properties
Custom properties can be redefined in media queries, enabling a clean responsive type system:
:root {
--font-size-base: 1rem;
--font-size-xl: 1.75rem;
--font-size-2xl: 2.25rem;
--font-size-3xl: 2.75rem;
}
@media (min-width: 768px) {
:root {
--font-size-xl: 2rem;
--font-size-2xl: 2.75rem;
--font-size-3xl: 3.5rem;
}
}
@media (min-width: 1200px) {
:root {
--font-size-xl: 2.25rem;
--font-size-2xl: 3rem;
--font-size-3xl: 4rem;
}
}
This pattern means every element that uses these variables automatically gets the right size at every breakpoint — no need to repeat breakpoint logic at every component level.
Component-Level Overrides
Custom properties cascade, so you can override them at a component level without breaking the global scale:
.prose {
/* Override for long-form reading */
--font-size-base: 1.125rem;
--line-height-normal: 1.7;
--font-sans: 'Source Serif 4', Georgia, serif;
font-family: var(--font-sans);
font-size: var(--font-size-base);
line-height: var(--line-height-normal);
}
.ui-compact {
/* Override for dense UI */
--font-size-base: 0.875rem;
--line-height-normal: 1.4;
}
Theming with Custom Properties
Custom properties enable powerful theming systems, including dark mode typographic adjustments:
:root {
--font-weight-body: 400;
--font-weight-heading: 700;
}
@media (prefers-color-scheme: dark) {
:root {
/* Reduce weight slightly in dark mode — lighter strokes are easier to read
against a dark background at the same perceived contrast */
--font-weight-body: 350;
--font-weight-heading: 600;
}
}
This technique works well with variable fonts that support the full weight spectrum — Inter and Roboto Flex are excellent choices for this pattern.
Putting It All Together
Here's a complete, production-ready typography foundation using all the properties covered in this guide:
/* === Typography Foundation === */
:root {
/* Fonts */
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-serif: 'Lora', Georgia, serif;
--font-mono: 'JetBrains Mono', 'Courier New', monospace;
/* Scale */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
--text-5xl: 3rem;
/* Weights */
--weight-light: 300;
--weight-regular: 400;
--weight-medium: 500;
--weight-semibold: 600;
--weight-bold: 700;
--weight-black: 900;
/* Line heights */
--leading-none: 1;
--leading-tight: 1.2;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.625;
--leading-loose: 2;
}
/* Base */
html {
font-size: 16px;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
body {
font-family: var(--font-sans);
font-size: var(--text-base);
font-weight: var(--weight-regular);
line-height: var(--leading-normal);
font-feature-settings: 'kern' 1, 'liga' 1, 'calt' 1;
text-rendering: optimizeLegibility;
}
/* Headings */
h1, h2, h3, h4, h5, h6 {
font-weight: var(--weight-bold);
line-height: var(--leading-tight);
letter-spacing: -0.02em;
}
h1 { font-size: var(--text-5xl); }
h2 { font-size: var(--text-4xl); }
h3 { font-size: var(--text-3xl); }
h4 { font-size: var(--text-2xl); }
h5 { font-size: var(--text-xl); }
h6 { font-size: var(--text-lg); }
/* Body text */
p {
max-width: 70ch; /* Optimal line length for reading */
}
/* Code */
code, kbd, pre, samp {
font-family: var(--font-mono);
font-size: 0.875em;
font-feature-settings: 'liga' 0; /* Disable ligatures in code */
}
/* Links */
a {
text-underline-offset: 3px;
text-decoration-thickness: 1px;
}
/* Small text utilities */
.text-small {
font-size: var(--text-sm);
line-height: var(--leading-relaxed);
}
/* Caption and metadata */
.text-caption {
font-size: var(--text-xs);
letter-spacing: 0.02em;
color: currentColor;
opacity: 0.7;
}
CSS typography is a deep system with many interdependent parts. The properties here work together: your choice of font-family affects what weights and styles are available; your line-height should scale with your font-size; your letter-spacing should respond to your text-transform. Master each property individually, then study how they interact, and you'll have the foundations to build typographic systems that are both beautiful and robust.
CSS Typography Deep Dive
Typography Terms
Try These Tools
Fonts Mentioned
Designed by Christian Robertson for Google's Material Design ecosystem, this neo-grotesque sans-serif is the most widely used typeface on the web and Android. Its dual-nature design balances mechanical precision with natural reading rhythm, making it equally at home in UI labels and long-form text. The variable font supports width and weight axes alongside Cyrillic, Greek, and extended Latin scripts.
Rasmus Andersson spent years refining this neo-grotesque specifically for computer screens, optimizing letter spacing, x-height, and stroke contrast for high readability at small sizes on digital displays. An optical size axis (opsz) lets the font automatically adjust its design for captions versus headlines, while the weight axis covers the full range from thin to black. It has become the de facto choice for dashboards, documentation sites, and developer tools worldwide.