at-rules Flashcards

aka @rules

1
Q

What is an at-rule?

A

At-rules are CSS statements that instruct CSS how to behave. They begin with an at sign, @ (U+0040 COMMERCIAL AT), followed by an identifier and includes everything up to the next semicolon, ; (U+003B SEMICOLON), or the next CSS block, whichever comes first.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Syntax of at-rules

A

At-rules begin with an at sign, @ (U+0040 COMMERCIAL AT), followed by an identifier and includes everything up to the next semicolon, ; (U+003B SEMICOLON), or the next CSS block, whichever comes first.

Regular

/* General structure */
@identifier (RULE);

/* Example: tells browser to use UTF-8 character set */
@charset "utf-8";

There are several regular at-rules, designated by their identifiers, each with a different syntax:

  • @charset — Defines the character set used by the style sheet.
  • @import — Tells the CSS engine to include an external style sheet.
  • @namespace — Tells the CSS engine that all its content must be considered prefixed with an XML namespace.

Nested

@identifier (RULE) {
}

A subset of nested statements, which can be used as a statement of a style sheet as well as inside of conditional group rules.

  • @media — A conditional group rule that will apply its content if the device meets the criteria of the condition defined using a media query.
  • @scope - A conditional group rule that will apply its content if the device meets the criteria of the given condition.
  • @starting-style - A conditional group rule that will apply starting transition if the browser meets the criteria of the given condition.
  • @supports — A conditional group rule that will apply its content if the browser meets the criteria of the given condition.
  • @page — Describes the aspect of layout changes that will be applied when printing the document.
  • @font-face — Describes the aspect of an external font to be downloaded.
  • @keyframes — Describes the aspect of intermediate steps in a CSS animation sequence.
  • @counter-style — Defines specific counter styles that are not part of the predefined set of styles.
  • @font-feature-values (plus @swash, @ornaments, @annotation, @stylistic, @styleset and @character-variant) — Define common names in font-variant-alternates for feature activated differently in OpenType.
  • @property — Describes the aspect of custom properties and variables.
  • @layer – Declares a cascade layer and defines the order of precedence in case of multiple cascade layers.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are conditional group rules?

A

Each at-rule has a different syntax. Nevertheless, several of them can be grouped into a special category named conditional group rules. These statements share a common syntax and each of them can include nested statements—either rulesets or nested at-rules. Furthermore, they all convey a common semantic meaning—they all link some type of condition, which at any time evaluates to either true or false. If the condition evaluates to true, then all of the statements within the group will be applied.

Conditional group rules are:

  • @media — A conditional group rule that will apply its content if the device meets the criteria of the condition defined using a media query.
  • @scope - A conditional group rule that will apply its content if the device meets the criteria of the given condition.
  • @supports — A conditional group rule that will apply its content if the browser meets the criteria of the given condition.

Since each conditional group may also contain nested statements, there may be an unspecified amount of nesting.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

@import CSS at-rule

A

The @import CSS at-rule is used to import style rules from other valid stylesheets. An @import rule must be defined at the top of the stylesheet, before any other at-rule (except @charset and @layer) and style declarations, or it will be ignored.

The @import rule is not a nested statement. Therefore, it cannot be used inside conditional group at-rules.

The @import rule can also be used to create a cascade layer by importing rules from a linked resource. Rules can also be imported into an existing cascade layer. The layer keyword or the layer() function is used with @import for this purpose. Declarations in style rules from imported stylesheets interact with the cascade as if they were written literally into the stylesheet at the point of the import.

Syntax

@import url;
@import url layer;
@import url layer(layer-name);
@import url layer(layer-name) supports(supports-condition);
@import url layer(layer-name) supports(supports-condition) list-of-media-queries;
@import url layer(layer-name) list-of-media-queries;
@import url supports(supports-condition);
@import url supports(supports-condition) list-of-media-queries;
@import url list-of-media-queries;

