CSS3 & Responsive Design

CSS Syntax, Rulesets & Comments

20 min Lesson 2 of 60

The Anatomy of a CSS Ruleset

Every CSS style you write follows a precise structure called a ruleset (sometimes simply called a "rule"). Whether you are changing a single color or building a complex responsive layout, you are always writing rulesets. Mastering the anatomy of a ruleset is the first step to writing CSS confidently, because once you understand how the parts fit together, every new property and value you learn simply slots into this same structure.

A CSS ruleset consists of two fundamental parts: a selector and a declaration block. The selector identifies which HTML element or elements the styles should apply to. The declaration block, wrapped in curly braces { }, contains one or more declarations -- each of which pairs a property with a value.

The Structure of a CSS Ruleset

selector {
    property: value;
    property: value;
    property: value;
}

/* A concrete example: */
h1 {
    color: navy;
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 16px;
}

Let us dissect each component in detail:

  • Selector (h1) -- This tells the browser which elements on the page this ruleset targets. In the example above, every <h1> element in the document will receive these styles. Selectors can be simple (a tag name, a class, an ID) or complex (combining multiple conditions). We will explore selectors in depth in the next lesson.
  • Opening curly brace ({) -- Marks the start of the declaration block. Everything between { and } is part of this ruleset's declarations.
  • Declaration (color: navy;) -- A single styling instruction. It always follows the pattern property: value;. Each declaration changes one specific visual aspect of the targeted elements.
  • Property (color) -- The specific aspect of the element you want to control. CSS has hundreds of properties covering colors, fonts, spacing, layout, animation, and more. Properties are predefined keywords -- you cannot invent your own (though CSS custom properties provide a variable-like mechanism).
  • Colon (:) -- The required separator between the property name and the value. Without it, the browser cannot parse the declaration.
  • Value (navy) -- The specific setting you want for that property. Different properties accept different types of values: keywords (like navy, bold, center), numeric values with units (like 16px, 2rem, 50%), color codes (like #1a1a2e, rgb(255, 0, 0)), or functional values (like url(), calc()).
  • Semicolon (;) -- Marks the end of each declaration. The semicolon is required between declarations. While the last declaration in a block technically does not need one, you should always include it -- omitting it is the single most common source of subtle CSS bugs.
  • Closing curly brace (}) -- Marks the end of the declaration block and the entire ruleset.
Note: The terms "rule," "ruleset," and "rule set" are used interchangeably in CSS documentation. The official CSS specification uses "rule" for the broader concept and "ruleset" specifically for the selector + declaration block structure. In everyday conversation, most developers simply say "rule."

Multiple Declarations in a Single Ruleset

A single ruleset can contain as many declarations as you need. Each declaration controls a different aspect of the targeted element's appearance. The order of declarations within a ruleset generally does not matter -- the browser applies all of them independently. However, there is one important exception: if you declare the same property more than once within the same ruleset, the last declaration wins.

Example: A Ruleset with Many Declarations

/* Styling an article card with multiple declarations */
.article-card {
    display: block;
    max-width: 640px;
    background-color: #ffffff;
    border: 1px solid #e0e0e0;
    border-radius: 8px;
    padding: 24px;
    margin-bottom: 20px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    font-family: Georgia, "Times New Roman", serif;
    line-height: 1.7;
    color: #333333;
    transition: box-shadow 0.3s ease;
}

/* When the same property appears twice, the last one wins */
p {
    color: red;
    font-size: 16px;
    color: blue;  /* This overrides the earlier color: red */
}
/* Result: paragraphs will be blue, 16px */
Tip: Declaring the same property twice is not always a mistake -- it is a legitimate fallback strategy. You provide a safe, widely-supported value first, followed by a modern value. Browsers that do not understand the modern value will use the first one, while modern browsers use the second. Example: background: #333; background: linear-gradient(to right, #333, #666);. Older browsers get the solid color; modern browsers get the gradient. This technique is called progressive enhancement and is considered a CSS best practice.

Multiple Selectors for One Ruleset

You can apply the exact same set of declarations to multiple selectors by separating the selectors with commas. This is called selector grouping and is one of the most important techniques for keeping your CSS concise and avoiding repetition.

Example: Grouping Selectors

/* WITHOUT grouping -- repetitive and hard to maintain */
h1 {
    font-family: "Segoe UI", Arial, sans-serif;
    color: #1a1a2e;
    line-height: 1.2;
}

h2 {
    font-family: "Segoe UI", Arial, sans-serif;
    color: #1a1a2e;
    line-height: 1.2;
}

h3 {
    font-family: "Segoe UI", Arial, sans-serif;
    color: #1a1a2e;
    line-height: 1.2;
}

/* WITH grouping -- clean and DRY (Don't Repeat Yourself) */
h1,
h2,
h3 {
    font-family: "Segoe UI", Arial, sans-serif;
    color: #1a1a2e;
    line-height: 1.2;
}

/* You can then add unique styles for each heading separately */
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.5rem; }

