CSS Descriptor

A comprehensive guide to CSS descriptors within @font-face rules, covering required and optional descriptors, syntax, code examples, and performance best practices for modern web typography.

What Are CSS Descriptors?

CSS descriptors are a specialized type of CSS syntax element used within at-rules to define specific characteristics and behaviors of the rule they belong to. Unlike CSS properties that apply to elements on a page, descriptors exist only within the context of their parent at-rule, providing configuration and metadata that the browser uses to interpret and apply the rule's behavior.

Descriptors serve as configuration parameters for CSS at-rules, similar to how attributes configure HTML elements or how parameters configure functions in programming languages. When you define a @font-face rule, you use descriptors to specify everything about how the custom font should be loaded, displayed, and used throughout your stylesheet.

The distinction between descriptors and properties is fundamental to understanding CSS at-rules. Regular CSS properties like color or font-size cascade through elements and can be applied to any element in your HTML. CSS descriptors, by contrast, are only meaningful within their specific at-rule context and don't cascade or inherit in the traditional sense. Each at-rule has its own set of valid descriptors, and attempting to use a descriptor outside its intended context results in the declaration being ignored by the browser.

As explained in the MDN Web Docs at-rules guide, understanding this distinction is essential for writing effective CSS that leverages the full power of modern at-rules like @font-face, @counter-style, and @property.

At-Rules Using Descriptors

Several CSS at-rules utilize descriptors to configure their behavior:

  • @font-face -- The most common use case, defining custom font loading and rendering
  • @counter-style -- Defines custom list item markers and numbering systems
  • @property -- Registers typed custom properties with default values and inheritance behavior
  • @page -- Specifies page characteristics for paged media like printed documents

Each of these at-rules has its own specific set of descriptors that control how the rule functions. The @font-face at-rule, which we'll explore in depth, offers the most comprehensive set of descriptors for modern web typography. Understanding how descriptors work across these at-rules gives you a more complete picture of CSS's configuration capabilities.

Whether you're implementing custom fonts for a web development project or building sophisticated styling systems, mastering descriptors is essential for leveraging the full potential of modern CSS.

The @font-face At-Rule

The @font-face at-rule is the primary context where CSS descriptors are used, representing one of the most important innovations in modern web typography. Before @font-face was widely supported, web designers were limited to web-safe fonts that could be assumed to exist on users' computers. The list of these safe fonts was short and uninspiring: Arial, Times New Roman, Verdana, and a handful of others that designers relied on to ensure consistent rendering across different systems.

The @font-face rule changed this paradigm by allowing designers to specify custom fonts hosted on their servers or reference locally-installed fonts. When you include a @font-face rule in your CSS, you're telling the browser about a font resource and providing specific instructions through descriptors about how that resource should be handled. Each descriptor provides different information: where to find the font file, what name to use when referencing it, how it should display while loading, and what variations it supports.

According to MDN Web Docs, the @font-face at-rule has evolved significantly since its introduction, with modern implementations supporting variable fonts, color fonts, and sophisticated loading strategies that balance performance with visual quality.

Required Descriptors

Every @font-face rule must include at least two descriptors to be valid and functional. The font-family descriptor provides a name that will be used to reference this font throughout the stylesheet, functioning as an identifier rather than specifying an actual font family. The src descriptor specifies where the font data comes from, either as a URL pointing to a remote font file or as a reference to a locally-installed font using the local() function.

Without both of these required descriptors, the @font-face rule is incomplete and won't function as expected. The browser needs to know what to call the font and where to find its data. All other descriptors are optional and provide additional configuration for how the font should be rendered and what capabilities it offers.

Basic @font-face with required descriptors
1@font-face {2 font-family: "CustomFont";3 src: url("fonts/custom.woff2") format("woff2");4}

Font Source Descriptor (src)

The src descriptor is the most complex and powerful in @font-face, supporting multiple ways to specify font sources with optional format hints and technology indicators. The descriptor accepts a comma-separated list of sources, allowing you to specify multiple fallbacks and indicate your preference order.

The url() function specifies external font files, which can be absolute URLs pointing to any server or relative URLs resolved against the stylesheet's location. The local() function references fonts already installed on the user's device, allowing you to use system fonts without downloading. The format() hint provides the browser with font file format information, enabling it to skip downloading unsupported formats without attempting to parse the file. The tech() hint indicates specific font technologies such as color fonts (COLRv1) or variable font axes.

As documented by MDN Web Docs, the src descriptor's syntax supports sophisticated fallbacks that ensure fonts load efficiently across different browsers and device capabilities.

src descriptor with multiple sources
1@font-face {2 font-family: "Trickster";3 src:4 local("Trickster"),5 url("trickster-COLRv1.otf") format("opentype") tech(color-COLRv1),6 url("trickster-outline.otf") format("opentype"),7 url("trickster-outline.woff") format("woff");8}