where:

  • url - Is a <string>, a <url> or a url() function representing the location of the resource to import. The URL may be absolute or relative.
  • list-of-media-queries - Is a comma-separated list of media queries, which specify the media-dependent conditions for applying the CSS rules defined in the linked URL. If the browser does not support any of these queries, it does not load the linked resource.
  • layer-name - Is the name of a cascade layer into which the contents of the linked resource are imported.
  • supports-condition - Indicates the feature(s) that the browser must support in order for the stylesheet to be imported. If the browser does not conform to the conditions specified in the supports-condition, it may not fetch the linked stylesheet, and even if downloaded through some other path, will not load it. The syntax of supports() is almost identical to that described in @supports, and that topic can be used as a more complete reference.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What is the problem with this styles?

* {
  margin: 0;
  padding: 0;
}
/* more styles */
@import url("my-imported-styles.css");
A

As the @import at-rule is declared after the styles, it is invalid and hence ignored.

@import url("my-imported-styles.css");
* {
  margin: 0;
  padding: 0;
}
/* more styles */

“@import” (MDN Web Docs). Retrieved March 27, 2024.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Explain the following CSS rules

@import url("fineprint.css") print;
@import url("bluish.css") print, screen;
@import "common.css" screen;
@import url("landscape.css") screen and (orientation: landscape)
A

The @import rules in the above examples show media-dependent conditions that will need to be true before the linked CSS rules are applied. So for instance, the last @import rule will load the landscape.css stylesheet only on a screen device in landscape orientation.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Explain the following CSS rules

@import url("gridy.css") supports(display: grid) screen and (max-width: 400px);
@import url("flexy.css") supports(not (display: grid) and (display: flex)) screen
  and (max-width: 400px);
A

The @import rules above illustrate how you might import a layout that uses a grid if display: grid is supported, and otherwise imports CSS that uses display: flex. While you can only have one supports() statement, you can combine any number of feature checks with not, and, and or, as long as you wrap each condition to be tested in parentheses. You can also use parentheses to indicate precedence. Note that if you just have a single declaration then you don’t need to wrap it in additional parenthese: this is shown in the first example above.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Explain the following CSS rule

@import url("whatever.css") supports((selector(h2 > p)) and
    (font-tech(color-COLRv1)));
A

The CSS rule above shows an @import that is conditional on both child combinators (selector()) and the font-tech() function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Explain the following CSS rules

@import url(headings.css) layer(default);
@import url(links.css) layer(default);

@layer default {
  audio[controls] {
    display: block;
  }
}
A

The CSS rules in headings.css and links.css stylesheets cascade within the same layer as the audio[controls] rule.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

@namespace CSS at-rule

A

@namespace is an at-rule that defines XML namespaces to be used in a CSS style sheet.

Syntax

/* Default namespace */
@namespace url(XML-namespace-URL);
@namespace "XML-namespace-URL";

/* Prefixed namespace */
@namespace prefix url(XML-namespace-URL);
@namespace prefix "XML-namespace-URL";

Description
The defined namespaces can be used to restrict the universal, type, and attribute selectors to only select elements within that namespace. The @namespace rule is generally only useful when dealing with documents containing multiple namespaces—such as HTML with inline SVG or MathML, or XML that mixes multiple vocabularies.

Any @namespace rules must follow all @charset and @import rules, and precede all other at-rules and style declarations in a style sheet.

@namespace can be used to define the default namespace for the style sheet. When a default namespace is defined, all universal and type selectors (but not attribute selectors, see note below) apply only to elements in that namespace.

The @namespace rule can also be used to define a namespace prefix. When a universal, type, or attribute selector is prefixed with a namespace prefix, then that selector only matches if the namespace and name of the element or attribute matches.

In HTML, known foreign elements will automatically be assigned namespaces. This means that HTML elements will act as though they are in the XHTML namespace, even if there is no xmlns attribute anywhere in the document, and the <svg> and <math> elements will be assigned their proper namespaces.

