CSS CSS Foundation & Core Concepts Understanding CSS Syntax

Three lessons into this CSS series and you’ve already covered a lot of ground. You know what CSS is and why it exists. You know how the browser actually reads and renders your CSS. And in the last lesson, you learned about the three ways to attach CSS to your HTML, inline, internal, and external.

Now comes the part where everything starts to feel real. Because knowing that CSS exists is one thing. But understanding exactly what you’re writing when you write CSS, that’s what separates someone who’s just pasting examples from someone who’s actually building things.

This lesson is about CSS syntax: the structure, the grammar, the rules behind every line of CSS code. By the end, you’ll be able to read a CSS rule you’ve never seen before and understand what every single character is doing. That’s a skill worth having.

Let’s get into it.


01What Is a CSS Rule? (And Why Developers Call It a “Ruleset”)

Every time you write CSS to style something, you’re writing a CSS rule. The more formal term is a CSS ruleset, and you’ll hear both used interchangeably.

A ruleset is just a block of instructions that says two things: who gets styled, and what those styles are.

Here’s the simplest possible example of a CSS rule:

h1 {
  color: tomato;
}

That’s it. One target (the h1 element), one style (text color set to tomato red). A complete CSS rule.

But there are actually five or six distinct parts in that tiny example, each playing a specific role. Learning to name them and understand what they do is exactly what makes you confident writing CSS from scratch, not just copying it.


02The Anatomy of a CSS Rule: Labeled and Explained

Let me show you a rule with two declarations and label every single part:

CSS Rule Anatomy
h1 {
color: tomato;
font-size: 32px;
}

Selector

Curly Braces

Property

Colon

Value

Semicolon

Now let’s go through each part in detail.

The Selector: Who Gets Styled?

The selector sits before the curly braces. It’s how you tell CSS which HTML element (or elements) you want to style.

In the example above, h1 is the selector. It means: find every <h1> tag on the page and apply the styles inside this block to all of them.

Selectors can be very simple, just a tag name like p or button. Or they can be more precise, targeting a specific class or ID. We’ll cover the most common types in depth later in this lesson.

If you’ve read our article on HTML tags, elements, and attributes, you’ll see the connection right away: CSS selectors often directly reference those HTML tag names. That link between HTML structure and CSS targeting is something you’ll use constantly.

The Declaration Block: Curly Braces and Everything Inside

Right after the selector, you open a pair of curly braces: { }.

Everything inside those braces is called the declaration block. This is where all the actual styling instructions live. The opening { starts the block, and the closing } ends it. The browser reads everything between them as styles that apply to the selected element.

Common beginner trap: Forgetting to close the curly brace. That one missing } can silently break every CSS rule that comes after it in your stylesheet, because the browser thinks all of it belongs to that unclosed block. We’ll revisit this in the mistakes section.

Declarations: A Property and a Value, Together

Inside the declaration block, you write declarations.

Each declaration has exactly two pieces: a property and a value, joined by a colon. Like this:

color: tomato;

color is the property. tomato is the value.

Think of it like a question and answer. The property asks: “What do I want to control?” The value answers: “Here’s exactly what it should be.”

One declaration, one thing being styled. You stack multiple declarations together to style multiple things at once. That’s the whole pattern.

The Colon: The Connector Between Property and Value

The colon : sits between the property name and its value. Its job is to separate the two, nothing more.

No space before it. A space after it is optional but conventional (and makes the code easier to read). Never use an equals sign here. That’s a JavaScript thing, not CSS.

The format is always: property: value. One colon, always in that position.

The Semicolon: Ending Each Declaration

After the value, you put a semicolon ;. This tells the browser that the current declaration is finished and the next one is about to begin.

You can have many declarations in one block. Without semicolons separating them, the browser wouldn’t know where one ends and the next begins.

Good habit to build: Technically, the very last declaration in a block doesn’t need a semicolon, and CSS will still work without it. But add it anyway, every time. When you come back later and add another declaration, you won’t accidentally break things because you forgot the semicolon on the line above.


03CSS Properties vs Values: Knowing the Difference

It’s worth spending a moment here, because I’ve seen quite a few beginners confuse properties and values, especially when reading CSS they didn’t write.

Here’s the clearest way I can put it:

A CSS property is a specific feature of an HTML element that you’re allowed to control. Its color, its size, its font, its spacing, its position.

A CSS value is the exact setting you’re assigning to that feature.