Each selector in the group is treated independently. If one selector in the group is invalid, modern browsers will still apply the rule to the other valid selectors. However, in older CSS behavior, an invalid selector could cause the entire grouped rule to be discarded -- so always double-check your selectors.

Example: Grouping Different Types of Selectors

/* You can mix selector types in a group */
h1,
.page-title,
#main-heading,
[role="heading"] {
    font-weight: 700;
    letter-spacing: -0.02em;
    margin-bottom: 0.5em;
}

/* Common pattern: resetting link styles across states */
a:link,
a:visited,
a:hover,
a:active {
    text-decoration: none;
}

/* Formatting tip: put each selector on its own line */
.btn-primary,
.btn-secondary,
.btn-outline,
.btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 10px 24px;
    border-radius: 6px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}
Tip: When grouping selectors, place each selector on its own line with a trailing comma. This makes the rule easier to read, easier to edit, and produces cleaner diffs in version control systems like Git. It also makes it much easier to spot if you accidentally missed a comma (which would create a descendant selector instead of a group).

Shorthand vs Longhand Properties

CSS offers two ways to declare many properties: the longhand form (individual properties) and the shorthand form (a single property that sets multiple related values at once). Understanding the difference is crucial because shorthand properties are everywhere in real-world CSS, and misusing them is a common source of bugs.

What Are Shorthand Properties?

A shorthand property lets you set several related properties in a single declaration. For example, instead of writing four separate margin declarations, you can write one:

Example: Longhand vs Shorthand

/* LONGHAND -- four separate declarations */
.box {
    margin-top: 10px;
    margin-right: 20px;
    margin-bottom: 10px;
    margin-left: 20px;
}

/* SHORTHAND -- one declaration, same result */
.box {
    margin: 10px 20px;
}

/* ---------------------------------------- */

/* LONGHAND -- background properties individually */
.hero {
    background-image: url("hero.jpg");
    background-position: center center;
    background-size: cover;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-color: #1a1a2e;
}

/* SHORTHAND -- all background properties in one */
.hero {
    background: #1a1a2e url("hero.jpg") center / cover no-repeat fixed;
}

/* ---------------------------------------- */

/* LONGHAND -- font properties individually */
.text {
    font-style: italic;
    font-weight: 700;
    font-size: 18px;
    line-height: 1.6;
    font-family: Georgia, serif;
}

/* SHORTHAND -- all font properties in one */
.text {
    font: italic 700 18px/1.6 Georgia, serif;
}

/* ---------------------------------------- */

/* LONGHAND -- border properties individually */
.card {
    border-width: 2px;
    border-style: solid;
    border-color: #e0e0e0;
}

/* SHORTHAND -- all border properties in one */
.card {
    border: 2px solid #e0e0e0;
}

Common Shorthand Properties

Here are the most frequently used shorthand properties:

  • margin -- Sets margin-top, margin-right, margin-bottom, margin-left
  • padding -- Sets padding-top, padding-right, padding-bottom, padding-left
  • border -- Sets border-width, border-style, border-color
  • background -- Sets background-color, background-image, background-position, background-size, background-repeat, background-attachment
  • font -- Sets font-style, font-variant, font-weight, font-size, line-height, font-family
  • flex -- Sets flex-grow, flex-shrink, flex-basis
  • transition -- Sets transition-property, transition-duration, transition-timing-function, transition-delay
  • animation -- Sets animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, animation-fill-mode, animation-play-state

The Margin and Padding Shorthand Patterns

The margin and padding shorthands follow a special pattern based on how many values you provide:

Example: Margin/Padding Value Patterns

