Font Weight, Style, and Variant in CSS
What You Learn From This Page
- How font-weight controls typographic thickness and hierarchy.
- How normal, italic, and angled oblique styles differ.
- How font-variant and its subproperties enable small caps, numeric forms, and ligatures.
- How missing faces, variable fonts, inheritance, and browser synthesis affect results.
- How to apply these properties accessibly and debug the actual rendered face.
Introduction
CSS offers several properties for controlling the typographic form and emphasis of text. font-weight controls relative darkness or stroke thickness, font-style selects upright, italic, or oblique forms, and font-variant activates alternate typographic forms such as small capitals. More specific variant properties control numbers, ligatures, East Asian forms, and superscript or subscript glyphs.
These declarations do not manufacture unlimited styles from any font. They participate in font matching: the browser searches the chosen family for a face supporting the requested weight, style, and features. When a suitable face is missing, it may select a nearby face or synthesize an approximation. Understanding that relationship between CSS requests and font capabilities is essential for predictable production typography.
The Three Core Responsibilities
The properties solve different problems. Weight creates visual hierarchy between body text, labels, and headings. Style selects an upright or slanted design, often supporting emphasis, citations, or editorial conventions. Variant chooses alternate glyph forms without changing the underlying text content.
.heading {
font-weight: 700;
font-style: italic;
font-variant: small-caps;
}
They can be combined, but each extra treatment should have a purpose. Bold italic small caps may be technically valid and visually excessive. Good typography uses the smallest set of distinctions needed to communicate structure and meaning.
What font-weight Controls
The font-weight property specifies the weight of glyphs, commonly perceived as boldness, darkness, or stroke thickness. A higher numeric value represents a weight at least as dark as the preceding value within the CSS scale, though the visual difference depends entirely on the selected family.
p { font-weight: 400; }
.label { font-weight: 500; }
h2 { font-weight: 700; }
Weight is useful for hierarchy, but it should not carry meaning alone. Screen size, contrast, font design, and text size all influence whether a particular weight remains readable.
Keyword Weight Values
The common keywords are normal, bold, lighter, and bolder. Normal computes to 400 and bold computes to 700. Lighter and bolder are relative to the inherited weight rather than fixed synonyms for one numeric step.
.body-copy { font-weight: normal; }
.important { font-weight: bold; }
.nested-note { font-weight: lighter; }
.nested-heading { font-weight: bolder; }
Use numeric values when a design system needs explicit levels. Relative keywords are useful when a child should express contrast from its context without knowing that context's exact number.
Numeric Weight Values
Traditional examples show weights in increments of 100: 100 thin, 200 extra light, 300 light, 400 regular, 500 medium, 600 semibold, 700 bold, 800 extra bold, and 900 black. These labels are conventions, not guarantees that every family contains all nine faces.
Modern CSS permits numeric weights from 1 through 1000. Static families usually expose selected values, while variable fonts can provide a continuous range and render values such as 450 or 575 when their supported weight axis includes them. Always confirm the actual family capabilities.
Weight Reference Table
| Common value | Typical label | Common role |
|---|---|---|
| 100 | Thin | Large display text only when legible |
| 200 | Extra Light | Decorative large typography |
| 300 | Light | Secondary display typography |
| 400 | Regular | Body text |
| 500 | Medium | Controls and labels |
| 600 | Semibold | Subheadings and emphasis |
| 700 | Bold | Primary headings |
| 800 | Extra Bold | Strong display text |
| 900 | Black | Heavy display emphasis |
The table is a vocabulary guide, not a promise about appearance. One family's 600 may look lighter than another family's 500 because weight values are relative within a family.
normal and bold
font-weight: normal is equivalent to 400, and font-weight: bold is equivalent to 700. The browser then matches those requested values against available faces. If a precise face is absent, matching or synthesis rules determine the visible result.
body { font-weight: normal; }
strong { font-weight: bold; }
The strong element adds semantic importance independently of how it looks. CSS can style it with another weight, but removing bold appearance does not remove its semantic meaning.
lighter and bolder
Relative weight keywords are calculated from the parent's inherited weight. They do not simply add or subtract 100. CSS maps the inherited value into broader relative classes and chooses a computed lighter or bolder result according to defined rules.
.card {
font-weight: 400;
}
.card__title {
font-weight: bolder;
}
This makes a component contextual, but exact results can surprise developers expecting arithmetic. Use a numeric token such as 600 or 700 when the design requires a stable, explicit heading level.
Missing Static Weights
A static font family may provide only regular 400 and bold 700. If CSS requests 500, the browser uses its font matching algorithm to select a nearby available face. Requesting 900 does not guarantee a genuine black face, and the browser may approximate the request.
For downloadable fonts, align the loaded faces with CSS usage. For system stacks, accept that installed capabilities vary and test the likely outcomes. Typography should remain readable even when the exact requested weight cannot be rendered.
Variable Fonts and Continuous Weight
A variable font can expose a wght axis covering a range such as 100 through 900 or another family-specific interval. Values inside that range can represent designed interpolation rather than selection among a few static files.
.title {
font-family: "Variable Sans", sans-serif;
font-weight: 550;
}
Intermediate values are useful only when the font supports them and the difference serves a role. Do not create dozens of nearly indistinguishable weights that weaken hierarchy. A small semantic scale remains easier to maintain.
Building a Weight Hierarchy
A practical hierarchy might use 400 for body text, 500 for controls or metadata, 600 for section headings, and 700 for page titles. The exact values depend on family design, size, contrast, and density.
body { font-weight: 400; }
.control-label { font-weight: 500; }
h2 { font-weight: 600; }
h1 { font-weight: 700; }
Review the levels together. If 500 and 600 appear identical in the selected font, the hierarchy may need spacing, size, or color support instead of another weight.
Weight and Accessibility
Very thin faces can lose strokes on low-density displays, small sizes, or low-contrast color combinations. Body text at 100 or 200 may satisfy a visual trend while imposing unnecessary reading effort. Regular or medium weights are generally safer starting points for essential content.
Heavy text can also reduce clarity when counters close or letterforms become dense. Test actual devices, zoom, high-contrast settings, and users' bold text preferences where relevant. Weight should reinforce hierarchy without becoming the sole indicator of state or meaning.
What font-style Controls
The font-style property selects an upright normal face, an italic face, or an oblique face. Italic commonly refers to a separately designed set of letterforms, while oblique commonly refers to a slanted form. Actual family support and browser matching determine the result.
.plain { font-style: normal; }
.citation { font-style: italic; }
.note { font-style: oblique; }
Style inherits, so setting italic on a blockquote normally affects descendant text unless another rule resets it.
Normal Style
font-style: normal requests the upright face. It is the initial value and can reset italic or oblique inherited from an ancestor. This is useful when a nested label or attribution should remain upright inside an italic quotation.
blockquote { font-style: italic; }
blockquote cite { font-style: normal; }
The reset is visual only. The semantic roles still come from HTML and document structure. Do not use normal style to imply that a citation is no longer a citation.
Italic Style
font-style: italic requests the family's italic face. A designed italic may use different constructions rather than merely slanting upright letters. This can improve rhythm and distinction for emphasis, publication titles, citations, terminology, and editorial conventions.
em,
.publication-title {
font-style: italic;
}
Ensure the italic face includes required scripts and weights. A family may support regular italic but not bold italic, or cover fewer glyphs in the italic resource than in the upright face.
Oblique Style
font-style: oblique requests an oblique face. Such a face typically preserves upright letter construction while applying a designed slant. If the family lacks an appropriate face and synthesis is allowed, the browser may geometrically shear upright glyphs.
.aside-note {
font-style: oblique;
}
A true oblique face can preserve stroke relationships better than automatic slanting. Whether italic and oblique appear distinct depends on the family and user agent's matching behavior.
Oblique Angles
CSS allows an optional angle with oblique style. A positive angle requests a clockwise slant in horizontal writing, while a negative value requests the opposite direction. The font or browser must be able to match or synthesize the result.
.quote {
font-style: oblique 12deg;
}
Angles should be used sparingly. A custom slant can be useful with a variable slant axis or deliberate display design, but extreme angles damage readability and may not map to an actual face.
Italic Versus Oblique
| Aspect | Italic | Oblique |
|---|---|---|
| Primary idea | Distinct italic design | Slanted form |
| Letterforms | Often redesigned | Often based on upright forms |
| Angle control | No angle in the property value | Optional CSS angle |
| Synthesis | Depends on matching behavior | Can be synthesized when allowed |
| Common role | Emphasis and editorial text | Stylistic slant and display treatment |
The visual distinction is font-specific. Inspect the rendered face instead of assuming that the two keywords always produce obviously different text.
Semantic em Versus Visual Italic
The HTML em element expresses stress emphasis. Italic is a visual treatment. Browsers commonly style em with italic text, but CSS can change that presentation without changing the document meaning.
em {
font-style: italic;
}
Use semantic markup when emphasis affects interpretation or assistive technology. Use a class with font-style for purely visual conventions such as publication titles. Do not replace meaningful markup with a generic span merely to obtain slanted text.
What font-variant Controls
The font-variant shorthand controls alternate typographic forms. Its traditional CSS2-era use is small-caps, but modern CSS defines specific variant properties for capitals, numeric forms, ligatures, East Asian typography, and vertical positions.
.section-label {
font-variant: small-caps;
}
Variant features depend on font support. If a designed glyph is absent, the browser may synthesize a form or leave the text closer to normal, depending on the feature and synthesis settings.
Small Caps
Small caps display lowercase-origin text using capital-shaped glyphs sized and spaced to harmonize with lowercase text. A font with true small-cap glyphs provides better stroke weight and proportions than simply shrinking full uppercase letters.
.category {
font-variant-caps: small-caps;
letter-spacing: 0.05em;
}
Small caps work well for short categories, running labels, acronyms, and editorial details. Long paragraphs in small caps are harder to read and reduce word-shape variation.
Small Caps Versus text-transform
text-transform: uppercase maps text to uppercase characters and displays full-size capitals. Small caps preserve a hierarchy between original uppercase and lowercase-origin letters through specially designed smaller capitals when available.
.full-caps { text-transform: uppercase; }
.typographic-caps { font-variant-caps: small-caps; }
These are not interchangeable visual effects. Text transformation can also have language-sensitive behavior. Choose based on content and typography, and verify what users copy or encounter through accessibility tools.
font-variant-caps
The dedicated capitals property supports values such as small-caps, all-small-caps, petite-caps, all-petite-caps, unicase, and titling-caps. A family may implement only some of these OpenType features.
Use feature detection through visual and font-capability testing rather than assuming every valid CSS value produces a distinct designed form. Provide an acceptable normal presentation when specialized caps are unavailable.
font-variant-numeric
The numeric variant property controls alternate number forms. Common values include tabular-nums, proportional-nums, lining-nums, oldstyle-nums, slashed-zero, and fraction-related features where the font supports them.
.financial-value {
font-variant-numeric:
tabular-nums lining-nums;
}
This is one of the most practical variant controls for dashboards, data tables, clocks, counters, and financial interfaces because it can improve alignment without changing the underlying text.
Tabular Versus Proportional Numbers
Tabular numerals use equal advance widths so columns align and changing counters remain visually stable. Proportional numerals use widths suited to each digit and can look more natural inside running prose.
.data-table,
.live-counter {
font-variant-numeric: tabular-nums;
}
article {
font-variant-numeric: proportional-nums;
}
Tabular values do not add semantic table structure. Use proper table markup for relationships, and use the font feature to improve numeric alignment within that structure.
Oldstyle and Lining Numbers
Lining numerals generally share a capital-height alignment and suit interfaces, tables, and all-cap contexts. Oldstyle numerals vary in height and may have ascenders or descenders, allowing them to blend with lowercase editorial text.
.essay {
font-variant-numeric: oldstyle-nums;
}
.metric {
font-variant-numeric: lining-nums;
}
The selected font must contain the alternate glyphs. In an unsupported face, these values may not create a visible difference.
font-variant-ligatures
Ligatures replace particular character sequences with coordinated glyphs. Common typographic examples include combinations such as fi and fl. The ligature property can control common, discretionary, historical, and contextual forms depending on the font.
.article-copy {
font-variant-ligatures: common-ligatures;
}
Common ligatures can improve text texture, while discretionary effects may be too decorative for interfaces. Code samples often need predictable individual characters, so decorative ligatures should be evaluated carefully in technical contexts.
Position and East Asian Variants
font-variant-position can request designed superscript or subscript forms, while font-variant-east-asian controls specialized glyph forms relevant to East Asian typography. These are typographic features, not replacements for semantic HTML such as sup and sub when document structure matters.
Only use language- and script-specific features with appropriate content knowledge and font support. A valid declaration can still be irrelevant or visually ineffective for the chosen family and text.
Combining Weight, Style, and Variants
A component can combine a medium or bold weight with tabular numbers, while editorial labels might combine small caps with spacing. The properties operate independently but must resolve through a face that supports the requested combination.
.metric {
font-weight: 600;
font-style: normal;
font-variant-numeric: tabular-nums;
}
.category {
font-weight: 500;
font-variant-caps: small-caps;
}
Test combinations directly. A family may support a feature in its regular face but not in every italic or bold face.
Article Typography Example
article h2 {
font-weight: 700;
}
article blockquote {
font-style: italic;
}
article .category {
font-variant-caps: small-caps;
}
Each treatment has a separate role: heading hierarchy, editorial quotation styling, and category labeling. Because the properties inherit, keep selectors scoped so an italic blockquote does not accidentally make its citation or interactive controls italic unless that is intended.
Dashboard Typography Example
.metric__value {
font-weight: 600;
font-variant-numeric: tabular-nums;
}
.metric__change {
font-weight: 500;
font-style: normal;
}
Weight gives the current value prominence, while tabular numerals keep changing digits stable and align repeated metrics. Status meaning should also be expressed through labels, icons, or accessible state, not only through weight or color.
Button and Caption Examples
Buttons usually benefit from upright medium or semibold text because labels must be scanned quickly. Captions may use italic when it supports the editorial convention, but size, contrast, and line height must remain readable.
.button {
font-weight: 600;
font-style: normal;
}
.caption {
font-size: 0.875rem;
font-weight: 400;
font-style: italic;
}
A caption should not become faint merely because it is secondary. Visual hierarchy can use spacing and size without sacrificing contrast or legibility.
Inheritance Behavior
Font weight, style, and variant properties generally inherit. A card assigned weight 500 passes that computed weight to descendants unless they override it. An italic blockquote and a small-cap label group similarly influence nested text.
.card { font-weight: 500; }
blockquote { font-style: italic; }
.label-group { font-variant-caps: small-caps; }
Inheritance reduces repetition but can create unintended typography in nested controls, code samples, or icons. Inspect the ancestor chain when a child unexpectedly appears bold, italic, or variant-styled.
The font Shorthand
The font shorthand can combine style, a limited variant grammar, weight, size, line height, and family. Size and family are required, while optional components must follow the shorthand grammar.
.title {
font: italic 700 2rem/1.2 "Inter", sans-serif;
}
This roughly requests italic style, weight 700, a 2rem size, 1.2 line height, and an Inter-based stack. The shorthand resets omitted font longhands, including modern settings not visibly represented, so use it when defining a complete state rather than making a narrow change.
Designed Faces Versus Synthetic Faces
When a family lacks the requested face, browsers may synthesize an approximation. Synthetic bold can thicken glyphs, synthetic oblique can shear upright forms, and synthetic small caps can scale uppercase glyphs. These fallbacks keep a distinction visible but rarely match forms designed by a type designer.
Important brand and publication typography should provide actual faces or variable ranges. General interfaces should still tolerate synthesis or fallback because installed system fonts vary. Evaluate the visible result rather than assuming the requested CSS guarantees a designed face.
Controlling Font Synthesis
The font-synthesis family of properties controls whether user agents may create missing weight, style, small-cap, or position forms. Disabling synthesis can prevent undesirable approximations, but it can also remove an expected distinction when no real face exists.
.brand-heading {
font-synthesis: none;
}
Use this only with a verified face set and reliable fallback plan. A request for bold should not become visually regular without another means of communicating hierarchy.
Common Mistake: Unsupported Weight
Requesting 900 from a family that contains only 400 and 700 does not create the intended black face. Matching or synthesis may produce something heavier, but the result can vary and may not preserve letter quality.
For web fonts, load or define the actual weights used. For system fonts, choose a small resilient scale and test platform fallbacks. Inspect rendered-font details in DevTools instead of checking only the computed numeric value.
Common Mistake: Synthetic Bold and Italic
Browsers can synthesize a missing bold or slanted face, which makes an incomplete font package appear functional. The approximation may have uneven strokes, crowded counters, or awkward script-specific forms. It can also differ among rendering engines.
Provide true bold and italic faces for important typography. Load only those styles the page actually uses, then test permanent fallback conditions where another family supplies the emphasis.
Common Mistake: Italic as Generic Secondary Styling
Applying italic to every secondary label, hint, timestamp, and metadata field reduces its meaning and can make dense interfaces harder to scan. Italic works best when it follows a typographic convention or communicates emphasis within context.
Use size, spacing, color with adequate contrast, or placement for secondary hierarchy. Reserve italic for roles where the slanted form adds useful distinction rather than treating it as a universal dimming technique.
Common Mistake: Confusing CSS with Semantics
font-weight: bold creates a visual appearance, while strong expresses importance. font-style: italic creates a visual treatment, while em expresses stress emphasis. Visual and semantic choices often align, but they are not interchangeable.
Start with the correct HTML meaning, then use CSS to create the desired presentation. A screen reader does not infer importance merely because a generic span is bold, and changing the visual style of strong does not erase its semantics.
Common Mistake: Assuming Real Small Caps
A small-caps declaration does not prove that the family contains designed small-cap glyphs. A browser may synthesize them by shrinking uppercase forms, which can produce strokes that look too light and spacing that feels uneven.
Use a family with verified OpenType small-cap support for high-quality editorial typography. Test every required weight and style combination, and provide a normal or uppercase fallback that remains acceptable if the feature is absent.
Variant Properties Versus font-feature-settings
The low-level font-feature-settings property can address OpenType feature tags directly, but it should not replace a clear high-level CSS property when one exists. A declaration such as font-variant-numeric: tabular-nums communicates intent, participates in the standardized cascade model for that feature, and is easier for a team to review than an unexplained feature tag.
.accounting-table {
font-variant-numeric: tabular-nums lining-nums;
}
Reserve low-level settings for specialized features that have no suitable higher-level control, and document the tag and supported fonts. Feature tags are font capabilities, not universal visual commands. The declaration may have no effect when the selected face lacks the requested glyph forms.
Centralize Typographic Roles with Tokens
Design systems can name recurring roles rather than scattering numbers and styles across selectors. Tokens for body, medium control, and strong heading weights keep hierarchy consistent, while component CSS remains free to apply italic or numeric variants where content requires them.
:root {
--weight-body: 400;
--weight-control: 500;
--weight-heading: 700;
}
body { font-weight: var(--weight-body); }
button { font-weight: var(--weight-control); }
h1, h2 { font-weight: var(--weight-heading); }
Do not create a token for every possible numeric value. Define roles that are repeated and expected to change together, verify that each loaded family supports them, and keep specialized one-off typography close to the content it serves.
Performance Considerations
Static web fonts commonly use separate resources for regular, bold, italic, and bold italic faces. Loading every possible weight and style increases transfer and processing even when the page uses only a few. Audit semantic roles and request only the faces needed by real content.
Variable fonts can consolidate ranges, but one variable resource is not automatically smaller than two static files. Measure actual formats, subsets, cache behavior, and page usage. A strong fallback stack keeps content readable while resources load or fail.
Accessibility Considerations
Do not rely on bold, italic, small caps, or numeric form as the only signal for an error, selected state, live change, or required field. Combine typographic treatment with clear text, semantic markup, programmatic state, and icons where appropriate.
Avoid very light body text and extended italic paragraphs. Test zoom, larger default fonts, bold text preferences, high contrast, narrow screens, and fallback fonts. Small caps and all caps often benefit from short content and deliberate letter spacing, but spacing should not become so wide that words fragment.
Debugging Rendered Typography
Use DevTools to inspect the winning declaration, computed weight and style, inherited variant values, loaded font resources, and actual rendered font. A computed weight of 600 does not prove that a genuine 600 face was used. Inspect whether the browser selected a nearby face or synthesized one.
Test regular, bold, italic, combined bold italic, small caps, and numeric features with representative characters. Disable web fonts to evaluate fallbacks, and verify required languages because face coverage can differ by style or weight.
Property Comparison
| Property | Primary control | Example | Dependency |
|---|---|---|---|
font-weight | Darkness or thickness | 700 | Available weight face or range |
font-style | Upright, italic, or slant | italic | Available style face or synthesis |
font-variant-caps | Alternate capital forms | small-caps | Font feature or synthesis |
font-variant-numeric | Alternate numeral forms | tabular-nums | Font feature support |
font-variant-ligatures | Ligature behavior | common-ligatures | Available ligature glyphs |
Common Interview Questions
What does font-weight control? It requests the relative darkness or stroke thickness of text and participates in matching an available font face.
What are normal and bold? Normal is equivalent to 400, while bold is equivalent to 700.
Can font-weight use values other than 100-step numbers? Yes. CSS accepts numbers from 1 to 1000, and variable fonts can provide continuous ranges.
What is the difference between italic and oblique? Italic commonly uses redesigned letterforms, while oblique commonly uses slanted forms and can accept an angle.
What does small-caps do? It requests capital-shaped forms for lowercase-origin text, preferably using designed small-cap glyphs.
Is small caps the same as uppercase? No. Uppercase uses full-size capital characters, while small caps create a typographic size hierarchy.
Why use tabular-nums? Equal-width numerals align columns and stabilize changing counters.
Do these properties inherit? Yes, font weight, style, and variant behavior generally inherit to descendants.
Practical Review Checklist
- Choose a small weight scale that creates visible hierarchy.
- Use readable regular or medium weights for essential body text.
- Load or define every important static weight and style actually used.
- Use intermediate weights only when a variable font supports them.
- Distinguish designed italic and oblique faces from synthesis.
- Use semantic strong and em markup when meaning matters.
- Verify real small-cap glyph support for editorial typography.
- Use tabular numerals for aligned tables, counters, and financial data.
- Keep specialized variants scoped to content that benefits from them.
- Avoid relying on typographic appearance as the only state indicator.
- Test inheritance, fallback families, scripts, and combined styles.
- Inspect actual rendered faces and synthesis in browser DevTools.
Key Takeaway
font-weight, font-style, and font-variant describe separate dimensions of typography: thickness, upright or slanted form, and alternate glyph forms. Their declarations are requests that the browser resolves against available faces and font features, sometimes using nearby matches or synthesized approximations.
Use weight for clear hierarchy, italic or oblique for intentional editorial treatment, and variant properties for capabilities such as small caps, tabular numbers, and ligatures. Preserve semantic HTML, load only the faces the design needs, and test actual rendered output under fallback and accessibility conditions. Precise typography comes from aligning CSS, font capabilities, and content meaning rather than stacking visual effects.