Properties are predefined by the CSS specification. You can’t invent them. color, font-size, background-color, margin, padding, border-radius… these are real properties that every browser understands. If you typo one, CSS won’t throw an error. It’ll just silently ignore it. (More on that shortly.)

Values depend entirely on the property. Each property has its own set of valid values. Here are five common property and value pairs:

Text Color
color: steelblue;

Accepts: color names, hex, rgb, hsl

Font Size
font-size: 18px;

Accepts: px, rem, em, %, vw

Background
background-color: #1e293b;

Accepts: any color value

Text Alignment
text-align: center;

Accepts: left, right, center, justify

Font Weight
font-weight: 700;

Accepts: normal, bold, 100–900

Corner Rounding
border-radius: 12px;

Accepts: px, %, rem values

You’ll naturally pick up which values are valid for each property as you use them. You don’t need to memorize this. It becomes instinct with practice.


04Multiple Declarations in One Block

In real CSS, you’ll almost never write a rule with just one declaration. You’ll style several things at once inside one block. Here’s how that looks:

<!DOCTYPE html>
<html>
<head>
  <style>
    p {
      color: #cbd5e1;
      font-size: 17px;
      line-height: 1.75;
      font-family: Georgia, serif;
      background-color: #1e293b;
      padding: 20px;
      border-radius: 10px;
    }
  </style>
</head>
<body>
  <p>This paragraph has seven CSS declarations applied to it, all inside one declaration block.</p>
</body>
</html>

Each declaration is on its own line (purely for readability, CSS doesn’t care about whitespace), ends with a semicolon, and they’re all wrapped inside one pair of curly braces. This is the pattern you’ll follow in every CSS file you ever write.

Why is each declaration on its own line? Technically, you could write it all on one line: p { color: #cbd5e1; font-size: 17px; } and it would work fine. But putting each declaration on its own line is standard practice. It’s much easier to read, edit, and debug. You’ll see this in every real stylesheet.


05CSS Selector Types: The Three You’ll Use Most

Selectors are one of the most important parts of writing CSS. They determine which elements your styles actually reach. There are many types of CSS selectors, and we’ll go deeper on them in dedicated future lessons. For now, let’s focus on the three you’ll use constantly:

Element Selector
p {
color: #818cf8;
font-weight: 600;
}
Result

Every <p> on the page gets this style.

Class Selector
.highlight {
color: #f472b6;
font-weight: 700;
}
Result
This has class=”highlight”
This paragraph is not affected.
ID Selector
#page-title {
color: #22d3ee;
font-size: 28px;
}
Result

Hello, World

Element Selectors (Also Called Type Selectors)

The simplest kind. You just write the tag name, and it targets every element of that type on the page.

h2 {
  font-size: 28px;
}

p {
  color: #cbd5e1;
  line-height: 1.7;
}

button {
  background-color: #6366f1;
  color: white;
}

Every <h2> gets that font size. Every <p> gets that color and line height. Every <button> gets that background. Element selectors are perfect for setting baseline styles across your whole page.

If you’ve been reading through our HTML lessons, you already know how semantic HTML elements help give your page meaningful structure. CSS element selectors let you tap into that structure directly and style it.

Class Selectors (The One You’ll Reach For Most)

Class selectors target elements that have a specific class attribute in their HTML. You define the class in HTML, then reference it in CSS with a dot . before the name.

<!DOCTYPE html>
<html>
<head>
  <style>
    .intro-text {
      font-size: 20px;
      font-weight: 600;
      color: #6366f1;
    }
  </style>
</head>
<body>
  <p class="intro-text">This paragraph has the intro-text class.</p>
  <p>This one does not, so it's unstyled by that rule.</p>
</body>
</html>

The dot before the name is what makes it a class selector. No dot means you’re targeting an HTML element by tag name. With a dot, you’re targeting by class. That distinction is important.

Class selectors are flexible because the same class can be applied to multiple elements, and one element can have multiple classes. This makes them the go-to choice for building reusable, modular styles.

ID Selectors (Powerful, but Use Them Selectively)

ID selectors target a single element by its id attribute, using a hash # before the name.

<!DOCTYPE html>
<html>
<head>
  <style>
    #main-heading {
      color: #ec4899;
      font-size: 48px;
      letter-spacing: -1.5px;
    }
  </style>
</head>
<body>
  <h1 id="main-heading">CSS Syntax Is Clicking</h1>
</body>
</html>

IDs are meant to be unique on a page, meaning one element per ID. Because of that, ID selectors are generally used less often in modern CSS than class selectors. When you’re building styles you’ll reuse across multiple elements, reach for a class. IDs work well for targeting one specific, unique element.