/* ONE value: applies to ALL four sides */
.box-a {
    margin: 20px;
    /* Same as: margin-top: 20px; margin-right: 20px;
                margin-bottom: 20px; margin-left: 20px; */
}

/* TWO values: vertical | horizontal */
.box-b {
    margin: 10px 20px;
    /* Same as: margin-top: 10px; margin-right: 20px;
                margin-bottom: 10px; margin-left: 20px; */
}

/* THREE values: top | horizontal | bottom */
.box-c {
    margin: 10px 20px 30px;
    /* Same as: margin-top: 10px; margin-right: 20px;
                margin-bottom: 30px; margin-left: 20px; */
}

/* FOUR values: top | right | bottom | left (clockwise) */
.box-d {
    margin: 10px 20px 30px 40px;
    /* Same as: margin-top: 10px; margin-right: 20px;
                margin-bottom: 30px; margin-left: 40px; */
}

/* Memory aid: think of a clock -- start at 12 and go clockwise:
   12 o'clock = top
    3 o'clock = right
    6 o'clock = bottom
    9 o'clock = left */
Warning: A critical gotcha with shorthand properties is that they reset omitted values to their defaults. For example, if you set background: url("image.jpg");, it will reset background-color to transparent, even if you had previously set a background color. This is because the background shorthand sets ALL background sub-properties. If you only want to change the image without affecting the color, use the longhand background-image: url("image.jpg"); instead. This "reset" behavior is the number one source of confusion with shorthand properties.

Example: Shorthand Reset Behavior

/* Potential problem with shorthand */
.element {
    background-color: #1a1a2e;
    background-image: url("pattern.png");
    background-repeat: repeat;
    background: url("hero.jpg") center / cover no-repeat;
    /* DANGER: The shorthand above resets background-color to transparent!
       The #1a1a2e color is gone. If hero.jpg fails to load,
       the background will be transparent, not dark navy. */
}

/* Safer approach */
.element {
    background: #1a1a2e url("hero.jpg") center / cover no-repeat;
    /* Include the fallback color in the shorthand itself */
}

/* Or use longhand to change only what you need */
.element {
    background-color: #1a1a2e;
    background-image: url("hero.jpg");
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}

CSS Comments

Comments in CSS are written between /* and */. Everything between these delimiters is completely ignored by the browser. Comments are an essential tool for writing maintainable CSS -- they help you document your code, explain non-obvious decisions, organize large stylesheets into logical sections, and temporarily disable rules during debugging.

Example: CSS Comment Syntax

/* This is a single-line comment */

/*
   This is a multi-line comment.
   It can span as many lines as you need.
   Useful for longer explanations.
*/

.header {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    background-color: #1a1a2e; /* Dark navy -- matches brand guidelines */
    padding: 15px 30px;
    z-index: 1000; /* Must stay above modal overlays (z-index: 999) */
}

Types of Comments and When to Use Them

Professional CSS developers use comments strategically. Here are the most common patterns:

Example: Comment Patterns Used by Professional Developers

/* ============================================================
   SECTION HEADER COMMENTS
   Used to divide a stylesheet into major sections.
   Makes it easy to find code with Ctrl+F / Cmd+F.
   ============================================================ */

/* --- Sub-section Comment ---
   Divides a section into smaller logical groups */

/* Brief inline comment explaining a specific decision */
.nav-link {
    padding: 8px 16px;
    white-space: nowrap; /* Prevent link text from wrapping to two lines */
}

/* TODO: Refactor this section when the new design system is finalized */

/* HACK: Workaround for Safari flexbox gap bug.
   Remove when Safari 16+ has majority market share.
   See: https://bugs.webkit.org/show_bug.cgi?id=XXXXX */
.flex-container > * + * {
    margin-left: 16px;
}

/* DEPRECATED: Old button styles -- use .btn-primary instead */
.old-button {
    background: gray;
}

/*
   DEBUG: Temporarily disabling this rule to test layout
   .sidebar {
       width: 300px;
       float: left;
   }
*/

/* @FIXME: This breaks on screens narrower than 320px */

Table of Contents Pattern

For large stylesheets, a table of contents at the top is invaluable:

Example: Table of Contents Comment