Note: In XML, unless a prefix is defined directly on an attribute (e.g., xlink:href), that attribute has no namespace. In other words, attributes do not inherit the namespace of the element they’re on. To match this behavior, the default namespace in CSS does not apply to attribute selectors.

Examples:

@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);

/* This matches all XHTML <a> elements, as XHTML is the default unprefixed namespace */
a {
}

/* This matches all SVG <a> elements */
svg|a {
}

/* This matches both XHTML and SVG <a> elements */
*|a {
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

@charset CSS rule

A

The @charset CSS rule specifies the character encoding used in the style sheet. Although the first character in @charset is the @ symbol, it is not an at-rule. The CSS syntax module deprecates this rule, defining it as an unrecognized legacy rule to be dropped when a stylesheet is grammar-checked, but it is fully supported in all browsers.

Syntax

@charset "UTF-8";
@charset "iso-8859-15";

Formal syntax

@charset "<charset>";

charset - A <string> denoting the character encoding to be used. It must be the name of a web-safe character encoding defined in the IANA-registry, and must be double-quoted, following exactly one space character (U+0020), and immediately terminated with a semicolon. If several names are associated with an encoding, only the one marked with preferred must be used.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

@scope CSS at-rule

A

The @scope CSS at-rule enables you to select elements in specific DOM subtrees, targeting elements precisely without writing overly-specific selectors that are hard to override, and without coupling your selectors too tightly to the DOM structure.

In JavaScript, @scope can be accessed via the CSS object model interface CSSScopeRule.

Syntax

@scope can be used in two ways:

  1. As a standalone block inside your CSS, in which case it includes a prelude section that includes scope root and optional scope limit selectors — these define the upper and lower bounds of the scope.
@scope (scope root) to (scope limit) {
  rulesets
}
  1. As inline styles included inside a <style> element in your HTML, in which case the prelude is omitted, and the enclosed ruleset is automatically scoped to the <style> element’s enclosing parent element.

HTML

<parent-element>
  <style>
    @scope {
      rulesets
    }
  </style>
</parent-element>

NOTE: It is important to understand that, while @scope allows you to isolate the application of selectors to specific DOM subtrees, it does not completely isolate the applied styles to within those subtrees. This is most noticeable with inheritance — properties that are inherited by children (for example color or font-family) will still be inherited, beyond any set scope limit.

NOTE 2: At the moment of this writing support for this at-rule is limite please check its browser compatibility table before use.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What does :scope pseudo-class refers to in the following CSS ruleset

@scope (.feature) {
  :scope {
    background: rebeccapurple;
    color: antiquewhite;
    font-family: sans-serif;
  }
}
A

In the context of a @scope block, the :scope pseudo-class represents the scope root — it provides an easy way to apply styles to the scope root itself, from inside the scope. In the example CSS provided :scope will refer to .feature elements.

In fact, :scope is implicitly prepended to all scoped style rules. If you want, you can explicitly prepend :scope or prepend the nesting selector (&) to get the same effect if you find these representations easier to understand.

The three rules in the following block are all equivalent in what they select:

@scope (.feature) {
  img { ... }

  :scope img { ... }

  & img { ... }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is the difference between :scope and & inside @scope at-rule?

A

:scope represents the matched scope root, whereas & represents the selector used to match the scope root. Because of this, it is possible to chain & multiple times. However, you can only use :scope once — you can’t match a scope root inside a scope root.

@scope (.feature) {
  /* Selects a .feature inside the matched root .feature */
  & & { ... }

  /* Doesn't work */
  :scope :scope { ... }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

How are @scope conflicts are resolved?

A

@scope adds a new criterion to the CSS cascade: scoping proximity. This states that when two scopes have conflicting styles, the style that has the smallest number of hops up the DOM tree hierarchy to the scope root is applied. Let’s look at an example to see what this means.

Take the following HTML snippet, where different-themed cards are nested inside one another:

HTML

<div class="light-theme">
  <p>Light theme text</p>
  <div class="dark-theme">
    <p>Dark theme text</p>
    <div class="light-theme">
      <p>Light theme text</p>
    </div>
  </div>
</div>

If you wrote the theme CSS like so, you’d run into trouble:

.light-theme {
  background: #ccc;
}

.dark-theme {
  background: #333;
}

.light-theme p {
  color: black;
}

.dark-theme p {
  color: white;
}

The innermost paragraph is supposed to be colored black because it is inside a light theme card. However, it’s targeted by both .light-theme p and .dark-theme p. Because the .dark-theme p rule appears later in the source order, it is applied, and the paragraph ends up being wrongly colored white.

To fix this, you can use @scope as follows:

CSS

@scope (.light-theme) {
  :scope {
    background: #ccc;
  }
  p {
    color: black;
  }
}

@scope (.dark-theme) {
  :scope {
    background: #333;
  }
  p {
    color: white;
  }
}

Now the innermost paragraph is correctly colored black. This is because it is only one DOM tree hierarchy level away from the .light-theme scope root, but two levels away from the .dark-theme scope root. Therefore, the light style wins.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

@media CSS at-rule

A

The @media CSS at-rule can be used to apply part of a style sheet based on the result of one or more media queries. With it, you specify a media query and a block of CSS to apply to the document if and only if the media query matches the device on which the content is being used.

Syntax

/* At the top level of your code */
@media screen and (min-width: 900px) {
  article {
    padding: 1rem 3rem;
  }
}

/* Nested within another conditional at-rule */
@supports (display: flex) {
  @media screen and (min-width: 900px) {
    article {
      display: flex;
    }
  }
}
17
Q

@supports CSS at-rule

A

The @supports CSS at-rule lets you specify CSS declarations that depend on a browser’s support for CSS features. Using this at-rule is commonly called a feature query. The rule must be placed at the top level of your code or nested inside any other conditional group at-rule.

Syntax
The @supports at-rule consists of a block of statements with a supports condition. The supports condition is a set of one or more name-value pairs (e.g., <property>: <value>).

@supports (<supports-condition>) {
  /* If the condition is true, use the CSS in this block. */
}

The conditions can be combined by conjunctions (and), disjunctions (or), and/or negations (not).

@supports (<supports-condition>) and (<supports-condition>) {
  /* If both conditions are true, use the CSS in this block. */
}

The precedence of operators can be defined with parentheses. Supports conditions can use either a <property>: <value> declaration syntax or a <function()> syntax.

18
Q

@supports declaration syntax

A

The declaration syntax checks if a browser supports the specified <property>: <value> declaration. The declaration must be surrounded by parentheses. The following example returns true and applies the CSS style if the browser supports the expression transform-origin: 5% 5%:

@supports (transform-origin: 5% 5%) {
}
19
Q

@supports function syntax

A

The function syntax checks if a browser supports values or expressions within the function. The functions supported in the function syntax are:

selector()
This function evaluates if a browser supports the specified selector syntax. The following example returns true and applies the CSS style if the browser supports the child combinator:

@supports selector(h2 > p) {
}

font-tech()
This function checks if a browser supports the specified font technology for layout and rendering. The following example returns true and applies the CSS style if the browser supports the COLRv1 font technology:

@supports font-tech(color-COLRv1) {
}

font-format()
This function checks if a browser supports the specified font format for layout and rendering. The following example returns true and applies the CSS style if the browser supports the opentype font format:

@supports font-format(opentype) {
}
20
Q

@supports not operator

A

The not operator precedes an expression resulting in the negation of the expression. The following returns true if the browser’s transform-origin property considers 10em 10em 10em to be invalid:

@supports not (transform-origin: 10em 10em 10em) {
}

As with any operator, the not operator can be applied to a declaration of any complexity. The following examples are both valid:

@supports not (not (transform-origin: 2px)) {
}
@supports (display: grid) and (not (display: inline-grid)) {
}
21
Q

@supports and operator

A

The and operator creates a new expression from the conjunction of two shorter expressions. It returns true only if both of the shorter expressions are also true. The following example returns true if and only if the two shorter expressions are simultaneously true:

@supports (display: table-cell) and (display: list-item) {
}

Multiple conjunctions can be juxtaposed without the need of more parentheses. The following are both equivalent:

@supports (display: table-cell) and (display: list-item) and (display: contents) {
}
@supports (display: table-cell) and
  ((display: list-item) and (display: contents)) {
}

Note: When using both and and or operators, the parentheses must be used to define the order in which they apply. Otherwise, the condition is invalid and the whole rule is ignored.

22
Q

@supports or operator

A

The or operator creates a new expression from the disjunction of two shorter expressions. It returns true if one or both of the shorter expressions is also true. The following example returns true if at least one of the two shorter expressions is true:

@supports (transform-style: preserve) or (-moz-transform-style: preserve) {
}

Multiple disjunctions can be juxtaposed without the need of more parentheses. The following are both equivalent:

@supports (transform-style: preserve) or (-moz-transform-style: preserve) or (-webkit-transform-style: preserve) {}

@supports (transform-style: preserve-3d) or ((-moz-transform-style: preserve-3d) or (-webkit-transform-style: preserve-3d))) {}

Note: When using both and and or operators, the parentheses must be used to define the order in which they apply. Otherwise, the condition is invalid and the whole rule is ignored.

“The or operator” (MDN Web Docs). Retrieved April 10, 2024.

23
Q

@layer CSS at-rule

A

The @layer CSS at-rule is used to declare a cascade layer and can also be used to define the order of precedence in case of multiple cascade layers.

Rules within a cascade layer cascade together, giving more control over the cascade to web developers. Any styles not in a layer are gathered together and placed into a single anonymous layer that comes after all the declared layers, named and anonymous. This means that any styles declared outside of a layer will override styles declared in a layer, regardless of specificity.

Syntax

@layer layer-name {rules}
@layer layer-name;
@layer layer-name, layer-name, layer-name;
@layer {rules}

where:

  • layer-name - Is the name of the cascade layer.
  • rules - Is the set of CSS rules in the cascade layer.
24
Q

List the 4 ways you can create a cascade @layer

A

1.- Create a named cascade layer with the CSS rules for that layer inside, like so:

@layer utilities {
  .padding-sm {
    padding: 0.5rem;
  }

  .padding-lg {
    padding: 0.8rem;
  }
}

2.- Create a named cascade layer without assigning any styles. This can be a single layer, as shown below:

@layer utilities;

Multiple layers can be defined at once:

@layer theme, layout, utilities;

This is useful because the initial order in which layers are declared indicates which layer has precedence. As with declarations, the last layer to be listed will win if declarations are found in multiple layers. Therefore, with the preceding example, if a competing rule was found in theme and utilities, the one in utilities would win and be applied.

A rule in utilities would be applied even if it has lower specificity than the rule in theme. This is because once the layer order has been established, specificity and order of appearance are ignored. This enables the creation of simpler CSS selectors because you do not have to ensure that a selector will have high enough specificity to override competing rules; all you need to ensure is that it appears in a later layer.

Note: Having declared your layer names, thus setting their order, you can add CSS rules to the layer by re-declaring the name. The styles are then appended to the layer and the layer order will not be changed.

3.- Create a cascade layer with no name. For example:

@layer {
  p {
    margin-block: 1rem;
  }
}

This creates an anonymous cascade layer. This layer functions in the same way as named layers; however, rules cannot be assigned to it later. The order of precedence for anonymous layers is the order in which layers are declared, named or not, and lower than the styles declared outside of a layer.

4.- Create a cascade layer is by using @import. In this case, the rules would be in the imported stylesheet. Remember that the @import at-rule must precede all other types of rules, except @charset and @layer rules.

@import "theme.css" layer(utilities);
25
Q

is it possible to nest @layers?

A

Layers may be nested. For example:

@layer framework {
  @layer layout {
  }
}

To append rules to the layout layer inside framework, join the two names with a ..

@layer framework.layout {
  p {
    margin-block: 1rem;
  }
}

“Nesting layers” (MDN Web Docs). Retrieved April 10, 2024.

26
Q

@page CSS at-rule

A

The @page at-rule is a CSS at-rule used to modify different aspects of printed pages. It targets and modifies the page’s dimensions, orientation, and margins. The @page at-rule can be used to target all pages in a print-out or a subset using its various pseudo-classes.

Syntax

/* Targets all the pages */
@page {
  size: 8.5in 9in;
  margin-top: 4in;
}

/* Targets all even-numbered pages */
@page :left {
  margin-top: 4in;
}

/* Targets all odd-numbered pages */
@page :right {
  size: 11in;
  margin-top: 4in;
}

/* Targets all selectors with `page: wide;` set */
@page wide {
  size: a4 landscape;
}

@page {
  /* margin box at top right showing page number */
  @top-right {
    content: "Page " counter(pageNumber);
  }
}

Page properties

The @page at-rule can contain only page descriptors and margin at-rules. The following descriptors have been implemented by at least one browser:

  • margin - Specifies the page margins. Individual margin properties margin-top, margin-right, margin-bottom, and margin-left can also be used.
  • page-orientation - Specifies the orientation of the page. This does not affect the layout of the page; the rotation is applied after the layout in the output medium.
  • size - Specifies the target size and orientation of the page box’s containing block. In the general case, where one page box is rendered onto one page sheet, it also indicates the size of the destination page sheet.

Margin at-rules

Warning: The margin at-rules have not been implemented by any user agent (updated: August 2023).

The margin at-rules are used inside of the @page at-rule. They each target a different section of the document printed page, styling the area of the printed page based on the property values set in the style block:

@page {
  @top-left {
    /* page-margin-properties */
  }
}
27
Q

@property CSS at-rule

A

The @property CSS at-rule is part of the CSS Houdini umbrella of APIs. It allows developers to explicitly define their CSS custom properties, allowing for property type checking and constraining, setting default values, and defining whether a custom property can inherit values or not.

The @property rule represents a custom property registration directly in a stylesheet without having to run any JS. Valid @property rules result in a registered custom property, as if registerProperty() had been called with equivalent parameters.

Syntax

@property --property-name {
  syntax: "<color>";
  inherits: false;
  initial-value: #c0ffee;
}

Descriptors

syntax

Describes the allowable syntax for the property. May be a <length>, <number>, <percentage>, <length-percentage>, <color>, <image>, <url>, <integer>, <angle>, <time>, <resolution>, <transform-function>, or <custom-ident>, or a list of data type and keyword values.

The + (space-separated) and # (comma-separated) multipliers indicate that a list of values is expected, for example <color># means a comma-separated list of <color> values is the expected syntax.

Vertical lines (|) - can create “or” conditions for the expected syntax, for example <length> | auto accepts a <length> or auto, and <color># | <integer># expects a comma-separated list of <color> values or a comma-separated list of <integer> values.

inherits

Controls whether the custom property registration specified by @property inherits by default.

initial-value

Sets the initial value for the property.

The @property rule must include both the syntax and inherits descriptors; if either are missing, the entire @property rule is invalid and ignored. The initial-value descriptor is also required, unless the syntax is the * universal syntax definition (e.g., initial-value: *). If the initial-value descriptor is required and omitted, the entire @property rule is invalid and ignored.

Unknown descriptors are invalid and ignored, but do not invalidate the @property rule.

Examples:

With CSS:

@property --item-size {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 40%;
}

With Js:

window.CSS.registerProperty({
  name: "--item-color",
  syntax: "<color>",
  inherits: false,
  initialValue: "aqua",
});

Usage example:

.container {
  display: flex;
  height: 200px;
  border: 1px dashed black;

  /* set custom property values on parent */
  --item-size: 20%;
  --item-color: orange;
}

/* use custom properties to set item size and background color */
.item {
  width: var(--item-size);
  height: var(--item-size);
  background-color: var(--item-color);
}

/* set custom property values on element itself */
.two {
  --item-size: initial;
  --item-color: inherit;
}

.three {
  /* invalid values */
  --item-size: 1000px;
  --item-color: xyz;
}
28
Q

@counter-style CSS at-rule

A

The @counter-style CSS at-rule lets you extend predefined list styles and define your own counter styles that are not part of the predefined set of styles. The @counter-style rule contains descriptors defining how the counter value is converted into a string representation.

@counter-style thumbs {
  system: cyclic;
  symbols: "\1F44D";
  suffix: " ";
}

ul {
  list-style: thumbs;
}

Syntax

The @counter-style at-rule is identified by a counter style name, and the style of the named counter can be fine-tuned using a <declaration-list> consisting of one or more descriptors and their values.

Counter style name

<counter-style-name> - Provides a name for your counter style. It is specified as a case-sensitive <custom-ident> without quotes. The value should not be equal to none. Like all custom identifiers, the value of your counter style can’t be a CSS-wide keyword. Avoid other enumerated CSS property values, including values of list and counter style properties. The name of your counter can’t be the case-insensitive list-style-type property values of decimal, disc, square, circle, disclosure-open, and disclosure-closed.

Descriptors

system
Specifies the algorithm to be used for converting the integer value of a counter to a string representation. If the value is cyclic, numeric, alphabetic, symbolic, or fixed, the symbols descriptor must also be specified. If the value is additive , the additive-symbols descriptor must also be specified.

symbols
Specifies the symbols that are to be used for the marker representations. Symbols can contain strings, images, or custom identifiers.

additive-symbols
Defines the additive tuples for additive systems. While the symbols specified in the symbols descriptor are used for constructing marker representation by most algorithms, additive counter systems, such as Roman numerals, consist of a series of weighted symbols. The descriptors is a list of counter symbol along with their non-negative integer weights, listed by weight in descending order.

negative
Specifies to symbols to be appended or prepended to the counter representation if the value is negative.

prefix
Specifies a symbol that should be prepended to the marker representation. Prefixes are added to the representation in the final stage, before any characters added to negative counter values by the negative descriptor.

suffix
Specifies, similar to the prefix descriptor, a symbol that is appended to the marker representation. Suffixes come after the marker representation, including after any characters added to negative counter values by the negative descriptor.

range
Defines the range of values over which the counter style is applicable. If a counter style is used to represent a counter value outside of the ranges defined by this descriptor, the counter style will drop back to its fallback style.

pad
Is used when you need the marker representations to be of a minimum length. For example if you want the counters to start at 01 and go through 02, 03, 04, etc., then the pad descriptor is to be used. For representations larger than the specified pad value, the marker is constructed as normal.

speak-as
Describes how speech synthesizers, such as screen readers, should announce the counter style. For example, the value of the list item marker can be read out as numbers or alphabets for ordered lists or as audio cues for unordered lists, based on the value of this descriptor.

fallback
Specifies the counter name of the system to fall back to if either the specified system is unable to construct the representation of a counter value or if the counter value is outside the specified range. If the fallback counter also fails to represent the value, then that counter’s fallback is used, if one is specified. If there are either no fallback counters described or if the chain of fallback systems are unable to represent a counter value, then it will ultimately fall back to the decimal style.

Examples:

@counter-style circled-alpha {
  system: fixed;
  symbols: Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ;
  suffix: " ";
}

.items {
  list-style: circled-alpha;
}