06Grouping Selectors: Apply One Block to Multiple Targets

Here’s a technique that saves a lot of repetitive writing. You can apply the same styles to multiple selectors at once by separating them with a comma.

/* Instead of writing this three times... */
h1, h2, h3 {
  font-family: 'Space Grotesk', sans-serif;
  color: #ffffff;
  line-height: 1.3;
}

That’s equivalent to writing three separate rules with identical declaration blocks. The grouped version is shorter, cleaner, and easier to update when you need to change something.

Each selector in the group is completely independent. h1, h2, h3 just means: “apply this to h1, AND h2, AND h3.” They don’t need to be related in the HTML. The comma is simply a way to list multiple targets for one set of styles.

<!DOCTYPE html>
<html>
<head>
  <style>
    h1, h2, h3 {
      color: #ffffff;
      line-height: 1.3;
      margin-bottom: 12px;
    }

    .btn-primary, .btn-secondary {
      padding: 10px 20px;
      border-radius: 8px;
      font-weight: 600;
      cursor: pointer;
    }

    .btn-primary {
      background-color: #6366f1;
      color: #ffffff;
    }

    .btn-secondary {
      background-color: transparent;
      color: #6366f1;
      border: 1px solid #6366f1;
    }
  </style>
</head>
<body>
  <h1>Grouped Heading Styles</h1>
  <h2>This h2 shares the same base styles</h2>
  <h3>So does this h3</h3>

  <button class="btn-primary">Primary Button</button>
  <button class="btn-secondary">Secondary Button</button>
</body>
</html>

Notice how in the example above, the two button classes share base styles (padding, border-radius, font-weight) through grouping, but then each has its own additional rule that gives it a unique look. This is a very common real-world pattern.


07How to Read a CSS Rule Like You Wrote It Yourself

Here’s a technique I still use when I look at an unfamiliar stylesheet for the first time: read the CSS rule out loud in plain English.

Seriously. Try it.

Take this rule:

.card {
  background-color: #1e293b;
  border-radius: 16px;
  padding: 28px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
}

Read it like this: “Find every element with the class card. Give it a dark navy background. Round its corners by 16 pixels. Add 28 pixels of internal spacing on all sides. Apply a soft dark shadow beneath it.”

Every CSS rule translates directly into plain instructions. Selector is the “who.” Each declaration is a separate “what” and “how.” Once you start reading CSS this way, new rules become immediately clear, even if you’ve never seen those specific properties before.

When you’re debugging your own styles later, this habit also helps you spot the issue faster because you’re forced to think through what each line is actually supposed to be doing.


08Common CSS Syntax Mistakes That Beginners Run Into

Understanding the right syntax matters, but so does knowing what goes wrong. CSS doesn’t throw error messages the way some other languages do. It mostly just ignores what it doesn’t understand, which can be maddening when your styles refuse to apply and you can’t figure out why.

Here are the four most common css syntax mistakes, with examples of what wrong and correct looks like side by side.

Mistake 1: Skipping the Semicolon

This is the most frequent one. Forget a semicolon, and the browser may discard that declaration and sometimes the one right after it too.

/* Wrong: missing semicolon after color */
p {
  color: white
  font-size: 16px;
  line-height: 1.6;
}

/* Correct */
p {
  color: white;
  font-size: 16px;
  line-height: 1.6;
}

Mistake 2: Typos in Property Names

CSS silently ignores properties it doesn’t recognize. No warning, no error, nothing. Your style just doesn’t apply and you’re left wondering why.

/* Wrong: 'colour' and 'fontsize' are not valid CSS properties */
p {
  colour: red;
  fontsize: 16px;
}

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

A quick way to catch this: if a property name isn’t turning a different color in your code editor, it’s probably wrong.

Mistake 3: A Missing Closing Curly Brace

Every opening { needs a closing }. If you forget the closing brace, the browser treats everything that follows as part of that unclosed block, and all your CSS below it stops working.

/* Wrong: h1 block is never closed */
h1 {
  color: white;
  font-size: 40px;

/* The browser reads h2's styles as part of h1's block */
h2 {
  font-size: 28px;
}

/* Correct */
h1 {
  color: white;
  font-size: 40px;
}

h2 {
  font-size: 28px;
}

Mistake 4: Using the Wrong Selector Prefix

No dot before a class name means CSS treats it as a tag name. No hash before an ID means the same thing. Since there’s no HTML element called card or btn, the rule just applies to nothing.

/* Wrong: targets a fictional HTML tag called "card" */
card {
  background: #1e293b;
}

/* Wrong: targets a fictional HTML tag called "btn" */
btn {
  color: white;
}

/* Correct: dot = class, hash = ID */
.card {
  background: #1e293b;
}

#btn-submit {
  color: white;
}

