Lesson 01 / 26
Rule, Declaration, and Value
The smallest units of a style language; a rule made of a selector and a declaration block, the structure of a property-value pair, and the rule that an invalid declaration is dropped.
Contents
The Web Fundamentals and HTML course turned the document into a node tree and loaded meaning onto that tree’s nodes: which one is a heading, which one is a section, which one is a table cell. In that course’s first lesson, one question in the three-way distinction it established went unanswered — the question of “how will it look?” This course answers it.
The answer comes in a separate language. That language is called CSS, and like HTML it is declarative: it states not what to do, but what should be so. This lesson names that language’s smallest units: rule, declaration, and value. If the distinctions are not established here, the conflict resolution in later lessons will not make sense, because a conflict is resolved not between rules, but between declarations.
A Rule Has Two Parts
A CSS rule has two parts: the selector, which says which elements are affected, and the declaration block, which says what will happen to them.
h1 { color: #143a52; margin-block-end: 0.5rem; }
Here, h1 is the selector, and the part between the curly braces is the declaration
block. The selector looks at the document’s tree and returns a set of elements; the
declaration block lists the changes to apply to every member of that set. It matters that
the two parts are independent of each other: the same declaration block can be written
with a different selector, and the same selector with a different block.
A selector can consist of several selectors separated by commas. This is called writing a selector list, and it is equivalent to writing the same block separately for each one:
h1, h2 { color: #143a52; }
This notation gives the same result as writing the rules h1 { color: #143a52; } and
h2 { color: #143a52; }. The equivalence is not complete: if one member of a selector list
is invalid, the behavior depends on the selector’s kind — a detail this course returns to
in the pseudo-class lesson.
Declaration: Property and Value
Every line inside a declaration block is a declaration, and it has two parts: the property to the left of the colon, and the value to the right. Declarations are separated by semicolons.
padding: 8px 12px;
A property name comes from a fixed dictionary; it cannot be invented. What forms a value
accepts is defined separately for every property: color expects a color, padding
expects between one and four lengths, text-align expects one of a numbered set of
keywords.
The following program splits a style text into its rules and declarations. It checks property names against a small dictionary and flags any that are not in it.
// style-parse.mjs — splits a style text into its rules and declarations const css = ` /* station page - first rules */ body { font-family: system-ui; line-height: 1.5 } h1, h2 { color: #143a52; margin-block-end: 0.5rem; } .measurement-table td { padding: 8px 12px; text-align: right; colour: blue } `; // drop comments, then split on the { } pair into rules const clean = css.replace(/\/\*[\s\S]*?\*\//g, ""); const rules = []; for (const chunk of clean.split("}")) { const [selector, body] = chunk.split("{"); if (body === undefined) continue; const declarations = body .split(";") .map((d) => d.trim()) .filter((d) => d.length > 0) .map((d) => { const colon = d.indexOf(":"); return { property: d.slice(0, colon).trim(), value: d.slice(colon + 1).trim() }; }); rules.push({ selector: selector.trim().replace(/\s+/g, " "), declarations }); } const known = new Set([ "font-family", "line-height", "color", "margin-block-end", "padding", "text-align", ]); for (const r of rules) { console.log(`selector : ${r.selector}`); console.log(`declaration : ${r.declarations.length}`); for (const d of r.declarations) { const status = known.has(d.property) ? "valid" : "DROPPED"; console.log(` ${d.property} = ${d.value} [${status}]`); } } console.log(`total rules : ${rules.length}`); console.log(`total declarations: ${rules.reduce((t, r) => t + r.declarations.length, 0)}`);
selector : body declaration : 2 font-family = system-ui [valid] line-height = 1.5 [valid] selector : h1, h2 declaration : 2 color = #143a52 [valid] margin-block-end = 0.5rem [valid] selector : .measurement-table td declaration : 3 padding = 8px 12px [valid] text-align = right [valid] colour = blue [DROPPED] total rules : 3 total declarations: 7
Three things become visible. First, the semicolon after the last declaration in a
block is not required; it was missing for body and for the last rule, and the
declarations still split correctly. Second, comments are written between /* … */ and are
discarded before parsing. Third, there is no property named colour; that declaration is
dropped, and only that declaration — the other two in the block are applied.
Invalidity Is Resolved at the Declaration Level
This last point speaks to the design of the language. The HTML Fundamentals course showed that the HTML parser does not reject a malformed document — it produces a result through defined recovery rules. CSS follows the same principle and defines recovery at three levels:
- If the property name is not recognized, that declaration is dropped; the block survives.
- If the property is recognized but the value does not match that property’s grammar,
that declaration is dropped as well. If
color: navy-ishis written, thecolorproperty stays at its previous value. - If the selector is not recognized, the entire rule is dropped; the declaration block applies to no element.
The common result of these three rules is that a style file never “fails to compile.” The part that is not understood silently falls away, and the rest is processed. The syntax error concept from the Programming Fundamentals course does not apply here: an error is not a reason to stop, it is a reason to skip.
This tolerance has a cost: a misspelled property name disappears without producing any warning. A declaration can fail to have an effect for two separate reasons — it was dropped, or it was overridden by another rule — and from the outside the two look identical. This distinction is made measurable in the cascade lesson.
Shorthand Properties and Their Longhands
Some properties do not carry a single value; they set several properties at once. These are called shorthand properties, and the properties they set are called that shorthand’s longhands.
The declaration padding: 8px 12px does not write to a single property, but to four. The
distribution rule based on the number of values is:
| Value count | Top | Right | Bottom | Left |
|---|---|---|---|---|
1 → 8px |
8px | 8px | 8px | 8px |
2 → 8px 12px |
8px | 12px | 8px | 12px |
3 → 8px 12px 4px |
8px | 12px | 4px | 12px |
4 → 8px 12px 4px 2px |
8px | 12px | 4px | 2px |
The order is clockwise: top, right, bottom, left. Missing values are copied from the opposite side.
A shorthand has a behavior that matters as much as its notation: it resets any longhand
it does not write to its initial value. When font: 16px serif is written, it is not only
size and family that get set; every longhand that shorthand covers — font-weight,
font-style, line-height, and so on — is reset to its initial value. This behavior makes
it dangerous to use a shorthand to change a single longhand that was set earlier. The rule
is: a shorthand is written to establish a group, a longhand to change a single
value from that group, and in that case the shorthand comes first.
The Station Page’s First Rules
This course styles the measurement station page built in the previous course. The page carried North Slope Station’s identification block, its measurement table, a location image, and a correction-notice form. So far, no style has been written; the page’s appearance has come from the browser’s own default style file — headings being bold and large, lists being indented, links being underlined are that file’s decisions.
The style file at the center of this course begins here:
/* station.css — step 1: base declarations */ body { font-family: system-ui, sans-serif; line-height: 1.5; color: #1c2733; } h1 { font-size: 2rem; margin-block-end: 0.5rem; } .measurement-table td { padding: 8px 12px; text-align: right; }
Three rules, seven declarations. Each lesson will add a layer to this file and justify why the added layer is written the way it is. By the end of the course, the file will be a complete style file carrying a color scale, a type scale, a spacing scale, and status styles.
Summary
- A CSS rule consists of a selector and a declaration block; the selector returns a set of elements from the document, and the block lists the declarations to apply to that set.
- A declaration is a property-value pair separated by a colon; the property name comes from a fixed dictionary, and each property defines its value’s grammar separately.
- Invalidity is resolved at the declaration level: an unrecognized property or a value that does not match only drops that declaration, and the block keeps working. An unrecognized selector drops the entire rule.
- A shorthand property sets a group of longhands at once and resets any longhand it does not write to its initial value; that is why a shorthand is for establishing a group, a longhand for fixing one.
- The page’s unstyled appearance comes from the browser’s default style file; every rule written is added on top of that file.
Next Step
This lesson established the structure of a rule but did not say how rules reach the document. A style file can be attached to a document in three different ways, and these three ways differ not just in how easy they are to write, but in loading order and conflict resolution. The next lesson compares these three ways and revisits, from the style file’s side, the render-blocking behavior established in the Web Fundamentals and HTML course’s resource-loading-order lesson.
To keep your progress and take notes, Log in
My notes
Log in to take notes.