Font Family Descriptor (font-family)

The font-family descriptor in @font-face serves as a label or identifier for the font rather than inheriting from the document's font stack. When you specify font-family: "Open Sans" in a @font-face rule, you're creating a font face available under that name for use in font-family properties elsewhere in your stylesheet.

This naming system allows you to use custom fonts with the same syntax as system fonts. The name you choose can include spaces and special characters, though wrapping in quotes is recommended for names containing spaces or unusual characters. The name you specify becomes the reference point that other CSS rules use to apply this particular font face.

Understanding this distinction is crucial: the @font-face font-family descriptor creates a local binding that makes the custom font available, while the standard CSS font-family property used on elements references that binding. You can define multiple @font-face rules with different names, and reference them selectively throughout your stylesheet.

Font Characteristic Descriptors

Beyond the required descriptors, @font-face supports optional descriptors that define the characteristics of the font face and how it should be applied. These provide fine-grained control over font weight, style, and stretch, enabling sophisticated typography systems with minimal CSS.

Font Weight Descriptor (font-weight)

The font-weight descriptor specifies the weight of the font face being defined, accepting either a single value or a range of values. For static fonts that come in specific weights, use values like 400 (regular) or 700 (bold). For variable fonts that support continuous weight variation, specify a range like 100 900 to indicate all weights between these values are available in a single font file.

When defining multiple static font weights, you need separate @font-face rules for each weight, each with its own font-family (usually matching) and font-weight descriptor. Variable fonts, by contrast, can serve multiple weights from a single file, reducing HTTP requests and simplifying font management. The CSS-Tricks guide to @font-face emphasizes that variable fonts represent a significant advancement in web typography efficiency.

font-weight descriptor examples
1/* Static font weights */2@font-face {3 font-family: "MyFont";4 src: url("myfont.woff2") format("woff2");5 font-weight: 400;6}7 8@font-face {9 font-family: "MyFont";10 src: url("myfont-bold.woff2") format("woff2");11 font-weight: 700;12}13 14/* Variable font with weight range */15@font-face {16 font-family: "VariableFont";17 src: url("variable.woff2") format("woff2-variations");18 font-weight: 100 900;19}

Font Style Descriptor (font-style)

The font-style descriptor specifies whether the font face represents normal text, italic text, or oblique (slanted) text. It accepts normal, italic, or oblique with optional angle values for variable fonts. Oblique angles range from -90deg to 90deg, with positive values slanting in one direction and negative values in the opposite.

For static italic fonts, you typically define a separate @font-face rule with font-style: italic. Variable fonts can support a range of oblique styles, allowing continuous adjustment from upright to slanted. This flexibility is particularly valuable for design systems that require fine-tuned typographic control without managing multiple font files.

font-style descriptor examples
1@font-face {2 font-family: "SerifFont";3 src: url("serif-italic.woff2") format("woff2");4 font-style: italic;5}6 7@font-face {8 font-family: "VariableSans";9 src: url("variable-sans.woff2") format("woff2-variations");10 font-style: oblique -10deg 0deg;11}

Font Stretch Descriptor (font-stretch)

The font-stretch descriptor specifies the width of the font face, enabling support for condensed, normal, and expanded font variants. Accepts keywords like condensed, expanded or percentage values from 50% to 200%. Variable fonts can specify a range of stretch values, allowing continuous adjustment between narrow and wide variants.

This descriptor is essential for fonts that come in multiple widths. By defining separate @font-face rules with different font-stretch values, you create a complete font family that responds to the font-stretch property on elements. Variable fonts make this even more powerful, enabling smooth transitions between widths without loading multiple files.

font-stretch descriptor examples
1@font-face {2 font-family: "WideFont";3 src: url("wide.woff2") format("woff2");4 font-stretch: expanded;5}6 7@font-face {8 font-family: "VariableWidth";9 src: url("variable-width.woff2") format("woff2-variations");10 font-stretch: 50% 200%;11}

Display and Rendering Descriptors

Modern web typography requires careful consideration of how fonts load and render. The font-display descriptor controls font loading behavior for better user experience, addressing the classic problem of invisible text (FOIT) during font loading.

Font Display Descriptor (font-display)

The font-display descriptor determines how a font face is displayed during loading, directly impacting perceived performance and user experience:

  • auto: Browser default behavior, typically similar to block
  • block: Hides text until custom font loads completely (causes FOIT - Flash of Invisible Text)
  • swap: Shows fallback font immediately, swaps when custom font loads (FOUT - Flash of Unstyled Text)
  • fallback: Short swap period (typically 100ms), then uses fallback
  • optional: Uses custom font only if already cached, otherwise permanent fallback

