CSS controls how a web page looks: colour, spacing, fonts and layout. This course starts with how a rule is written and builds up to modern layout with Flexbox, Grid and responsive design.

It works best if you already know basic HTML, but each lesson explains what it needs. Keep a page open in your browser and change the values as you read; seeing the page react is the fastest way to understand CSS.

1. What is CSS? (start here)

The language that makes web pages look good.

In the HTML course you learned that HTML describes what is on a page: headings, paragraphs, images. Without anything else, those elements look plain: black text on a white background, in a default font.

CSS (Cascading Style Sheets) controls how it looks: colours, fonts, sizes, spacing, borders, layout, even animations. The same HTML can look completely different just by changing the CSS.

An easy comparison is a house. HTML is the building: walls, doors, windows. CSS is the paint, the furniture, and where everything is placed.

<h1>Hello</h1>

Plain HTML on its own

.title {
  color: rebeccapurple;
  text-align: center;
  font-size: 48px;
}

The same heading with three lines of CSS: purple, centred and big

"Cascading"

The word cascading means styles flow down and combine. If one rule says "all text is grey" and another says "this heading is red", the heading ends up red because the more specific rule wins. You will learn exactly how in the lesson on the cascade.

What you will learn in this course

  • How a CSS rule is written
  • Colours, text, and sizes
  • The box model: how every element is a box with space around it
  • Borders, rounded corners and shadows
  • Spacing with margin
  • Flexbox: lining things up and centring them
TipThe Playground in this club gives you a small page with a heading (class title) and a paragraph (class note). Whatever CSS you write is applied to them, so you see every change at once.
Recap
  • CSS controls the look of an HTML page.
  • HTML is the structure, CSS is the style.
  • The same HTML can look totally different with different CSS.

2. How CSS meets HTML

Where to write your CSS, and what a rule looks like.

There are three ways to add CSS to a page. You will mostly use the third.

<p style="color: tomato;">Red text</p>

1. Inline: a style attribute on one element (avoid for anything big)

<head>
  <style>
    p { color: tomato; }
  </style>
</head>

2. Internal: a style element inside the head of the page

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

3. External: a separate .css file, linked from the head (best for real websites)

An external file keeps your style in one place, and many pages can share it. Change the file once and every page updates.

The shape of a CSS rule

Every piece of CSS is a rule:

selector {
  property: value;
  property: value;
}

The anatomy of a rule

  • The selector says which elements to style. For example p means "every paragraph".
  • Inside curly braces { } are one or more declarations.
  • A declaration is a property (what to change, like color) then a colon, then a value (what to change it to, like tomato), and ends with a semicolon ;.
.title {
  color: tomato;
}

A real rule: make the title tomato red

Watch outDo not forget the semicolon at the end of each declaration, and do not mix up the colon : and the semicolon ;. A missing semicolon is the number one cause of "my CSS stopped working".
Recap
  • CSS can be inline, internal (style element), or external (a .css file).
  • A rule = selector + { property: value; }.
  • Always end each declaration with a semicolon.

3. Selectors and colours

Choosing what to style, and painting it.

A quick word on selectors

A selector decides which elements a rule applies to. The two you need first:

  • A type selector is just an element name: p, h1, button. It matches every element of that type.
  • A class selector starts with a dot: .title matches every element that has class="title".

Classes are the main tool, because you can put the same class on many elements, and one element can have several classes.

Text colour

The color property sets the text colour. You can write colours in several ways:

.title {
  color: tomato;          /* a colour name */
}
.note {
  color: #8b5cf6;         /* hex code */
}

Two ways to write a colour: a name and a hex code

  • Names: red, tomato, rebeccapurple, navy and about 140 others.
  • Hex codes: #rrggbb. Each pair is the amount of red, green and blue from 00 (none) to ff (full). #ff0000 is pure red, #000000 is black, #ffffff is white. #fa0 is a short form of #ffaa00.
  • rgb(): rgb(255, 99, 71) is the same tomato, with each number from 0 to 255.
  • hsl(): hsl(9, 100%, 64%) describes a colour by hue, saturation and lightness. Many people find it the easiest to tweak.

Background colour

