How CSS Works: A Beginner’s Guide

How CSS Works: A Beginner’s Guide

You wrote a few rules. You saved the file. You refreshed the browser — and somehow a plain HTML document turned into a designed page. That moment is the whole point of CSS, but the mechanism behind it is often a mystery for beginners.

CSS is not a script that runs line by line. It is a stylesheet: a set of rules that the browser reads, matches against the document, and turns into pixels. This guide walks through exactly how that happens — from the anatomy of a rule to the cascade that resolves conflicts, to the box model that gives every element its size, to the rendering pipeline that produces what you finally see.

In one sentence: CSS works by matching selectors to HTML elements, collecting every declaration that applies, resolving conflicts through the cascade and specificity, and then feeding the winning values into the browser’s layout and paint pipeline.

The Short Answer

Every time the browser renders a page, it does the same thing with CSS:

Parse HTML → DOM
→
Parse CSS → CSSOM
→
Match selectors
→
Cascade & specificity
→
Layout
→
Paint & composite

Each step depends on the one before it. If the HTML never parses, CSS has nothing to match. If the cascade cannot decide a winner, the browser falls back to a default. If layout fails, nothing gets painted.

Understanding this pipeline is what separates beginners who fight CSS from developers who work with it. When a rule “does not work,” the answer is almost always hiding somewhere in this flow.

The mental model

Think of CSS as a voting system. Every declaration is a vote for how an element should look. The cascade counts the votes, applies tie-breakers, and delivers a single winning value per property. No ambiguity survives the process.

Anatomy of a CSS Rule

Before anything else, you need to be able to read a CSS rule. Every rule has the same four parts, in the same order:

