Module 1: Introduction & Fundamentals
Syntax and Structure: Rules, Declarations and How Browsers Handle Errors
The anatomy of a CSS rule, shorthand versus longhand, comments, at-rules, and the exact way browsers recover from invalid CSS.
CSS syntax is small. You can learn all of it in an afternoon. What takes longer is understanding how browsers behave when the syntax is slightly wrong, because that is where most beginner bugs come from.
Anatomy of a rule#
.card, .panel {
padding: 1rem;
border: 1px solid #ddd;
}
Reading it from the outside in:
.card, .panel { padding: 1rem; border: 1px solid #ddd; }
└─────┬──────┘ └───────────────────┬─────────────────┘
selector list declaration block
└──────┬──────┘
declaration
property : value ;
- The selector list says which elements the rule applies to. Commas mean "or".
- The declaration block is everything between the braces.
- A declaration is a property, a colon, a value, and a semicolon.
Whitespace does not matter. You can write the whole rule on one line or spread it over ten. Teams pick a style and enforce it with a formatter (Module 10).
Values come in a few shapes#
.box {
display: flex; /* keyword */
width: 320px; /* number with unit */
line-height: 1.5; /* unitless number */
color: rgb(20 20 20); /* function */
margin: 0 auto; /* multiple values */
width: calc(100% - 2rem); /* function with math */
font-family: "Inter", sans-serif; /* list, with a string */
}
Zero is the only number that can skip its unit: margin: 0 is fine. margin: 10 is invalid, and the browser ignores the declaration.
Comments#
/* This is the only comment syntax CSS has. */
There is no //. If you write // reset before a rule, the browser parses it as part of the next selector, which makes that selector invalid, and the rule disappears. It is a classic bug.
At-rules#
Rules that start with @ are instructions to the browser, not style rules for elements. You will meet these throughout the course:
@import url("theme.css"); /* pull in another file (use sparingly) */
@media (min-width: 768px) { ... } /* conditional styles */
@font-face { ... } /* define a custom font */
@keyframes spin { ... } /* define an animation */
@supports (display: grid) { ... } /* feature detection */
@layer base, components; /* control cascade order */
Shorthand and longhand#
Many properties are shorthands that set several longhand properties at once.
.a { margin: 10px 20px 30px 40px; } /* top right bottom left, clockwise */
.b { margin: 10px 20px; } /* vertical | horizontal */
.c { margin: 10px; } /* all four */
Here is the part that bites. A shorthand always sets all of its longhands, and the ones you leave out are reset to their initial values.
.hero {
background-image: url("hero.jpg");
background-size: cover;
}
.hero.dark {
background: #111; /* resets image AND size back to initial */
}
The second rule does not just change the color. background also resets background-image and background-size, so the photo vanishes. When you only want to change one aspect, use the longhand (background-color).
How browsers recover from errors#
CSS is designed to be forward-compatible, so browsers are lenient by default. The rules for failure are specific, and you should know them:
An invalid declaration is dropped. The rest of the rule survives.
.btn {
color: white;
padding: 10; /* invalid: no unit. Dropped. */
background: #0b5fff; /* still applied */
}
An invalid selector in a list drops the entire rule.
h1, h2, ::unknown-thing {
margin: 0; /* nothing applies, not even to h1 and h2 */
}
That is why unknown pseudo-selectors can silently break a whole group. The newer :is() selector is "forgiving" and ignores invalid entries instead, which is one reason it exists.
Later declarations win, so you can build fallbacks.
.panel {
background: #444; /* old browsers stop here */
background: color-mix(in srgb, red, blue); /* new browsers override it */
}
A browser that does not understand the second line drops it and keeps the first. This is the oldest feature-detection trick in CSS, and it still works.
Case sensitivity and naming#
Property names and keywords are not case-sensitive (COLOR: RED works), but nobody writes that. Class names and IDs in selectors are case-sensitive, because HTML treats them that way: .Card does not match class="card".
Names in CSS use hyphens by convention: font-size, .main-nav. Underscores work but look out of place.
Common mistakes#
- A missing semicolon.
color: redfollowed bymargin: 0on the next line without a semicolon gets read as one broken value, and both declarations die. //comments. See above.- Spaces in the wrong place.
calc(1px+2px)is invalid because+needs spaces around it. A space between a function name and its parenthesis, such asrgb (0 0 0), is also invalid. - Typos that fail silently.
colour,font-wieght,margin-botom. Check DevTools for the strikethrough. - Resetting by accident with a shorthand, as in the
backgroundexample.
Practice#
- Write a rule with three deliberate errors: a missing unit, a misspelled property, and a missing semicolon. Open it in DevTools and see exactly which declarations survive.
- Put
// this is a commentabove a working rule and observe what breaks. Then fix it properly. - Give an element a background image with
background-image, then override only its color without losing the image, first using the longhand and then the shorthand. Compare the results. - Write a two-line fallback for a property of your choice, using a value your browser does not support on the second line (for example a nonsense keyword), and confirm the first line stays in effect.