CSS @ornaments At-Rule

The @ornaments at-rule defines names for ornamental glyph alternatives in an OpenType font. It is used inside @font-feature-values and allows the font-variant-alternates property to select decorative symbols using readable names instead of numeric font feature indexes.

@ornaments Syntax

@font-feature-values "Font Name" {
  @ornaments {
    ornament-name: index;
  }
}

The @ornaments at-rule is a nested at-rule that must appear inside @font-feature-values. It associates a custom ornament name with a numeric index supported by the specified font.

The syntax contains three important parts:

  • Font family: The font associated with the ornament definitions.
  • Ornament name: A custom identifier used to reference an ornamental glyph.
  • Index: A positive integer identifying the ornament alternative within the font.
@font-feature-values "Decorative Font" {
  @ornaments {
    floral: 1;
    geometric: 2;
  }
}

This example defines two names, floral and geometric, associated with ornament indexes 1 and 2.

Each ornament definition accepts exactly one positive integer. A declaration containing multiple indexes is invalid.

How @ornaments Works

Some OpenType fonts contain ornamental glyphs, such as decorative symbols, flourishes, and typographic ornaments. These alternatives are stored in the font and identified by numeric indexes.

The @ornaments at-rule assigns readable names to these indexes so they can be referenced using the ornaments() function in font-variant-alternates.

@font-feature-values "Decorative Font" {
  @ornaments {
    fancy: 1;
  }
}
.decorative-symbol {
  font-family: "Decorative Font", serif;
  font-variant-alternates: ornaments(fancy);
}

When the font supports the selected ornament, the browser uses the corresponding alternate glyph.

The @ornaments rule does not create decorative symbols. It only provides names for ornament features already available in the font.

Ornamental glyphs use the OpenType ornm feature, which allows a font to substitute decorative glyphs for supported characters.

Defining Ornament Names

Multiple ornament names can be defined within the same @ornaments block.

@font-feature-values "Decorative Font" {
  @ornaments {
    simple: 1;
    elaborate: 2;
    classic: 3;
  }
}

Each name identifies a separate ornament index. The actual appearance depends on how the font designer assigned its alternate glyphs.

Using Different Font Families

Different fonts may use different indexes for similar ornaments. The same readable name can be mapped to a different index for each font family.

@font-feature-values "Font One" {
  @ornaments {
    decorative: 1;
  }
}
@font-feature-values "Font Two" {
  @ornaments {
    decorative: 3;
  }
}

Both fonts define the name decorative, but the selected index differs.

This allows the same ornaments(decorative) value to be used with different fonts without changing the property declaration.

Valid and Invalid Definitions

@font-feature-values "Decorative Font" {
  @ornaments {
    valid-ornament: 2;
    invalid-ornament: 2 3;
  }
}

The first declaration is valid because it contains one index. The second is invalid because @ornaments does not accept multiple indexes for a single name.

This differs from some other font feature value rules, such as @styleset, which can accept multiple indexes.

Applying Ornament Styles

After defining an ornament name, use the font-variant-alternates property with the ornaments() function to activate it.

@font-feature-values "Decorative Font" {
  @ornaments {
    flourish: 1;
    divider: 2;
  }
}
.flourish {
  font-family: "Decorative Font", serif;
  font-variant-alternates: ornaments(flourish);
}
.divider {
  font-family: "Decorative Font", serif;
  font-variant-alternates: ornaments(divider);
}

The .flourish and .divider selectors request different ornamental alternatives from the same font.

Combining Font Alternatives

The font-variant-alternates property can enable an ornament together with other font features.

@font-feature-values "Decorative Font" {
  @ornaments {
    fancy: 1;
  }
  @swash {
    flowing: 2;
  }
}
.decorative-text {
  font-family: "Decorative Font", serif;
  font-variant-alternates: ornaments(fancy) swash(flowing);
}

This example requests an ornamental alternative and a swash alternative. Each feature applies only when the font provides the corresponding glyph substitution.

For ordinary text, ornamental substitutions should be used selectively to preserve readability and meaning.

Font Requirements

The @ornaments at-rule depends on the capabilities of the selected OpenType font.

For an ornament to appear, the following conditions must be met:

  • The selected font must be available to the browser.
  • The font must contain the OpenType ornm feature.
  • The specified index must correspond to an ornament supported by that font.
  • The text must contain a character for which the font provides the ornamental substitution.

If these conditions are not met, the browser generally displays the normal glyph instead.

Using @font-face

A custom font can be loaded using @font-face before its ornament features are applied.

@font-face {
  font-family: "Decorative Font";
  src: url("decorative-font.woff2") format("woff2");
}
@font-feature-values "Decorative Font" {
  @ornaments {
    flourish: 1;
  }
}
.ornament {
  font-family: "Decorative Font", serif;
  font-variant-alternates: ornaments(flourish);
}

The font file must contain the appropriate ornament feature. Loading an ordinary font without ornamental glyphs will not produce decorative substitutions.

Font designers are encouraged to provide ornaments as alternatives to suitable characters, such as the bullet character, rather than replacing unrelated letters or numbers.

Ornaments and Other Font Features

The @ornaments at-rule is one of several feature value rules available inside @font-feature-values.

At-Rule Purpose Property Function
@ornaments Defines ornamental glyph alternatives. ornaments()
@swash Defines decorative swash alternatives. swash()
@stylistic Defines individual stylistic alternatives. stylistic()
@styleset Defines groups of stylistic alternatives. styleset()
@annotation Defines annotation glyph alternatives. annotation()
@character-variant Defines character-specific variants. character-variant()

Each rule provides names for a different type of OpenType feature. The appropriate rule depends on the font's available glyph alternatives and the intended typographic effect.

@ornaments Example

The following example defines a named ornament and applies it to a decorative separator.

HTML

<p class="ornament">&#8226;</p>

CSS

@font-feature-values "Decorative Font" {
  @ornaments {
    flourish: 1;
  }
}
.ornament {
  font-family: "Decorative Font", serif;
  font-size: 36px;
  text-align: center;
  font-variant-alternates: ornaments(flourish);
}

The HTML contains a bullet character. If the selected font supports an ornamental alternative for that character at index 1, the browser displays the decorative glyph instead of the standard bullet.

The example uses a placeholder font family name. To see an ornamental substitution, replace it with an available OpenType font that provides the required ornm feature and index.

Browser Support

The @ornaments feature is Baseline Widely available as part of @font-feature-values and is supported in modern browsers. The visual result still depends on the selected font's OpenType ornament features. See Can I Use? for compatibility details.

Specifications

The @ornaments at-rule is defined in CSS Fonts Module Level 4 as a feature value block within @font-feature-values. It maps author-defined ornament names to numeric OpenType feature indexes used by the ornaments() function of font-variant-alternates.

CSS Fonts Module Level 4