background-color (or the short background) paints behind the element.

.title {
  color: white;
  background-color: #1e293b;
}

Colour and background together

TipMake sure text and background have enough contrast. Light grey text on a white background is hard to read, especially for people with weaker eyesight.
Recap
  • A selector chooses elements. .name picks everything with that class.
  • color sets text colour; background-color sets the paint behind.
  • Colours can be names, hex codes, rgb() or hsl().

4. Selectors in more depth

Picking exactly the elements you want.

Selectors are the "aim" of CSS. Here are the ones you will use all the time.

p { color: #334155; }          /* every paragraph */
.note { color: tomato; }       /* anything with class="note" */
#hero { color: navy; }         /* the one element with id="hero" */

Type, class, id

  • Type selector: p, h1. Matches by element name.
  • Class selector: .note. Reusable. This is your everyday tool.
  • ID selector: #hero. Matches the single element with that id. Because ids are unique, they are less flexible than classes.

Grouping

If several selectors share the same declarations, list them with commas.

.title, .note {
  font-family: Georgia, serif;
}

One rule for two selectors

Descendant selector

Two selectors separated by a space mean "the second one, but only inside the first".

nav a {
  color: white;
}

Only links that are inside a nav

Pseudo-classes

A pseudo-class is a state of an element. It starts with a colon. The most common is :hover, which applies while the mouse is over the element.

.note:hover {
  background: #fde68a;
}

The note turns yellow when the mouse is over it

Which should I use?

Use classes for almost everything. Use type selectors for page-wide defaults (like body or p). Avoid ids for styling.

Recap
  • Type (p), class (.note), id (#hero).
  • Commas group selectors; a space means "inside".
  • :hover and other pseudo-classes style a state.

5. Text alignment and text style

Where text sits, and how it looks.

text-align controls how text lines up inside its box: left (the default), right, center, or justify (stretch lines to the full width).

.title {
  text-align: center;
}

Centre the title

More text properties

  • font-weight: normal, bold, or a number like 600.
  • font-style: italic or normal.
  • font-family: the typeface. List fallbacks in order: font-family: Georgia, serif;. The browser uses the first one that is available.
  • line-height: the space between lines. 1.5 means one and a half times the font size. It makes paragraphs much easier to read.
  • text-decoration: underline, line-through, or none (the way to remove the underline from links).
  • text-transform: uppercase, lowercase or capitalize.
  • letter-spacing: space between letters.
.note {
  font-family: Georgia, serif;
  font-weight: bold;
  line-height: 1.6;
  text-transform: uppercase;
  letter-spacing: 1px;
}

Several text properties together

One thing to know

text-align aligns the text inside the box. It does not move the box itself. Moving the box is done with margin or flexbox, which come later.

Recap
  • text-align: left, right, center, justify.
  • font-weight, font-family, line-height and text-decoration shape the text.
  • text-align moves text inside its box, not the box.

6. Units and text size

Making things bigger or smaller.

font-size sets how big text is. Every size needs a unit after the number.

.note {
  font-size: 22px;
}

A 22 pixel note

The units you need

  • px (pixels): an exact size. One pixel is one dot on the screen (more or less). Easy to understand.
  • rem: relative to the page's base font size, which is usually 16px. 1rem = 16px, 1.5rem = 24px, 2rem = 32px. It respects the user's browser settings, so it is the best choice for text.
  • em: relative to the parent element's font size. Handy but trickier.
  • %: a percentage of something else, often the parent's size.
  • vw / vh: 1% of the browser window's width or height.
.title {
  font-size: 2.5rem;    /* 40px by default */
}
.note {
  font-size: 1.25rem;   /* 20px by default */
}

rem scales with the user's settings

Which unit when?

  • Text: rem.
  • Borders, shadows, tiny details: px.
  • Widths that should adapt to the screen: % or vw.
Watch outA number with no unit (like font-size: 20;) is invalid, and the browser ignores it. The only exception is 0, which needs no unit.
Recap
  • Every size needs a unit: px, rem, em, %, vw, vh.
  • rem is based on the base font size (16px by default). Great for text.
  • A number without a unit is ignored.

7. The box model

Every element is a box.

This is the most important idea in CSS. Every element on a page is a rectangular box, and every box has four layers, from the inside out:

  1. Content: the text or image itself.
  2. Padding: space inside the box, between the content and the border.
  3. Border: a line around the padding.
  4. Margin: space outside the border, pushing other boxes away.

Picture a framed photo on a wall. The photo is the content. The white card around it is the padding. The frame is the border. The gap to the next frame on the wall is the margin.

.note {
  background: #fef3c7;
  padding: 16px;
}

Padding and a background colour make a card

The background colour fills the content and the padding (up to the border). That is why padding is the quickest way to make something look like a card: the colour gets room to breathe around the text.

Writing padding

padding: 16px;              /* all four sides */
padding: 8px 24px;          /* top and bottom 8px, left and right 24px */
padding: 4px 8px 12px 16px; /* top, right, bottom, left (clockwise) */
padding-left: 20px;         /* one side only */

Padding shorthand

Width and the box

By default, width sets only the content width. Padding and border are added on top, so a width: 200px box with padding: 20px is really 240px wide. Many developers switch this off with a rule that makes width include padding and border:

* {
  box-sizing: border-box;
}

A common reset

TipIn the browser's Inspect tool, hover over an element and you will see a coloured diagram of its box: content, padding, border and margin. It is the best way to understand the box model.
Recap
  • Content, padding, border, margin: from inside to outside.
  • Padding is inside the border; margin is outside.
  • Background colour covers content and padding.
  • box-sizing: border-box makes width include padding and border.

8. Borders and rounded corners

Outlines and soft shapes.

A border is a line drawn around an element. It needs three values: width, style and colour.

.note {
  border: 2px solid orange;
}

A 2px solid orange border

  • Width: 1px, 2px, 4px...
  • Style: solid, dashed, dotted, double, or none.
  • Colour: any colour value.

If you set a border style of none (which is the default), the border is not drawn at all. That is why you must always include the style when you use the long form.

Single sides

border-bottom: 3px solid navy; draws a line on one side only. There are also border-top, border-left and border-right.

Rounded corners

border-radius softens the corners. Larger numbers mean rounder corners.

.note {
  border: 2px solid #f59e0b;
  border-radius: 12px;
}

Soft corners with a visible border

  • border-radius: 8px; a gentle curve, great for cards.
  • border-radius: 50%; on a square makes a circle.
  • border-radius: 999px; on a button makes a "pill" shape.
TipRounding works even without a border: the background colour gets rounded too.
Recap
  • border: width style colour.
  • Without a style (solid, dashed...) the border does not show.
  • border-radius rounds corners; 50% on a square makes a circle.

9. Shadows

Depth for cards and buttons.

box-shadow draws a soft shadow behind an element so it looks lifted off the page.

.note {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

A soft shadow below the note

The values, in order:

  1. x offset: how far the shadow moves right (negative moves left). 0 means no sideways shift.
  2. y offset: how far it moves down (negative moves up). 4px pushes it down.
  3. blur: how soft the edge is. Bigger is softer.
  4. colour: usually a transparent black. rgba(0, 0, 0, 0.2) is black at 20% opacity.

rgba and transparency

rgba(red, green, blue, alpha) is like rgb() with a fourth number from 0 (invisible) to 1 (solid). Semi-transparent shadows look natural because the background shows through.

Tips for good shadows

  • Subtle looks better: low opacity (0.1 to 0.25) and generous blur.
  • Use more than one shadow by separating them with a comma.
  • A shadow does not take up space. It never pushes other elements around.
.note {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 8px 24px rgba(0, 0, 0, 0.15);
}

Two shadows: a sharp small one and a soft big one

Recap
  • box-shadow: x y blur colour.
  • Use rgba() for a see-through colour.
  • Shadows do not affect layout.

10. The cascade, inheritance and specificity

Why a style wins or loses.

Sometimes you write a rule and nothing happens. Usually another rule won. CSS decides in this order.

1. Inheritance

Some properties pass down from parent to child automatically. If you set color on body, every paragraph inside it gets that colour too. Text properties (color, font-family, line-height) are inherited. Box properties (margin, padding, border, background) are not.

body {
  font-family: Georgia, serif;
  color: #1e293b;
}

Set once on body; everything inside inherits it

2. Specificity

When two rules target the same element and property, the more specific selector wins. From weakest to strongest:

  • type selector (p)
  • class selector (.note)
  • id selector (#hero)
  • inline style attribute
p     { color: blue; }
.note { color: red; }

The class beats the type, so the note is red

3. Order

If two rules are equally specific, the later one wins.

.note { color: red; }
.note { color: green; }

Same specificity: the last rule wins, so green

Debug it

In your browser's Inspect tool, select the element. The Styles panel lists every rule that touches it and shows overridden ones crossed out.

Watch outAvoid !important. It forces a rule to win, but it makes your CSS hard to change later.
Recap
  • Text properties are inherited; box properties are not.
  • More specific selectors win: type < class < id < inline.
  • Equal specificity: the later rule wins.

11. Margin: space between boxes

Pushing elements apart.

padding is the space inside a box. margin is the space outside it, and it pushes neighbouring boxes away.

.note {
  margin-top: 24px;
}

Push the note 24px away from the title above it

You can set each side, or use the shorthand just like padding:

margin: 16px;              /* all sides */
margin: 8px 24px;          /* top and bottom, then left and right */
margin: 0 auto;            /* no vertical margin, centre horizontally */
margin-top: 24px;
margin-bottom: 0;

Margin shorthand

Centring a block

If a block has a fixed width, setting its left and right margins to auto centres it horizontally in its parent.

.note {
  width: 300px;
  margin: 0 auto;
}

A centred box 300px wide

Margin collapse

When the bottom margin of one block touches the top margin of the next, the browser does not add them. It uses the larger of the two. This is called margin collapse, and it is why a 20px bottom margin above a 30px top margin makes a gap of 30px, not 50px.

Padding or margin?

Ask: is the space inside the thing (between its edge and its content)? Use padding. Is it the space between things? Use margin.

TipHeadings and paragraphs already have default margins from the browser. That is why they do not touch each other even though you wrote no CSS.
Recap
  • margin is space outside the border; it pushes neighbours away.
  • margin: 0 auto centres a block that has a width.
  • Vertical margins between blocks collapse to the larger one.

12. Block, inline and width

How elements flow on the page.

Every element has a display type. It decides how the element behaves in the flow of the page.

  • block: takes the full width available and starts on a new line. div, p, h1, ul are block. You can set width, height, and all margins.
  • inline: flows within a line of text, only as wide as its content. span, a, strong, em are inline. width and height do not apply.
  • inline-block: flows like inline, but you can set width, height and vertical margins.
  • flex: the element becomes a flexible container for its children (next lesson).
  • none: the element disappears completely.
a {
  display: inline-block;
  padding: 8px 16px;
}

Make a normally inline element act like a box

Width and height

Block elements stretch to fit their container unless you set a width. Use max-width to say "as wide as needed, but never wider than this", which is perfect for readable text columns and works on small screens.

.article {
  max-width: 680px;
  margin: 0 auto;
}

A readable column that shrinks on phones

Recap
  • Block elements fill the row; inline elements flow in text.
  • inline-block is inline with box powers.
  • display: none removes an element. max-width is great for responsive layouts.

13. Flexbox: lining things up

Centre and arrange with one rule.

Putting things side by side or centring them used to be painful. Flexbox solves it. You turn a parent element into a flex container, and its direct children become flex items that line up along a direction.

body {
  display: flex;
  flex-direction: column;
  align-items: center;
}

The page body becomes a centred column

Three ideas:

  1. display: flex on the parent switches flexbox on.
  2. flex-direction chooses the main axis: row (left to right, the default) or column (top to bottom).
  3. align-items aligns the items on the cross axis (the other direction): flex-start, center, flex-end, stretch.

In our example the direction is a column, so the main axis is vertical, the cross axis is horizontal, and align-items: center centres the items horizontally. If the direction were row, the same align-items: center would centre them vertically.

The golden rule

Flex properties like flex-direction and align-items go on the parent, not on the items.

Watch outIf nothing seems to happen, check that display: flex is on the parent. Without it, the other flex properties are ignored.
Recap
  • display: flex on the parent starts flexbox.
  • flex-direction sets the main axis; align-items aligns across it.
  • Flex properties go on the parent container.

14. Flexbox: gaps, spacing and rows

A few more flex tools.

Once display: flex is on, these properties do most of the work.

  • justify-content spreads items along the main axis: flex-start, center, flex-end, space-between, space-around.
  • align-items aligns them across the cross axis.
  • gap adds space between items (no margins needed).
  • flex-wrap: wrap lets items drop onto the next line when there is not enough room.
body {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  gap: 16px;
  min-height: 100vh;
}

Items in a row, centred both ways, with a gap

A classic: centre anything on the screen

To centre a box both horizontally and vertically in the window, use a flex container that is as tall as the window, and centre both axes: display: flex; justify-content: center; align-items: center; min-height: 100vh;.

A navigation bar

nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

A row with the logo on the left and links on the right

Recap
  • justify-content works on the main axis, align-items on the cross axis.
  • gap adds spacing between flex items.
  • flex-wrap: wrap lets items move to a new line.

15. Hover effects and transitions

Making things respond.

Pages feel alive when things react. You already met :hover. Add transition to make the change smooth instead of instant.

.note {
  background: #fef3c7;
  padding: 16px;
  border-radius: 12px;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.note:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
}

A note that lifts and brightens on hover

  • transition: property duration timing tells the browser to animate changes smoothly. Put it on the normal state.
  • transform: translateY(-4px) moves the element up by 4 pixels without affecting layout.
  • Useful transforms: scale(1.05) to grow slightly, rotate(3deg) to tilt.

Other states

  • :focus applies when a form field or button has keyboard focus. Always keep a visible focus style: keyboard users depend on it.
  • :active applies while a button is being pressed.
TipKeep transitions short (0.15 to 0.3 seconds). Slow animations feel sluggish.
Recap
  • :hover styles the mouse-over state.
  • transition on the normal state animates the change.
  • transform moves, scales or rotates without changing layout.

16. Making a page work on phones

One page, every screen size.

People view pages on phones, tablets and big monitors. Responsive design means your CSS adapts to the screen.

Step 1: the viewport tag

Add this line to the head of your HTML so phones do not zoom out and shrink the page:

<meta name="viewport" content="width=device-width, initial-scale=1">

In the head of your HTML

Step 2: flexible sizes

Prefer max-width, percentages and rem over fixed pixel widths.

Step 3: media queries

A media query applies CSS only when a condition is true, usually about the screen width.

.cards {
  display: flex;
  gap: 16px;
}

@media (max-width: 600px) {
  .cards {
    flex-direction: column;
  }
}

Stack the layout on small screens

Read it as: "when the screen is 600 pixels wide or narrower, make the cards stack in a column."

Mobile first

Many developers write the small-screen styles first, then use min-width queries to add features for bigger screens. It keeps phone pages light and simple.

Recap
  • Add the viewport meta tag.
  • Use flexible units; add media queries for changes at certain widths.

17. Fixing CSS that does not work

A checklist for when nothing changes.

Every developer asks "why is my CSS not working?" every week. Walk through this list from top to bottom.

  • Typo. Is the property name spelled right? backround does nothing and gives no error.
  • Missing semicolon, colon or brace. One mistake can break the following rules too.
  • Wrong selector. Does the element really have the class you used? Is it .note with a dot, not note?
  • Another rule wins. Check specificity and order (see the cascade lesson).
  • Wrong target. Flex properties go on the parent. margin has no effect on some inline elements.
  • No unit. font-size: 20 is ignored. Use 20px.
  • Cache. Hard-refresh the page (Ctrl+Shift+R) if you changed a linked file.

Use the Inspect tool

Right-click the element and choose Inspect. In the Styles panel you can:

  • See every rule that applies, with overridden ones crossed out.
  • Tick or untick a declaration to test it instantly.
  • Edit values live and see the page change.

Once you find the fix, copy it back into your real file.

Recap
  • Check spelling, punctuation, selector, specificity and units.
  • The Inspect tool shows which rules apply and which lose.
  • Test changes live in the browser before editing your file.