CSS Guide: Selectors, Flexbox, Grid, Typography, and Color

Published Updated

CSS is the language browsers use to style web documents. HTML supplies the page structure, then CSS controls presentation through colors, type, spacing, borders, and layout. The same CSS rules work whether you write a plain stylesheet, use a component framework, or generate utility classes with a tool such as Tailwind.

A useful CSS foundation has three parts. Selectors choose the elements to style, layout rules arrange their boxes, and typography plus color shape the readable surface. The cascade connects those parts by deciding which declaration applies when several rules target the same element.

CSS at a Glance

CategoryWhat it coversStart here if
CSS SelectorsType, class, and id selectors, combinators, pseudo-classes, and specificityYour rule is written correctly and the element still refuses to change
CSS LayoutNormal flow, flexbox, grid, and coordinate-based positioningYour boxes are styled but sitting in the wrong places
CSS Typography and ColorColors, units, fonts, text, custom properties, and shadowsThe layout works and the page is still tiring to read

What CSS Actually Does

Every ordinary CSS rule has the same two halves. A selector picks elements out of the document, and a declaration block sets property values on whatever it picked. Most of any stylesheet you read is repetitions of that one shape, alongside at-rules such as @media, @layer, and @font-face, which carry instructions to the browser rather than styling an element directly.

The browser applies those values to a box. Every element the browser renders is a rectangle with four layers, working outward from the text: the content itself, the padding around it, the border around that, and the margin holding neighbours away. Almost every spacing problem you hit early on comes down to changing the wrong one of those four.

Those boxes then need arranging, and that is a separate job from styling them. A card can have perfect padding and still land in the wrong column. Presentation and position are controlled by different property families, which is why the guides below split them apart rather than teaching one long list of properties.

Where CSS Came From

Early web pages were unstyled HTML. Håkon Wium Lie proposed CSS in 1994 so presentation could live in a stylesheet instead of being written into every tag. The first CSS specification followed in 1996.

The language is still that stylesheet. Selectors pick elements and declarations set their properties. The cascade decides which value wins when several rules match. Flexbox, grid, and custom properties are later additions on that same model.

What CSS Code Looks Like

.topic-card {
  padding: 1rem;
  border: 1px solid #4a5568;
  border-radius: 6px;
}

The Cascade Decides Every Conflict

Here is the rule the rest of CSS assumes you already know. Multiple rules are allowed to target the same element, and none of them fails. The browser collects every declaration that matches, then decides which value survives for each property. That decision process is the cascade, and it runs in a fixed order.

Origin and importance come first, so your stylesheet beats the browser default and an !important declaration outranks a normal one. Cascade layers are considered next, where a stylesheet uses @layer to declare its own order. Specificity then weighs how precisely each remaining selector describes the element, and source order breaks whatever ties are left, so the declaration written later wins.

That sequence describes the ordinary case, which is unscoped normal rules in your own stylesheet, and it covers almost everything you will write. Two things rearrange it. !important raises a declaration's importance rather than its specificity, and it also reverses the order of cascade layers. Rules written inside an @scope block add a proximity comparison between the specificity and source-order stages.

