Heyjiawei Blog

How to read the CSS specification syntax, a.k.a. CSS Property value syntax

July 26, 2020

Sometime back, I had to create this perforated gap with CSS. I wanted to use CSS background shorthand property but I didn’t know how to read it’s cryptic Formal syntax section.

After some googling, it turns out this syntax is called Value Definition Syntax. So here is my notes on how to read Value Definition Syntax.

Before we jump into my notes, I would like to clarify that I have read from both the specification and MDN’s summarised version of Value Definition Syntax. I felt that reading both gave me more clarity than just reading either and hence, if you do wish to learn how to read Value Definition Syntax, I would recommend you read both documents.

Before we can jump into [ ] && * +, we need to know how to read the words used together with these symbols. These words are called component value types.

Component Value Types

keywords - Are predefined literals. They have no quotes.

height: auto

auto is a keyword. It has no quotes and its a predefined literal in CSS. Other common keywords are inherit, initial and unset.

literals - “literally mean what their character mean”

/ can refer to the math division symbol. And it can also refer to the CSS shorthand syntax, which separates values that are semantically different but have a common syntax. I understand this with the example of background-position and background-size. Both stem from background but are different.

, separates values as you enumerate a list of values.

Data Types

Data types are separated into 2 types, the basic data types like <string>, <angle> and the non-terminal data types. I couldn’t understand the explanation of non-terminal data types but I think non-terminal data types are as follows:

  1. They are data types that share the same name of a property. But are put between quotes. E.g. <'border-width'>. This syntax actually defines the value of border-width property.
  2. The ones without quotes, e.g. <border-width> will be expanded later in the specification document. Basically, if you don’t see quotes within the angular brackets, then they aren’t the full definition

Update on 28th July 2020: To understand non-terminal, you have to understand that terminal and non-terminal are a pair. Non-terminal means that the term can be replaced. Terminal means that it terminates. This stackover flow question paints a good mental picture. Basically, as @jyee721 puts it, terminal is a constant value and non-terminal is a variable.

Now that we have the component value types, we need to know how to combine them and the component value combinators does exactly that.

Component Value Combinators

This section felt similar to boolean operators in JavaScript.

Brackets

Brackets are used to group components to bypass precendence rules. This is akin to () in JavaScript evaluation.

Juxtaposition

I would reword this to “Positioning matters”. The term “Juxtaposing components” means that all components must occur in the exact order as stated in the syntax.

Double ampersand &&

This symbol appears between 2 components bold && <length> and it means that these 2 components are mandatory but their order doesn’t matter. So bold && <length> is equivalent to <length> && bold.

Double bar ||

This symbol appears between 2 options. The term option is used because at least 1 option needs to be present. This means that more than 1 option can be used too! Oh, and their order doesn’t matter.

Single bar |

This symbol appears between 2 alternatives because only 1 of them must be present.

Precedence of Component Value Combinators

Like mathematics, component value combinators also follow a precedence rule.

  • Juxtaposition has precedence over the double ampersand

bold thin && <length> is equivalent to [ bold thin ] && <length>.

  • && has precendence over ||

bold || thin && <length> is equivalent to bold || [ thin && <length> ]

  • || has precendence over |

But that’s not all. Remember those pesky ? * + operators? Yeah they mean something too. I find them similar to regex operators.

Component Value Multipliers

These operators are called multipliers for they indicate how many times the type/keyword/bracketed group may be repeated. If there is no multiplier, the entity must appear exactly one time. Also, multipliers have precendence over all combinators.

Asterisk *

The * indicates that the preceding type, word, or group can occur zero, 1 or more times.

Plus +

The + indicates that the preceding type, word or group can occur 1 or more times.

Question mark ?

The ? indicates that the preceding type, word, or group is optional. This means they can occur zero or 1 time.

Curly braces { }

The { } indicates a range. If there is a digit within it, e.g. {3}, the preceding type, word or group will occur 3 times.

If there is a comma-separated pair of number, e.g. {4,6}, it indicates that the preceding type, word, or group must occur at at least 4 times and at most 6 times.

If you have a single digit and a comma like so {4,} it indicates that there must be at least 4 repetitions, with no upper bound on the number of repetitions. But the CSS specs also declared that User Agents must support at least 20 repetitions of the component. If a property value contains more than the supported number of repetitions, the declaration will be ignored as if it were invalid.

And there is no {,4}.

Hash #

The # indicates that the preceding type, word, or group occurs 1 or more times, separated by comma tokens. The white space surrounding the commas are optional.

The # may optionally be followed by { } to indicate precisely how many times the repetition occurs, like <length>#{1,4}. This means <length> can appear 1 to 4 times, and on each appearance, it has to be separated by comma.

e.g. <length>, <length>, <length>

Exclamation !

Indicates that the group is required and there must be at least 1 value. Even if the grammar of the items within the group allows the entire contents to be omitted, like [ bold? smaller? ] where you can skip the whole group; adding ! means at least 1 component value must exist.

[ bold? smaller? ]! would hence match

  • bold
  • smaller
  • bold smaller

Unless otherwise specified, white space and/or comments may appear before, after, and/or between components combined using the above combinators and multipliers.

Summary

  • combinators are tied to order and presence
  • multipliers are tied to frequency

From the specs, the section on Combinator and Multiplier Patterns shows that there are a small set of common ways to combine multiple independent component values in particular numbers and orders.