/* ============================================================
   STYLESHEET TABLE OF CONTENTS
   ============================================================
   1. CSS Custom Properties (Variables)
   2. Reset / Normalize
   3. Base Typography
   4. Layout System
   5. Header & Navigation
   6. Hero Section
   7. Content Sections
   8. Cards & Components
   9. Forms & Inputs
   10. Buttons
   11. Footer
   12. Utility Classes
   13. Animations
   14. Media Queries
   ============================================================ */

/* ============================================================
   1. CSS CUSTOM PROPERTIES
   ============================================================ */
:root {
    --color-primary: #1a1a2e;
    --color-accent: #e94560;
    --font-body: "Inter", sans-serif;
    --spacing-unit: 8px;
}

/* ============================================================
   2. RESET / NORMALIZE
   ============================================================ */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* ... remaining sections ... */

No Single-Line Comment Syntax

Unlike JavaScript, Python, or most programming languages, CSS does not support single-line comments with //. If you write // this is a comment in CSS, it will not be treated as a comment. Instead, the browser will try to interpret it as a CSS property -- and since // is not a valid property, it will generate a parse error that can cause unpredictable behavior.

Example: Invalid Comment Syntax

/* CORRECT -- this is a valid CSS comment */
.box { color: blue; }

// WRONG -- this is NOT a comment in CSS!
// The browser sees this as invalid CSS and may
// skip the following rules as well.
.box { color: red; }

/* If you come from JavaScript, be careful!
   Always use the slash-star syntax in CSS. */
Warning: Never place sensitive information in CSS comments. CSS files are publicly accessible to anyone visiting your website. Browsers download stylesheets as plain text, and anyone can view them through View Source, the Network tab, or by simply navigating to the CSS file URL. Never put passwords, API keys, internal architecture details, or any private information in CSS comments.

Whitespace Handling in CSS

CSS is extremely flexible about whitespace -- spaces, tabs, newlines, and carriage returns. The browser ignores all extra whitespace when parsing CSS. This means you have complete freedom in how you format your code, which is why CSS can be written in many different styles and still work identically.

Example: Different Formatting Styles (All Equivalent)