p { color: #94a3b8; }
.intro { color: #e2e8f0; }

A paragraph carrying class="intro" matches both rules. Both are normal declarations in the same origin and the same layer, so the decision reaches the specificity stage, where a class selector outranks a type selector. Specificity is settled before source order is ever consulted, which is why swapping the two rules around changes nothing at all.

This is why a declaration can look completely correct and still do nothing. The property is valid, the value is valid, and another rule simply won. Once you can read the cascade you stop guessing at that class of bug, and the CSS specificity guide gives you the scoring that decides it.

Why Old CSS Advice Looks Wrong

CSS accumulated a lot of workarounds for problems the language could not solve yet, and search results have a long memory. Recognising the old shapes saves you from copying a fix for a problem you no longer have.

Layout is where this bites hardest. Floats were designed for wrapping text around an image, then got pressed into service building whole page columns, which is why so many older stylesheets carry a clearfix rule to contain them. Purpose-built layout tools replaced that column-building use of floats, so reach for flexbox when you are arranging one direction and grid when rows and columns need to agree with each other.

You will also meet stylesheets full of !important, which usually signals a specificity fight nobody won rather than a real emergency. Understanding how specificity is scored removes most of the reasons to write it. Vendor prefixes are the third relic, added when browsers shipped experimental properties under their own names, and they mostly sit in old stylesheets as dead weight now.

The tell is the same in each case. If a snippet works around something that has since been given a real property, the workaround is costing you clarity for no benefit.

Choosing Which Elements to Style

Selectors are where beginners lose the most time, and the loss is rarely about syntax. You can write a selector that is perfectly valid and still target nothing, or target far more than you meant.

Start with the three that carry most of the work. A type selector matches every element of that kind, a class selector matches everything carrying that class, and an id selector matches the single element with that id. Classes do the overwhelming majority of real styling because they are reusable and their specificity stays predictable.

nav a { text-decoration: none; }
.button { padding: 0.5rem 1rem; }
.card > h3 { margin-top: 0; }

The third rule shows a combinator at work. The space in the first rule means any link inside the nav at any depth, while the child combinator in the third means only headings that are direct children of a card. Getting that distinction wrong is one of the most common reasons a rule reaches deeper into the page than intended.

Pseudo-classes then let you select states and positions that are not written in the HTML, such as the element under the cursor or the first item of a list. The CSS selectors guide works through each of these in order.

Arranging Boxes on the Page

Layout starts before you write a single layout property, because the browser already has a default. Normal flow stacks block elements down the page and runs inline elements along the line, and a lot of layout work is a small adjustment to that default rather than a replacement for it.

Flexbox handles one direction at a time. You declare a container and its children become items that share the space along a single axis, which covers navigation bars, button groups, and rows of cards.

.topic-list {
  display: flex;
  gap: 1rem;
}

Grid handles both directions together. Rows and columns are defined on the container, and items land in cells that line up across the whole structure, which is what page-level layouts usually need. The practical split is simple: content sharing one line is a flexbox job, and a structure where alignment has to hold in two directions is a grid job.

Positioning is the escape hatch for the small number of elements that must sit outside the flow, such as a sticky header or a badge pinned to a corner. Reaching for it as a general layout tool is a common early mistake, because absolutely positioned elements stop affecting their neighbours entirely. The CSS layout guide covers all four approaches with worked examples.

Making Text and Color Readable

A page can be laid out correctly and still be tiring to read. Type size, line height, line length, and contrast decide whether someone stays on the page, and all four are ordinary CSS properties rather than design intuition.

Color has more formats than most people need. Hex is compact and everywhere, and the newer functional formats carry an alpha channel for transparency directly. Units matter just as much: rem sizes stay relative to the root font size and respect a reader who has increased it, while fixed pixel values ignore that preference.

:root {
  --text-main: #e2e8f0;
  --space-gap: 1rem;
}

.topic-card {
  color: var(--text-main);
  padding: var(--space-gap);
}

Custom properties are the piece that changes how a stylesheet ages. Naming a value once and referencing it everywhere means a change happens in one place, and because custom properties are inherited and readable by JavaScript, they are also how most themes and dark modes are built now.

Shadows finish the surface by suggesting depth, and they are easy to overdo. A shadow that is obvious on a bright laptop screen can vanish on a different monitor, so borders remain the more reliable way to separate one surface from another. The CSS typography and color guide covers each of these properly.

Common Tasks, Mapped

You want toGo to
Center something, horizontally or verticallyFlexbox
Build a page-level structure with aligned rows and columnsGrid
Work out why your rule is being ignoredSpecificity
Style a hover, focus, or first-item statePseudo-classes
Pin a header so it stays visible while scrollingPositioning
Reuse one color or spacing value across a stylesheetCustom properties

What to Learn First

The order below front-loads the things that make everything after them easier to debug.

  1. Selector basics, because you cannot style anything you cannot reliably target.
  2. Specificity, because it explains the ignored-rule problem that otherwise costs you hours.
  3. Display and normal flow, because it is the default every layout tool modifies.
  4. Flexbox, which handles most day-to-day arrangement work.
  5. Colors and units, once the structure holds and readability becomes the problem.
  6. Grid and custom properties, when pages grow past a few screens.

What CSS Cannot Do

CSS styles what the document already contains. It cannot add, remove, or reorder real elements, so anything that changes the content itself belongs to HTML or JavaScript. Visual order can be changed with flexbox and grid, and doing so does not move the element for a screen reader or for keyboard focus, which is why reordering is a decision to make carefully.

CSS also cannot store data, make network requests, or respond to events that are not expressed as element state. Hover and focus are available because the browser tracks them as state, while a click that must change something elsewhere on the page needs JavaScript. Knowing the boundary saves you from hunting for a CSS solution that was never going to exist.

Every Guide in This Section

Frequently Asked Questions

Is CSS a programming language?

Not in the usual sense. CSS declares presentation rules rather than executing logic, though custom properties, calc, and container queries give it computed and conditional behaviour that blurs the old line.

Does the order of properties inside one rule matter?

Not for different properties, which apply independently. If the same property appears twice in one block the later one wins, which is the same last-one-wins tie-break that decides between separate rules of equal specificity.

Can CSS change content, not just appearance?

Only narrowly, through the content property on a before or after pseudo-element, which can insert text or an icon that is not in the source. CSS cannot add, remove, or reorder real elements.

Is Sass the same thing as CSS?

No. Sass and Less are preprocessor languages that compile to plain CSS before a browser sees them. They added variables and nesting years before CSS gained its own versions, which is why older projects still rely on them.

Do browsers support new CSS features at the same time?

No. Vendors ship features on independent timelines, so a property can work in one browser months before another. Checking current support is still part of deciding whether to rely on something new.

Where to Start

Build one small semantic page and style it end to end before reading further. Give it a heading, a couple of paragraphs, and four cards, then target them with classes, arrange the cards with flexbox, and set your colors through custom properties. Open browser developer tools and look at which declarations are crossed out, because that view is the cascade showing its work while your stylesheet is still small enough to hold in your head. When that page behaves the way you expect, start with the selectors guide and work down the order above.

Sources

  1. [1]
    CSS
    (developer.mozilla.org)
  2. [2]
    CSS selectors
    (developer.mozilla.org)
  3. [3]
    CSS box model
    (developer.mozilla.org)
  4. [4]
    Introducing the CSS cascade
    (developer.mozilla.org)
  5. [5]
    At-rules
    (developer.mozilla.org)
  6. [6]
    Cascade layers
    (developer.mozilla.org)