09Putting It All Together: A Real CSS Ruleset Structure in Action

Here’s a complete example that uses everything covered in this lesson. It’s a styled profile card built with proper CSS ruleset structure, multiple selector types, grouped selectors, and multiple declarations in each block.

<!DOCTYPE html>
<html>
<head>
  <style>
    /* Element selector: base page styles */
    body {
      background-color: #141d34;
      font-family: system-ui, sans-serif;
      display: flex;
      justify-content: center;
      padding: 60px 20px;
      margin: 0;
    }

    /* Class selector: the card container */
    .profile-card {
      background-color: #1e293b;
      border-radius: 20px;
      padding: 36px;
      max-width: 380px;
      width: 100%;
      border: 1px solid rgba(255, 255, 255, 0.08);
    }

    /* Class selector: the name heading */
    .profile-name {
      color: #ffffff;
      font-size: 26px;
      font-weight: 700;
      margin: 0 0 6px;
      line-height: 1.2;
    }

    /* ID selector: the accent symbol */
    #name-accent {
      color: #6366f1;
    }

    /* Class selector: the role / subtitle */
    .profile-role {
      color: #6366f1;
      font-size: 14px;
      font-weight: 600;
      margin: 0 0 20px;
      letter-spacing: 0.04em;
    }

    /* Class selector: the bio text */
    .profile-bio {
      color: #94a3b8;
      font-size: 15px;
      line-height: 1.75;
      margin: 0 0 24px;
    }

    /* Grouped selectors: both stat items share base styles */
    .stat-label, .stat-value {
      font-family: system-ui, sans-serif;
      display: block;
    }

    .stat-label {
      color: #475569;
      font-size: 12px;
      font-weight: 700;
      letter-spacing: 0.1em;
      text-transform: uppercase;
    }

    .stat-value {
      color: #ffffff;
      font-size: 22px;
      font-weight: 800;
    }
  </style>
</head>
<body>
  <div class="profile-card">
    <h2 class="profile-name">Daniyal Ahmed <span id="name-accent">✦</span></h2>
    <p class="profile-role">Frontend Developer</p>
    <p class="profile-bio">
      Building things on the web, one lesson at a time.
      Currently deep in CSS fundamentals.
    </p>
    <span class="stat-label">Lessons Published</span>
    <span class="stat-value">17</span>
  </div>
</body>
</html>

And here’s a preview of what that card looks like rendered:

Daniyal Ahmed

Building things on the web, one lesson at a time. Currently deep in CSS fundamentals, writing clean and confident code.

Frontend Developer

Look through that stylesheet. You can name every part now. You know what the selectors are, what declaration blocks contain, and what each property and value does. That’s real understanding, not just copying.


10CSS Syntax Quick Reference

Here’s a compact reference card for everything we covered. Bookmark it, screenshot it, whatever helps you come back to it fast:

CSS Rule: At a Glance
h1 / .class / #id
Selector
Targets the HTML element(s) you want to style. Sits before the curly brace.
{ … }
Declaration Block
The curly braces that wrap all the style instructions for that selector.
color
Property
The specific feature you want to control. Predefined by CSS. Always comes first in a declaration.
:
Colon
Separates the property from its value. Always written between the two, never an equals sign.
tomato
Value
The exact setting for the property. Valid values depend on the property being used.
;
Semicolon
Ends each declaration. Required after every property:value pair (always include it, even on the last one).
property: value;
Declaration
A single property and value pair combined. One declaration = one thing being styled.

11What’s Coming Next in This Series

Now that you have a solid grip on how CSS is written, the next lesson is about CSS comments: how to annotate your stylesheets, leave notes for your future self (or your team), and keep your CSS organized as it grows. It’s a quick but genuinely useful lesson.

After that, we’ll get into the CSS cascade, which is one of the most misunderstood topics in CSS, and also one of the most important. If you’ve ever written a style and wondered why it wasn’t applying, that lesson is going to answer your question completely and clearly.

You’re building solid fundamentals. Keep going. Every concept from here builds directly on what you just learned.

Understanding CSS Syntax

Choose a difficulty to load your challenge

Loading challenge…

Ready to Practice?

Select a difficulty level above to load your challenge.

Easy

1
Live Preview
Great Work!