/* Style 1: Expanded (recommended for development) */
.card {
    display: flex;
    flex-direction: column;
    background: white;
    border-radius: 8px;
    padding: 24px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* Style 2: Compact single-line */
.card { display: flex; flex-direction: column; background: white; border-radius: 8px; padding: 24px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }

/* Style 3: Minified (no whitespace at all) */
.card{display:flex;flex-direction:column;background:white;border-radius:8px;padding:24px;box-shadow:0 2px 8px rgba(0,0,0,0.1)}

/* All three produce the EXACT same result in the browser */

Here are the whitespace rules to remember:

  • Between the selector and the opening brace -- Whitespace is optional but recommended for readability (h1 { vs h1{).
  • Between declarations -- Only the semicolons matter. You can put each declaration on its own line (recommended) or on one line.
  • Within a declaration -- The space after the colon is optional but recommended (color: red vs color:red).
  • Within values -- Some values require specific whitespace. For example, calc(100% - 20px) needs the spaces around the minus sign: calc(100%-20px) does not work. The rgb() and hsl() functions in modern CSS accept spaces instead of commas: rgb(255 0 0).
  • In selector lists -- Whitespace around commas is optional: h1, h2, h3 and h1,h2,h3 are equivalent.
Note: During development, always use the expanded format with clear indentation. Use 2 or 4 spaces for indentation -- pick one and be consistent. The compact or minified format should only be used in production, and this minification should be handled by automated build tools (like PostCSS, cssnano, or your bundler's built-in minifier), never done by hand.

Common Syntax Errors and How to Avoid Them

CSS syntax errors are particularly insidious because CSS does not throw visible errors like JavaScript or server-side languages do. When the browser encounters invalid CSS, it silently ignores the broken rule and moves on to the next one. This means your page will not crash, but the broken styles simply will not apply -- and you might not notice until you wonder why your design looks wrong.

Error 1: Missing Semicolons

Example: Missing Semicolon Bug

/* BROKEN -- missing semicolon after "navy" */
h1 {
    color: navy
    font-size: 2rem;
    margin-bottom: 16px;
}
/* The browser tries to read "navy font-size: 2rem" as a single
   value for the color property. This is invalid, so it ignores
   BOTH the color and font-size declarations.
   Only margin-bottom: 16px applies. */

/* FIXED */
h1 {
    color: navy;
    font-size: 2rem;
    margin-bottom: 16px;
}

Error 2: Missing or Mismatched Braces

Example: Mismatched Braces

/* BROKEN -- missing closing brace */
.header {
    background: #1a1a2e;
    color: white;
    padding: 20px;
/* The parser never finds the closing brace for .header,
   so it keeps reading. The next ruleset becomes part of
   .header's declaration block, and styles go haywire. */

.main-content {
    max-width: 800px;
    margin: 0 auto;
}

/* FIXED */
.header {
    background: #1a1a2e;
    color: white;
    padding: 20px;
}

.main-content {
    max-width: 800px;
    margin: 0 auto;
}

Error 3: Missing Colon in Declarations

Example: Missing Colon

/* BROKEN -- missing colon */
p {
    color red;
    font-size: 16px;
}
/* "color red" is not a valid declaration.
   The browser ignores it. font-size still works. */

/* FIXED */
p {
    color: red;
    font-size: 16px;
}

Error 4: Invalid Values

Example: Invalid Property Values

/* BROKEN -- invalid values */
.box {
    color: 42;            /* Color cannot be a plain number */
    margin: big;          /* "big" is not a valid length */
    font-size: purple;    /* Cannot use a color name for font-size */
    width: 100;           /* Missing unit -- should be 100px or 100% */
    padding: -20px;       /* Padding cannot be negative */
    z-index: 3.5;         /* z-index must be an integer */
}
/* Each invalid declaration is ignored individually.
   Valid declarations in the same rule still apply. */

/* FIXED */
.box {
    color: #333333;
    margin: 20px;
    font-size: 16px;
    width: 100%;
    padding: 20px;
    z-index: 3;
}

Error 5: Typos in Property Names

Example: Misspelled Properties

/* BROKEN -- typos in property names */
.text {
    colour: red;          /* British spelling -- CSS uses American "color" */
    font-sie: 16px;       /* Misspelled "font-size" */
    marin-bottom: 20px;   /* Misspelled "margin-bottom" */
    backgroud: white;     /* Misspelled "background" */
    trasition: all 0.3s;  /* Misspelled "transition" */
}
/* All of these are silently ignored */

/* FIXED */
.text {
    color: red;
    font-size: 16px;
    margin-bottom: 20px;
    background: white;
    transition: all 0.3s;
}
Tip: Use a code editor with CSS autocompletion and linting (like VS Code with the CSS Language Features extension, or the Stylelint plugin). Autocompletion prevents typos in property names, and a linter will highlight invalid values before you even open the browser. This single habit will save you hours of debugging time.

CSS Error Handling: How Browsers Deal with Invalid CSS

Understanding how browsers handle errors is critical for debugging and for writing robust CSS that works across different browsers and versions. The core principle is simple: browsers skip what they do not understand. This behavior is actually by design and is fundamental to how CSS evolves over time.

The Rules of CSS Error Recovery

  • Invalid declaration -- If a declaration has an unknown property or invalid value, only that single declaration is ignored. Other declarations in the same ruleset still apply normally.
  • Invalid selector -- If a selector cannot be parsed, the entire ruleset (including all its declarations) is discarded. This is more severe than an invalid declaration.
  • Unclosed brace -- If an opening brace is never closed, the parser will try to find a closing brace, potentially consuming subsequent rulesets. This is the most destructive type of error.
  • Unclosed comment -- If /* is never closed with */, everything after it until the end of the file (or the next */ it finds) is treated as a comment. This can silently disable large portions of your stylesheet.

Example: How Browsers Skip Invalid CSS

/* Demonstrating CSS error recovery */
.box {
    color: navy;              /* Valid -- applied */
    font-size: huge;          /* Invalid value -- ignored */
    padding: 20px;            /* Valid -- applied */
    margin: red;              /* Invalid value for margin -- ignored */
    background: #f5f5f5;      /* Valid -- applied */
    bordre: 1px solid #ccc;   /* Invalid property name -- ignored */
    border-radius: 8px;       /* Valid -- applied */
}

/* Result: The .box element gets:
   color: navy;
   padding: 20px;
   background: #f5f5f5;
   border-radius: 8px;

   The three invalid declarations are silently skipped.
   No errors appear on screen. No console errors in most browsers.
*/

Why This Behavior Is Useful

The "skip what you do not understand" behavior is what makes CSS forwards-compatible. When new CSS features are added to the specification, only browsers that support them will apply the new styles. Older browsers will simply ignore the unfamiliar properties or values and use whatever fallback styles are in place. This is why CSS can introduce new features without breaking old websites -- a design philosophy fundamentally different from programming languages where a syntax error crashes the entire program.

Example: Forward Compatibility in Action

/* This CSS works in ALL browsers, old and new */
.container {
    display: block;          /* Fallback for old browsers */
    display: flex;           /* Modern browsers use this */
    display: grid;           /* Newest browsers use this */
    gap: 20px;               /* Only Grid/Flex browsers apply this */
    width: 90%;              /* Fallback width */
    width: clamp(300px, 90%, 1200px); /* Modern browsers use this */
}

/* Old browsers: display: block, width: 90%
   Modern browsers: display: grid, width: clamp(...), gap: 20px

   No errors anywhere. Both old and new browsers
   render something usable. */

Valid vs Invalid CSS Values

Each CSS property accepts specific types of values. Using the wrong type of value is one of the most common errors. Here is a summary of the major value types:

Example: CSS Value Types

/* KEYWORDS -- predefined words with specific meanings */
.element {
    display: flex;                /* flex, block, inline, grid, none, etc. */
    position: relative;           /* static, relative, absolute, fixed, sticky */
    text-align: center;           /* left, right, center, justify */
    font-weight: bold;            /* normal, bold, lighter, bolder */
    overflow: hidden;             /* visible, hidden, scroll, auto */
}

/* LENGTHS -- numbers with units */
.element {
    width: 300px;                 /* Pixels */
    height: 50vh;                 /* Viewport height percentage */
    font-size: 1.25rem;           /* Root em units */
    margin: 2em;                  /* Em units (relative to parent font-size) */
    padding: 5%;                  /* Percentage of parent width */
    border-width: 0.5mm;          /* Millimeters (for print) */
    gap: 1.5vw;                   /* Viewport width percentage */
}

/* COLORS -- multiple formats available */
.element {
    color: red;                   /* Named color (147 names available) */
    color: #ff0000;               /* Hexadecimal (6-digit) */
    color: #f00;                  /* Hexadecimal (3-digit shorthand) */
    color: #ff000080;             /* Hexadecimal with alpha (8-digit) */
    color: rgb(255, 0, 0);        /* RGB function */
    color: rgba(255, 0, 0, 0.5);  /* RGB with alpha */
    color: hsl(0, 100%, 50%);     /* HSL (Hue, Saturation, Lightness) */
    color: hsla(0, 100%, 50%, 0.5); /* HSL with alpha */
}

/* FUNCTIONS -- values that compute results */
.element {
    width: calc(100% - 40px);             /* Math calculation */
    background: url("image.jpg");          /* URL reference */
    background: linear-gradient(to right, #333, #666); /* Gradient */
    transform: rotate(45deg) scale(1.2);   /* Transform functions */
    filter: blur(4px) brightness(1.1);     /* Filter functions */
    color: var(--primary-color);           /* CSS variable reference */
    width: min(90%, 1200px);               /* Minimum of two values */
    font-size: clamp(14px, 2vw, 22px);    /* Clamped range */
}

/* NUMBERS (unitless) -- some properties accept plain numbers */
.element {
    opacity: 0.8;          /* 0 to 1, no unit */
    z-index: 100;          /* Integer, no unit */
    flex-grow: 2;           /* Number, no unit */
    line-height: 1.6;      /* Unitless ratio (preferred for line-height) */
    order: -1;              /* Integer, no unit */
}
Note: One critical rule: numeric values that represent lengths almost always need a unit. Writing width: 100 is invalid -- it must be width: 100px or width: 100% or some other unit. The only exception is the value 0, which does not need a unit because zero pixels, zero ems, and zero percent are all the same: nothing. So margin: 0 is perfectly valid without a unit.

Putting It All Together: A Complete Ruleset Example

Let us look at a realistic example that incorporates everything we have learned -- multiple rulesets, grouped selectors, shorthand properties, longhand properties, comments, and proper formatting:

Example: Complete Stylesheet Section

/* ============================================================
   CARD COMPONENT STYLES
   A reusable card component for blog posts, products, etc.
   ============================================================ */

/* Base card structure */
.card {
    display: flex;
    flex-direction: column;
    background: #ffffff;
    border: 1px solid #e2e8f0;
    border-radius: 12px;
    overflow: hidden;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

/* Card hover effect */
.card:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}

/* Card image */
.card img {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

/* Card text content area */
.card-body {
    padding: 20px;
    flex: 1; /* Shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0%; */
}

/* Card title and description share typography */
.card-title,
.card-description {
    font-family: "Inter", -apple-system, sans-serif;
    line-height: 1.5;
}

/* Individual heading and text styles */
.card-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: #1a202c;
    margin-bottom: 8px;  /* Longhand -- only setting bottom margin */
}

.card-description {
    font-size: 0.95rem;
    color: #718096;
    margin-bottom: 16px;
}

/* Card footer with action buttons */
.card-footer {
    padding: 16px 20px;        /* Shorthand: top/bottom | left/right */
    border-top: 1px solid #e2e8f0;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* TODO: Add dark mode variant styles */
/* TODO: Add .card--horizontal layout variant */

Exercise 1: Identify the Parts of a Ruleset

For each of the following CSS rules, identify the selector, each property, each value, and count the total number of declarations. Also identify any shorthand properties and list which longhand properties they represent:

.nav-link {
    display: inline-block;
    padding: 8px 16px;
    color: #ffffff;
    background: linear-gradient(135deg, #667eea, #764ba2);
    border: none;
    border-radius: 6px;
    font: 600 14px/1 "Inter", sans-serif;
    text-decoration: none;
    transition: opacity 0.2s ease;
}

h1, h2, h3, h4, h5, h6 {
    font-family: "Playfair Display", Georgia, serif;
    font-weight: 700;
    line-height: 1.2;
    color: #1a202c;
    margin: 0 0 0.5em;
}

Write down each part, identifying which properties are shorthand and what they expand to. Then rewrite the font shorthand in the first rule using only longhand properties.

Exercise 2: Fix the Broken CSS

The following CSS contains multiple syntax errors. Find and fix every error, then explain what each error would cause if left unfixed:

.hero-section {
    background-colour: #1a1a2e
    color white;
    padding; 60px 20px;
    text-align: centre;
    font-size: 18px
    line-height: 1.8;
    max-width: 100%
}

.hero-section h1 {
    font-size: 3rem
    font-weight: 900;
    margin-bottom: 20
    colour: #ffffff;

.hero-section p {
    font-size: big;
    color: #cccccc;
    max-width: 700px;
    margin: 0 auto;
}

Hint: there are at least 9 distinct errors. After fixing them, describe what the browser would render if you loaded the original broken version.

Exercise 3: Rewrite Using Shorthand and Longhand

Part A: Convert the following longhand CSS into the most concise shorthand form possible:

.box {
    margin-top: 10px;
    margin-right: 20px;
    margin-bottom: 30px;
    margin-left: 20px;
    padding-top: 15px;
    padding-right: 15px;
    padding-bottom: 15px;
    padding-left: 15px;
    border-width: 2px;
    border-style: dashed;
    border-color: #e94560;
    background-color: #f5f5f5;
    background-image: url("bg-pattern.png");
    background-repeat: repeat-x;
    background-position: top center;
}

Part B: Convert the following shorthand CSS into full longhand declarations:

.text {
    font: italic 700 18px/1.6 Georgia, serif;
    margin: 20px 40px;
    border: 3px dotted #333;
    transition: all 0.3s ease-in-out 0.1s;
}

Exercise 4: Comment a Real Stylesheet

Take any CSS file from a project you have worked on (or find a small open-source stylesheet). Add the following types of comments:

  • A table of contents at the top listing all major sections
  • Section divider comments for each logical group of styles
  • At least three inline comments explaining why a specific property value was chosen (not just what it does)
  • One TODO comment for a future improvement
  • One HACK comment explaining a browser-specific workaround

Share your commented stylesheet with a colleague and ask if the comments make the code easier to understand. Good comments explain the why, not the what -- the code itself tells you what it does.

ES
Edrees Salih
7 hours ago

We are still cooking the magic in the way!