.card { color: #0891b2; }
selector declaration block property value end of rule

The four parts

Selector
Describes which elements the rule targets. In the example, .card targets every element with the class card.
Declaration block
Everything between the curly braces. It contains one or more declarations.
Property
The aspect of the element being changed, such as color, font-size, or margin. Properties are predefined by the CSS specification.
Value
What the property is being set to, such as #0891b2, 1.5rem, or auto.

Each declaration ends with a semicolon, and the whole block is wrapped in curly braces. A rule can contain as many declarations as you need:

.card {
    background: #ffffff;
    border-radius: 12px;
    padding: 24px;
    box-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
}

Read it left to right: for every element with the class card, set the background to white, round the corners to 12 pixels, add 24 pixels of internal padding, and add a soft shadow.

The semicolon matters

A missing semicolon is one of the most common beginner mistakes. The browser will silently discard the entire declaration — and often the next one too — because it cannot tell where one property ends and the next begins.

How CSS Reaches the Page

For CSS to do anything, it has to reach the HTML document. There are three ways to deliver it, and each has different implications.

1. External stylesheet (recommended)

A separate .css file linked from the HTML head:

<head>
    <link rel="stylesheet" href="styles.css">
</head>

This is the standard approach. The CSS file is downloaded once, cached by the browser, and reused across every page on the site. It keeps presentation separate from structure and is by far the easiest to maintain.

2. Internal style block

Rules written directly inside a <style> element in the HTML head:

<head>
    <style>
        .card { border-radius: 12px; }
    </style>
</head>

This keeps everything in one file, which is convenient for small demos or pages with unique styling. It does not scale well because the styles cannot be shared or cached across pages.

3. Inline styles (avoid)

Rules applied directly to an element with the style attribute:

<div class="card" style="border-radius: 12px;">
    Content
</div>

Inline styles have the highest specificity short of !important, which makes them extremely hard to override. They cannot be reused, cannot be cached, and mix presentation back into the markup. Use them only for values that must be computed at runtime.

Delivery order matters

When multiple stylesheets or style blocks apply, the browser honors them in document order. An external stylesheet linked after an internal style block overrides it at equal specificity. Getting the order wrong is a common source of “why is this not applying?”

How Selectors Match

Selectors are the pattern-matching engine of CSS. The browser reads every selector and tests it against every element in the document. When a selector matches, the declarations inside its block become candidates for that element.

The main selector types

Common selector patterns
Selector Example Matches
Type p Every <p> element
Class .card Every element with class="card"
ID #hero The single element with id="hero"
Attribute [type="email"] Inputs with a matching type attribute
Descendant nav a Links anywhere inside a <nav>
Child ul > li List items that are direct children of a list
Pseudo-class a:hover Links while the pointer is over them
Pseudo-element p::first-line The first line of every paragraph

Selectors combine

Selectors are rarely used alone. They can be chained, combined with commas, or nested with combinators:

/* Comma: two separate rules */
h1, h2 { color: #0f172a; }

/* Chained: element that also has the class */
button.primary { background: #0891b2; }

/* Descendant combinator */
.card a { text-decoration: none; }

/* Child combinator */
.card > a { font-weight: 600; }

/* Adjacent sibling */
h2 + p { margin-top: 0; }

Each combinator expresses a different structural relationship. The descendant combinator ( ) matches at any depth. The child combinator (>) matches only direct children. Understanding the difference helps you write selectors that are both precise and resilient.

Match from right to left

Browsers evaluate selectors from right to left. For .card a, the browser first finds every <a>, then checks whether any ancestor has the class card. This is why very deep descendant chains are slower — the browser has to walk up the tree for each candidate.

The Cascade: Who Wins

The “C” in CSS stands for cascading. When more than one rule sets the same property on the same element, the cascade decides which declaration wins. It considers four factors, in this order:

  1. Origin and importance — user agent, user, and author styles, plus any !important flags.
  2. Specificity — a score based on the selectors involved.
  3. Source order — the position of the rule in the stylesheet.
  4. Inline styles — style attributes beat external rules at equal importance.

Origin and importance

There are three sources of CSS, and the cascade ranks them:

  • User agent styles — the browser’s built-in defaults.
  • User styles — custom styles set by the reader, often for accessibility.
  • Author styles — everything you write.

Author styles override user agent styles by default, which is why your rules beat the browser’s defaults. The exception is !important, which flips the order — important user agent styles beat important author styles, and important user styles beat everything. This is intentional: it lets users override website styling for accessibility reasons.

Avoid !important

!important should be a last resort. Once it is in place, it can only be overridden by another !important with equal or higher specificity, which leads to escalating complexity. If you find yourself reaching for it often, the real problem is probably specificity in your selectors.

Specificity: How Strong Is a Selector

Specificity is a score assigned to a selector. When two rules of the same origin and importance set the same property, the one with the higher specificity wins.

The score is usually described as three numbers, written like (a, b, c):

  • a — the number of ID selectors.
  • b — the number of class, attribute, and pseudo-class selectors.
  • c — the number of type and pseudo-element selectors.

Compare the scores from left to right. A single ID beats any number of classes. A single class beats any number of type selectors. Only when all three are equal does source order decide.

p
0, 0, 1
.card
0, 1, 0
.card p
0, 1, 1
nav .card a:hover
0, 2, 2
#hero
1, 0, 0
style=”…”
inline

A worked example

Suppose two rules both set the color of a paragraph:

p { color: #0f172a; }
.card p { color: #0891b2; }

The first selector has specificity (0, 0, 1). The second has (0, 1, 1). Because the second is more specific, the paragraph inside a .card becomes teal — regardless of which rule appears first in the file.

Keep specificity low

Aim for single-class selectors wherever possible. They have a uniform, predictable specificity, which means conflicts are resolved by source order rather than by an escalating arms race. Frameworks like BEM and utility systems exist largely to keep specificity flat.

The !important exception

A declaration marked with !important outranks all normal declarations of the same origin, regardless of specificity. It sits at the top of the cascade for that origin. Use it only to override third-party CSS you cannot edit, or as a deliberate escape hatch — never as a first tool.

Inheritance: What Passes Down

Not every property has to be set explicitly on every element. Some properties inherit — they take their value from the parent element unless overridden.

The rule is intuitive: properties that describe text inherit, and properties that describe layout do not.

Inherited

Text and typography

color, font-family, font-size, font-weight, line-height, letter-spacing, text-align.

These flow from parent to child automatically.

Not inherited

Layout and box

margin, padding, border, width, height, display, position.

These apply only to the element they are set on.

This is why setting font-family on body styles the whole page: every text node inside inherits it. And it is why setting margin on body affects only body itself, not the elements inside it.

Controlling inheritance

You can explicitly control inheritance with three keywords:

.btn {
    border: inherit;      /* take the parent's border */
    color: initial;       /* reset to the CSS default */
    margin: unset;        /* inherit if inherited, else initial */
}

These keywords are especially useful when you want to reset an element’s styling without losing inherited context.

The universal reset

Setting * { box-sizing: border-box; } is a common reset. Note that * does not break inheritance — it just applies box-sizing to every element individually, and because box-sizing is not inherited, this is the correct approach.

The Box Model: How Size Is Computed

Every element the browser renders is a rectangular box. That box is made of four nested layers, and understanding them is essential to controlling layout.

Margin
Border
Padding
Content
Margin Space outside the border. Pushes other elements away.
Border The visible edge of the box. Sits between padding and margin.
Padding Space inside the border. Pushes content away from the edge.
Content The actual text, image, or child element.

Sizing: content-box vs border-box

By default, width and height refer only to the content area. Padding and border are added on top, which makes elements wider than you might expect:

.box {
    width: 300px;
    padding: 20px;
    border: 5px solid;
    /* Total rendered width: 300 + 40 + 10 = 350px */
}

Setting box-sizing: border-box changes this. The declared width now includes padding and border, so the element is exactly as wide as you specified:

* { box-sizing: border-box; }

.box {
    width: 300px;
    padding: 20px;
    border: 5px solid;
    /* Total rendered width: 300px */
}

Almost every modern project sets border-box globally, because it makes layout math dramatically simpler.

Debug in DevTools

Every browser’s developer tools show a colored diagram of an element’s box model. Inspecting this panel is the fastest way to understand why an element is bigger or smaller than you expected.

The Rendering Pipeline

Once the cascade has produced a final set of values for every element, the browser goes to work turning that into pixels. This happens in four stages.

Style calculation
→
Layout
→
Paint
→
Composite

1. Style calculation

The browser takes the DOM tree from HTML and the CSSOM tree from CSS, walks them together, and computes the final style for every element. This is where the cascade, specificity, and inheritance all finish their work. The result is a new tree — sometimes called the render tree — where each node carries its resolved styles.

2. Layout

In the layout phase, the browser calculates the geometry of every box. It determines the width, height, and position of each element based on its styles, its content, and its siblings. This is where the box model, Flexbox, Grid, and normal flow all take effect.

Layout is expensive. Changing properties that trigger layout — width, height, margin, font-size, display — forces the browser to redo this work.

3. Paint

Once the geometry is known, the browser paints pixels. It fills in backgrounds, draws borders and text, renders images, and applies shadows and gradients. The result is a series of painted layers, often on the GPU.

Properties that trigger only paint — color, background-color, box-shadow — are cheaper than layout, but still not free.

4. Composite

Finally, the browser combines all the painted layers onto the screen. Some properties, such as transform and opacity, can be handled entirely in this phase. That is why animating with transform and opacity is far smoother than animating with top and left.

Animate the cheap properties

For smooth animations, stick to transform and opacity. These skip layout and paint and can often run entirely on the GPU. Anything else — animating width, height, or top — will trigger layout on every frame and cause jank.

How Layout Actually Works

Layout is where most of the complexity of CSS lives. Elements are positioned by one of several systems, and the system in use is determined by the display property and related rules.

Normal flow

By default, elements follow normal flow. Block elements stack vertically, each taking the full width of their parent. Inline elements flow with the text, wrapping as needed. This is the baseline layout system, and it handles simple documents perfectly.

Flexbox

Flexbox lays out items in a single row or column, distributing space and aligning along two axes. It is ideal for navigation bars, toolbars, card rows, and any case where you want items to size themselves within a container.

.nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}

Grid

Grid lays out items in two dimensions simultaneously — rows and columns — with explicit control over placement and sizing. It is ideal for full-page layouts, dashboards, and any design where both dimensions matter at once.

.layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    grid-template-rows: auto 1fr auto;
    gap: 24px;
    min-height: 100vh;
}

Positioning

For cases that do not fit flow, Flexbox, or Grid, the position property takes an element out of the normal flow and places it manually. Values include relative, absolute, fixed, and sticky.

Prefer Flexbox and Grid

Modern layout should reach for Flexbox and Grid first. Positioning is powerful but removes elements from the flow, which causes overlap, layout fragility, and accessibility issues. Use it sparingly, for overlays and floating UI only.

How Responsive Design Fits In

The browser does not apply CSS once. It re-evaluates certain rules whenever the environment changes — window size, device orientation, user preferences. The mechanism is the media query.

.card {
    padding: 16px;
}

@media (min-width: 768px) {
    .card {
        padding: 32px;
    }
}

The rule inside the media query applies only when the viewport is at least 768 pixels wide. On smaller screens, the base rule applies. This is the same cascade — media queries just add or remove candidates based on the current environment.

Relative units

Responsive design also depends on units that scale with the environment rather than fixed pixel values:

  • rem — relative to the root font size. Scales with user settings.
  • em — relative to the current element’s font size.
  • % — relative to the parent’s size.
  • vw and vh — relative to the viewport.
  • ch — relative to the width of the “0” character in the current font.

Using rem for typography and spacing means everything scales gracefully with the user’s preferred text size — a critical accessibility win.

Mobile-first ordering

Write your base styles for the smallest screen, then add media queries with min-width for larger sizes. This keeps the default styling simple and ensures the mobile experience is always the most optimized.

Custom Properties: Values That Flow

CSS custom properties — often called CSS variables — let you store a value under a name and reuse it anywhere in the stylesheet.

:root {
    --color-primary: #0891b2;
    --color-accent: #7c3aed;
    --space-md: 1rem;
    --radius: 12px;
}

.btn {
    background: var(--color-primary);
    padding: var(--space-md) calc(var(--space-md) * 1.5);
    border-radius: var(--radius);
}

Unlike preprocessor variables, CSS custom properties are live. They inherit, they can be changed at runtime, and they can be scoped to any element or selector.

Why they matter

  • Theming — swap a whole color scheme by redefining a few variables.
  • Consistency — one definition, many uses, no drift.
  • Responsive values — change a variable inside a media query and every rule that uses it updates.
  • JavaScript integration — read and set variables from scripts without touching individual properties.
.dark-theme {
    --color-primary: #22d3ee;
    --color-accent: #a855f7;
}

Because custom properties inherit, adding the dark-theme class to body instantly re-themes every descendant.

Not the same as Sass variables

Sass variables are resolved at compile time and disappear from the output. CSS custom properties remain in the stylesheet and are evaluated by the browser. That makes them dynamic — the browser can change them at runtime, and CSS can respond to those changes.

Why Your CSS Is Not Applying

This is the question every beginner asks. Almost every instance falls into one of a handful of categories.

1. Specificity conflict

Another rule with a higher specificity is overriding yours. Check the DevTools styles panel — the winning rule is shown, and overridden declarations are crossed out.

2. Typo or invalid value

Browsers silently ignore invalid declarations. A misspelled property name, colour instead of color, or an invalid value such as font-size: 14 without a unit, will simply be dropped.

3. Missing semicolon

If a declaration is missing its semicolon, the browser may merge it with the next one, causing both to fail. This is one of the most common typos.

4. Selector does not match

The element may not actually have the class or ID the selector is targeting. Typos in class names are frequent, and CSS fails silently when a selector matches nothing.

5. Element not in the DOM yet

If styles are added dynamically through JavaScript before the element exists, the rules will not apply. Wait for the element to be present before styling it.

Use the DevTools styles panel

Right-click any element and choose “Inspect.” The styles panel shows every rule that matched the element, in order of specificity, with overridden declarations struck through. This is the single most useful debugging tool in CSS.

Common Myths About How CSS Works

  • “CSS runs top to bottom.” CSS is not a script. The browser reads it in order, but the cascade decides which rules win based on origin, importance, and specificity — not on which line came first.
  • “Later rules always override earlier ones.” Source order only matters when specificity is equal. A later rule with lower specificity loses to an earlier, more specific one.
  • “The browser applies CSS once.” The browser re-runs style calculation, layout, and paint whenever the DOM, styles, or environment change. This is what makes responsive and interactive pages possible.
  • “You can style HTML with HTML.” Old presentational tags like <font> are deprecated and cannot build modern layouts. Presentation belongs in CSS.
  • “!important is a fix.” It is not. It is a last resort that makes the cascade harder to reason about and usually signals a specificity problem upstream.
  • “CSS is deterministic.” It is — but the determinism comes from the cascade rules, not from source order. Two identical rules produce the same result every time; two conflicting ones are resolved by a fixed set of tie-breakers.
A useful rule of thumb

When a rule does not seem to apply, do not guess. Inspect the element and read the cascade. Every mystery in CSS has a defined answer — it is just a matter of finding the rule that won.

Best Practices

These habits keep your CSS predictable as the project grows.

🧱

Start with a reset

Normalize or reset margin, padding, and box-sizing at the top of the stylesheet.

🎯

Keep specificity low

Prefer single classes. Avoid IDs for styling, and avoid deep descendant chains.

🏷️

Name by purpose

.card and .alert survive redesigns. .red-box does not.

📐

Use border-box everywhere

* { box-sizing: border-box; } removes an entire class of sizing bugs.

📏

Prefer relative units

rem, em, %, and ch scale with user settings.

⚡

Animate cheaply

Use transform and opacity. Avoid animating layout properties.

🎨

Use custom properties

Define colors, spacing, and radii once. Reference them everywhere.

📱

Design mobile-first

Write base styles for small screens and enhance upward with min-width.

✅

Validate your CSS

The W3C CSS Validator catches errors browsers silently ignore.

The one-line summary

CSS works by matching, cascading, laying out, and painting. Master those four steps, and every “why is this not working?” becomes a question you can answer.

Frequently Asked Questions

1. How does CSS work in simple terms?

CSS works by matching selectors to elements in the HTML document. For each match, the browser collects the declarations, resolves conflicts using the cascade and specificity, and then applies the winning values to build the page’s visual tree. The browser then lays out and paints that tree to produce what you see on screen.

2. What is the cascade in CSS?

The cascade is the algorithm that decides which declaration wins when multiple rules set the same property on the same element. It considers origin (user agent, author, user), importance, specificity, and source order. Later and more specific declarations override earlier or less specific ones.

3. What is specificity in CSS?

Specificity is a score assigned to each selector that determines how strongly it competes in the cascade. Inline styles beat IDs, IDs beat classes and attributes, and classes beat element selectors. When specificity is equal, source order decides.

4. How does the browser apply CSS to a page?

The browser parses HTML into a DOM tree and CSS into a CSSOM tree. It combines them into a render tree, computes the final styles for each element, lays out each box with its size and position, paints the pixels, and composites them onto the screen. This happens every time the page changes.

5. What is the box model in CSS?

Every element is rendered as a rectangular box made of four layers: the content area, padding, border, and margin. Together, they determine the element’s total size and how much space it takes up in the layout.

6. What is inheritance in CSS?

Inheritance is how some CSS properties pass down from a parent element to its children automatically. Text-related properties such as color, font-family, and line-height inherit. Layout properties like margin, padding, and border do not.

7. Why do some CSS rules not apply?

The most common reasons are specificity conflicts, an invalid property value, a typo in the selector or property name, a missing semicolon on the previous declaration, or a parent element with a rule that overrides the child. The browser’s DevTools show which rules won and why.

8. Does CSS run in a specific order?

Yes. The browser parses and applies CSS in a defined order: first user agent styles, then user styles, then author styles. Within each origin, importance and specificity determine the winner. Media queries are evaluated based on the current environment.

9. What does “cascading” actually mean?

“Cascading” describes how multiple stylesheets and rules flow together into a single set of winning declarations for each element. It is the mechanism that allows defaults, frameworks, and your own styles to coexist without stepping on each other blindly.

10. How does CSS handle responsive layouts?

Through media queries, relative units, and flexible layout systems like Flexbox and Grid. Media queries apply different rules at different viewport sizes. Relative units adapt to user settings and screen size. Flexbox and Grid reflow content automatically within whatever space is available.

11. What are CSS custom properties?

CSS custom properties, also called CSS variables, are values stored under a name that begins with two dashes, such as --color-primary. They can be read anywhere in the stylesheet with the var() function. They inherit, they update at runtime, and they make themes and design tokens easier to manage.

12. How long does it take to learn how CSS works?

The basics of selectors, the box model, and colors take a few weeks. The cascade, specificity, and layout with Flexbox and Grid take a few months of regular practice to feel natural. Truly mastering CSS is an ongoing process, because the language continues to grow.

Key Takeaways

  • A CSS rule is a selector plus a block of property-value declarations.
  • CSS reaches the page through external files, internal blocks, or inline styles.
  • The cascade decides which declaration wins based on origin, importance, specificity, and source order.
  • Specificity ranks IDs above classes, and classes above element selectors.
  • Some properties inherit; most layout properties do not.
  • Every element is a box made of content, padding, border, and margin.
  • The browser computes styles, lays out boxes, paints pixels, and composites layers.
  • Flexbox and Grid are the modern layout systems; positioning is for special cases.
  • Media queries and relative units make layouts responsive.
  • Custom properties store reusable values and make theming easy.
  • Most “CSS is not working” problems are specificity conflicts or typos.
  • DevTools show exactly which rule won — always inspect before guessing.

What to Learn Next

Now that you understand how CSS works under the hood, the natural next step is to go deeper on the parts that matter most. Start with CSS Selectors Explained and The CSS Box Model.

From there, explore CSS Specificity and the Cascade, Inheritance in CSS, and CSS Units Explained. When you are ready to build layouts, read CSS Flexbox Guide and CSS Grid Guide, then move on to Responsive Web Design.

If you want to understand how CSS fits with the rest of the browser, read How Web Browsers Work and HTML vs CSS.

Practice Challenge

The fastest way to internalize how CSS works is to build a page and then deliberately break it, so you can see the cascade in action. This exercise takes about twenty minutes.

  1. Create index.html and styles.css in the same folder.
  2. Write HTML with a heading, a paragraph, a list, and a button. Give each element a class.
  3. Link the stylesheet from the HTML head using <link rel="stylesheet">.
  4. Add a global reset at the top of the stylesheet: * { box-sizing: border-box; margin: 0; padding: 0; }
  5. Define two custom properties in :root — one for a primary color and one for spacing.
  6. Style the heading with the primary color, using var() to reference the custom property.
  7. Give the button a padding that uses the spacing variable multiplied by two.
  8. Now deliberately introduce a specificity conflict: add a rule for h1 and another for .page-title, both setting different colors. Confirm the class wins.
  9. Open DevTools, inspect the heading, and confirm the losing rule is crossed out.
  10. Add a media query that changes the heading size at min-width: 768px, and resize the window to see it switch.
  11. Finally, set border-box and then remove it, observing how the button’s total size changes.

When you finish, you will have seen the cascade, specificity, inheritance, the box model, custom properties, and media queries all working together in your own code. Once you have felt those mechanisms in action, CSS stops being a list of properties to memorize and becomes a system you can reason about.

Inar Learn
Inar Learnhttps://inarlearn.com
Inar Learn is an innovative online learning platform offering high-quality courses, tutorials, and resources to help learners gain practical skills and grow their knowledge.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here