The swap value is recommended for body text where immediate readability is important. According to CSS-Tricks, the swap strategy ensures text is always visible, improving Core Web Vitals metrics like Cumulative Layout Shift (CLS) when properly configured with fallback fonts.

Optimizing font loading through proper descriptor usage is a key aspect of technical SEO, as Core Web Vitals performance directly impacts search rankings.

font-display: swap for visible text
1@font-face {2 font-family: "PerformanceFont";3 src: url("font.woff2") format("woff2");4 font-display: swap;5}

Advanced Descriptors

Beyond commonly used descriptors, @font-face provides advanced options for fine-tuning font rendering and supporting specialized features like Unicode subsets and OpenType capabilities.

Unicode Range Descriptor (unicode-range)

The unicode-range descriptor specifies Unicode code points for which the font face may be used. This enables subsetting strategies that significantly reduce file sizes for specific languages or use cases. The descriptor is particularly valuable for non-Latin scripts with large character sets, where downloading an entire font file would be wasteful if you only need specific characters.

By defining separate @font-face rules with different unicode-range values for different scripts, browsers automatically select the appropriate font file based on the actual characters being rendered. This approach powers modern multilingual websites that balance typographic quality with performance.

unicode-range for language subsets
1@font-face {2 font-family: "GreekFont";3 src: url("greek.woff2") format("woff2");4 unicode-range: U+0370-03FF;5}6 7@font-face {8 font-family: "EmojiFont";9 src: url("emoji.woff2") format("woff2");10 unicode-range: U+1F600-1F64F;11}

Font Feature Settings Descriptor (font-feature-settings)

The font-feature-settings descriptor allows control over advanced OpenType features such as ligatures, small caps, stylistic sets, and contextual alternates. Features are accessed through four-letter OpenType tags with numeric values (1 for on, 0 for off).

Common OpenType features include:

  • liga -- Standard ligatures (combining characters like fi, fl)
  • dlig -- Discretionary ligatures
  • smcp -- Small caps
  • calt -- Contextual alternates
  • tnum -- Tabular figures

This descriptor enables sophisticated typographic effects without loading different font files, making it ideal for enhancing readability and visual interest in your designs.

font-feature-settings for OpenType control
1@font-face {2 font-family: "FeatureRich";3 src: url("feature-font.woff2") format("woff2");4 font-feature-settings: "liga" 1, "smcp" 1, "calt" 0;5}

Font Variation Settings Descriptor (font-variation-settings)

For variable fonts, this descriptor provides low-level control over font axis values like weight, width, slant, and optical size. Uses four-letter axis tags with numeric values for precise typographic adjustments. While font-weight, font-style, and font-stretch provide higher-level control, font-variation-settings offers direct access to any registered or custom variation axis.

Common axis tags include:

  • wght -- Weight (equivalent to font-weight)
  • wdth -- Width (equivalent to font-stretch)
  • slnt -- Slant
  • opsz -- Optical size
  • GRAD -- Grade

This descriptor is essential for advanced variable font implementations that require fine-grained control beyond the standard properties.

font-variation-settings for variable fonts
1@font-face {2 font-family: "VariableType";3 src: url("variable.woff2") format("woff2-variations");4 font-variation-settings: "wght" 500, "wdth" 80, "opsz" 12;5}

Font Metrics Descriptors

CSS provides descriptors for adjusting font metrics to ensure consistent line heights and alignment when using custom fonts. These are particularly important when transitioning between system fonts and custom fonts with different typographic characteristics.

Ascent and Descent Override

The ascent-override and descent-override descriptors define how the font calculates its line box height. These accept percentage values relative to the font's em size. These metrics determine how far the font extends above and below the baseline, directly affecting line height calculations and vertical rhythm.

When using custom fonts with unusual metric characteristics, these overrides ensure consistent text rendering. For example, if your custom font has a larger ascent than typical system fonts, setting ascent-override: 80% can align it better with your fallback font's baseline positioning.

Customizing font metrics
1@font-face {2 font-family: "CustomFont";3 src: url("custom.woff2") format("woff2");4 ascent-override: 80%;5 descent-override: 20%;6}

Line Gap Override (line-gap-override)

The line-gap-override descriptor specifies the line gap metric for the font, affecting spacing between lines of text. Accepts percentage values for fine-tuning line spacing. This metric is added to the line height calculation, providing additional breathing room between text lines when needed.

While often overlooked, line gap can significantly impact readability, especially for body text or multilingual content where different scripts may require different default spacing.

Adjusting line gap
1@font-face {2 font-family: "SpacedFont";3 src: url("spaced.woff2") format("woff2");4 line-gap-override: 5%;5}

Size Adjust Descriptor (size-adjust)

The size-adjust descriptor defines a multiplier for glyph outlines and metrics, making it easier to harmonize different fonts at the same font size. This is particularly useful for creating seamless fallbacks when custom fonts are loading or when mixing fonts with different apparent sizes.

By adjusting the size of the custom font relative to its metrics, you can ensure that switching between fallback and custom fonts causes minimal layout shift. A value like 90% makes the custom font render slightly smaller, which can compensate for fonts that appear larger at the same point size.

Implementing proper font metrics through these descriptors is a hallmark of professional web development that prioritizes both aesthetics and performance.

Using size-adjust for seamless fallbacks
1@font-face {2 font-family: "SubstituteFont";3 src: url("substitute.woff2") format("woff2");4 size-adjust: 90%;5}

Font Format Reference

Understanding font formats is essential for effective @font-face rules. Different formats have different browser support, file sizes, and capabilities. The format() hint in your src descriptor tells browsers which format to expect, enabling format skipping to avoid wasted downloads.

Font format keywords, browser support, and recommendations
Format KeywordFont FormatBrowser SupportNotes
woff2WOFF 2.0All modern browsersBest compression, preferred format
woffWOFF 1.0All modern browsersGood fallback for older browsers
opentypeOpenTypeAll modern browsersSupports advanced OpenType features
truetypeTrueTypeAll modern browsersLegacy format, broader compatibility
embedded-opentypeEmbedded OpenTypeIE onlyLegacy format, avoid
collectionOpenType CollectionModern browsersFont collections in one file
svgSVG FontNone (deprecated)Removed from browsers, never use

WOFF2 is the recommended format for most use cases, offering excellent compression, broad browser support, and native variable font support. Include WOFF as a fallback for older browsers that don't support WOFF2. SVG fonts are deprecated and should be avoided entirely.

As noted in the MDN Web Docs src descriptor documentation, always include format hints to enable format skipping--the browser can immediately reject fonts it can't support without downloading them, improving performance.

Best Practices

Writing effective @font-face rules requires understanding syntax, performance implications, and browser compatibility. Following these best practices ensures optimal typography performance and user experience.

Fallback Strategies

Always provide multiple font sources in your src descriptor, listing them in order of preference with format hints. Include format hints to allow browsers to skip unsupported formats without downloading. Consider including system font fallbacks using local() references for fonts that may already be installed on users' devices.

Performance Optimization

  • Use WOFF2 format for smallest file sizes and best compression
  • Subset fonts with unicode-range to include only characters you need
  • Prefer variable fonts to reduce font file count and enable smooth weight transitions
  • Preload critical fonts with <link rel="preload"> in your HTML head
  • Use font-display: swap for visible text during font loading
  • Use size-adjust to create seamless fallbacks with minimal layout shift

Security Considerations

The local() function can potentially be used for font fingerprinting in some scenarios. Modern browsers have added protections against this. Ensure proper CORS headers for external fonts served from CDNs and consider Subresource Integrity (SRI) for production deployments to verify font file integrity.

Implementing these font loading strategies is part of comprehensive web development services that deliver fast, accessible, and user-friendly websites.

Optimized @font-face with fallbacks
1@font-face {2 font-family: "OptimizedFont";3 src:4 url("font-woff2.woff2") format("woff2"),5 url("font-woff.woff") format("woff"),6 url("font-otf.otf") format("opentype");7 font-display: swap;8}

Frequently Asked Questions

What is the difference between CSS descriptors and properties?

CSS descriptors configure at-rules like @font-face, while CSS properties style elements. Descriptors only exist within their specific at-rule context and don't cascade like properties. For example, font-weight in @font-face specifies which font variant is defined, while font-weight on an element controls text boldness.

What is the best font-display value?

font-display: swap is recommended for most cases. It shows fallback text immediately and swaps to the custom font when loaded, ensuring text is always visible and improving perceived performance. Use block only when visual consistency is critical and loading delays are acceptable. Avoid optional unless you never want the custom font to load.

Should I use variable fonts?

Yes, variable fonts are recommended when available. They allow continuous variation of weight, width, and slant in a single file, reducing HTTP requests and total file size compared to multiple static font files. Use range syntax like font-weight: 100 900 for variable font support. Variable fonts also improve performance by enabling more efficient subsetting.

What font formats should I use in 2025?

Use WOFF2 as the primary format--best compression, modern support, variable font capability. Include WOFF as a fallback for older browsers. Avoid EOT and SVG formats entirely. Always include format() hints to enable format skipping and prevent unnecessary downloads.

Master Modern Web Typography

CSS descriptors unlock the full potential of custom web typography through @font-face. By mastering both required and optional descriptors, you can create typography that is both beautiful and performant, directly impacting Core Web Vitals metrics like CLS and LCP. Our web development team specializes in building performant websites with optimized typography systems.