CSS

CSS (Cascading Style Sheets) controls how HTML elements look on a webpage. While HTML provides structure, CSS handles layout, spacing, colours, and visual presentation. This page covers everything from the basics through to advanced techniques, with a clear divider marking where things get more complex.

Quick Check

CSS not working?
→ Is the selector correct?
→ Is the rule applied?
→ Is it overridden by another rule?
→ Is the parent controlling layout?
→ Is size causing the problem?
→ Is it losing the specificity battle?
                    

Applying CSS

There are three main ways to apply CSS to a webpage.

Method Where Use Case
Inline Inside HTML tags Quick testing (not recommended long term)
Internal <style> in head Small projects
External Separate .css file Best practice for real projects
Best habit:
HTML = structure
CSS  = styling
                        

Reset

Browsers apply default styles. * is used to reset browser defaults and make layout easier to control.

These default styles are called the User Agent Stylesheet — every browser ships with one. It's why an unstyled page still has margins, font sizes, and bullet points. Always check the User Agent Stylesheet before assuming your CSS rule isn't working.

Common example:

/* Reset - applies to all elements */
* {
    margin: 0;               /* remove default spacing */
    padding: 0;              /* remove default spacing */
    box-sizing: border-box;  /* keeps width predictable */
}
                        

This helps by:

  • removing unexpected default spacing
  • making sizing more consistent
  • creating a cleaner starting point
New CSS file starter — copy this to begin:

/* 1. Reset */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 2. Body defaults */
body {
    font-family: sans-serif;
    font-size: 1rem;
    line-height: 1.5;
    color: #333;
    background-color: #fff;
}
                        

Colour Formats

CSS supports several ways to write colours. They all do the same job — the difference is how readable and flexible they are to work with.

Format Example When to use it
Named color: red; Quick testing only — limited options
HEX color: #3b82f6; Common in designs and copied from tools like Figma
RGB color: rgb(59, 130, 246); When you need to work with red, green, blue values directly
RGBA color: rgba(59, 130, 246, 0.5); Same as RGB but with transparency (0 = invisible, 1 = solid)
HSL color: hsl(210, 75%, 25%); Best for adjusting colours — easy to make lighter, darker, or more muted
HSLA color: hsla(210, 75%, 25%, 0.8); HSL with transparency
HSL breakdown:
hsl( hue, saturation, lightness )

Hue        → 0–360 — the colour on the wheel (0 = red, 120 = green, 240 = blue)
Saturation → 0% = grey, 100% = full colour
Lightness  → 0% = black, 50% = normal, 100% = white

Why HSL is useful:
→ easy to make a colour lighter:  hsl(210, 75%, 40%) → hsl(210, 75%, 60%)
→ easy to make it more muted:     hsl(210, 75%, 25%) → hsl(210, 30%, 25%)
→ no need to guess hex codes
                        
Rule:
Use HEX when copying from design tools
Use HSL when you want to adjust colours yourself
Use RGBA / HSLA when you need transparency
                        

Colours & Backgrounds

CSS controls both text colour and element backgrounds, including images and gradients.

Property Description Example
color Text colour color: #333;
background-color Element background colour background-color: lightblue;
background-image Image or gradient background background-image: url("image.jpg");
background-size Scales background image background-size: cover;
background-position Aligns background image background-position: center;
For most background images use:

background-size: cover;
background-position: center;
background-repeat: no-repeat;
                        

The Cascade

The "C" in CSS stands for Cascading. It means that when multiple rules target the same element, CSS has a system for deciding which one wins. Understanding this saves a lot of confusion.

Three things decide which rule wins:

1. Specificity   → more specific selectors beat less specific ones
2. Order         → when specificity is equal, the rule written LAST wins
3. Importance    → !important overrides everything (use sparingly)
                        
Order example:

p { color: red; }
p { color: blue; }

→ text will be BLUE
→ the second rule comes later so it wins
                        
Practical rule:
If a style is not applying and you can't see why,
scroll down your CSS — a later rule may be overriding it.
                        
Concept What it means
Cascade Rules flow down — later rules can override earlier ones
Specificity More targeted selectors win over general ones
Inheritance Some properties (like font-family) pass down to child elements automatically
!important Forces a rule to win — overrides cascade and specificity

Selectors

Selectors are used to target HTML elements so CSS can be applied to them.

Selector Example Description
Element p Targets all elements of that type
Class .box Targets elements with a class
ID #main Targets a specific element
If CSS does nothing:
1. Check selector
2. Check class name
3. Check spelling
4. Check if another rule wins
                        

The Box Model

Every element in CSS is treated as a box. Understanding this is key to controlling layout and spacing.

+-------------------------+
|       margin            |
|  +-------------------+  |
|  |      border       |  |
|  |  +-------------+  |  |
|  |  |   padding   |  |  |
|  |  | +---------+ |  |  |
|  |  | | content | |  |  |
|  |  | +---------+ |  |  |
|  |  +-------------+  |  |
|  +-------------------+  |
+-------------------------+
                        

The box model is made up of content, padding, border, and margin.

Useful:
box-sizing: border-box;

Default behaviour:
width = content only
Padding and border are added on top of width.

border-box:
width = content + padding + border

Use border-box when you want predictable sizing.
                        

Spacing: Margin vs Padding

Margin controls space outside an element. Padding controls space inside the element between the content and its border.

Property Controls
margin Space outside the element
padding Space inside the element
gap Space between flex/grid items
Padding = inside the box
Margin  = outside the box
Gap     = between layout items
                        

Display

The display property controls how elements behave in layout.

Value Behaviour
block Takes full width and starts on a new line
inline Only takes needed width
inline-block Inline but allows width/height
none Removes element from layout
flex Creates a flex layout container
grid Creates a grid layout container
Use display to decide:
Does this behave like text?
Or like a layout box?
                        

Centring and Sizing

Center text

Use text-align: center; when you want to center text inside an element.

Center a block element

A block element must be narrower than its parent before centring becomes visible. Use auto margins to center it horizontally.

Default block behavior matters

Many block elements take up the full available width by default. This can make some alignment changes appear to do nothing.

Centring checklist:

text-align: center;
→ centers text/content inside an element

margin: auto;
→ centers a narrower block/container horizontally

justify-items / justify-content;
→ centers layout items, not the container itself

Rule:
Ask: Am I centering text, items, or the container?
                        

Default browser styles

  • Headings often have top and bottom margin
  • Paragraphs have default spacing
  • Lists often have default padding and margin

Always check default styles before assuming your layout rule is wrong.

Width vs max-width

  • width defines how much space an element should take
  • max-width sets a ceiling
  • Use percentage width when you want items to share a row

Images in Layout

Images are affected by both their own size and the container they sit inside. If the container is not controlled, the image may not behave as expected.

Common image problems include:

  • not filling the available space
  • stretching out of proportion
  • cropping in the wrong area
  • not aligning where expected
Property What it helps control
width How wide the image appears
max-width Stops the image becoming too large
height How tall the image appears
object-fit How the image fits inside its container
object-position Which part of the image stays visible when cropped
Rule:
control the container first
then control how the image fits inside it
                        

Typography

Typography controls how text looks and how easy it is to read. Good typography improves readability and overall layout.

Property What it controls
font-family The typeface used on the page
font-size The size of the text
font-weight How bold or light the text appears
line-height Space between lines of text
letter-spacing Space between letters
text-transform Uppercase/lowercase style
Basic rule:
make text readable first
style it second
                        

Units

Different CSS units are useful in different situations. Some are fixed, others are relative.

Unit Meaning Example
px Fixed size width: 200px;
% Relative to parent width: 50%;
rem Relative to root font size padding: 1.5rem;
vw / vh Relative to viewport width/height height: 50vh;
Good habit:
use rem for type/spacing
use % for flexible widths
use vw/vh carefully
                        

Flexbox

Flexbox is powerful but can feel confusing at first because layout behaviour depends heavily on the parent container and the chosen direction. Flexbox is one-dimensional — it handles either a row or a column at a time.

Direction Controls Everything

flex-direction: row

[ item ][ item ][ item ]

main axis  → left ↔ right
cross axis → top  ↕ bottom
                        
flex-direction: column

[ item ]
[ item ]
[ item ]

main axis  → top  ↕ bottom
cross axis → left ↔ right
                        

If alignment feels wrong, the direction is usually the cause.

If spacing is wrong:
check direction first

If items won't move:
check the parent
                        
Nav list recipe:

nav ul {
    display: flex;
    list-style: none;
    gap: 1rem;
}

nav a {
    text-decoration: none;
    color: inherit;  /* inherit = use the parent's colour instead of default link blue */
}
                        
Problem-solving order (learned from Flexbox Froggy level 24):

Don't try to move individual items first — figure out the overall
layout structure before touching individual positioning.

1. flex-direction   → which way does the main axis run?
2. flex-wrap         → does content wrap onto new lines?
3. justify-content   → position along the main axis
4. align-content     → position the wrapped lines along the cross axis
   (align-items      → position items within a single line)

Getting the structure (1-2) right first makes the positioning
properties (3-4) behave the way you'd expect.
                        
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ADVANCED CSS
  Everything below this point covers advanced concepts
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                    

Pseudo-Classes

Pseudo-classes target elements in a specific state, such as when a user hovers over a link or when an element is the first child in a container.

State-based styling

link     → normal
:hover   → pointer over it
:focus   → keyboard focus
:active  → being clicked
                        
Pseudo-Class Description Example
:hover Applies when the user hovers over an element. a:hover { color: gold; }
:focus Applies when an element receives keyboard focus. input:focus { outline: 2px solid white; }
:active Applies when an element is being clicked. button:active { transform: scale(0.98); }
:nth-child() Selects elements based on their position in a list. li:nth-child(2) { color: yellow; }

Pseudo-Elements

Pseudo-elements style specific parts of an element, such as the first letter or content inserted before or after an element.

Part-based styling

::before         → before content
::after          → after content
::first-letter   → first letter
::selection      → selected text
                        
Pseudo-Element Description Example
::before Inserts content before an element. h2::before { content: "★ "; }
::after Inserts content after an element. h2::after { content: " ★"; }
::first-letter Styles the first letter of text. p::first-letter { font-size: 2rem; }
::selection Styles text when selected by the user. ::selection { background: gold; }

CSS Positioning

Positioning controls how elements are placed on the page. It is essential for building complex layouts and UI components.

RELATIVE → keeps its space
ABSOLUTE → removed from flow
FIXED    → attached to viewport
STICKY   → relative until stuck
                        
Position Type Description Example
static Default positioning, follows normal document flow. div { position: static; }
relative Positioned relative to its normal position. div { position: relative; top: 10px; }
absolute Positioned relative to the nearest positioned ancestor. div { position: absolute; right: 0; }
fixed Stays fixed to the viewport when scrolling. nav { position: fixed; top: 0; }
sticky Scrolls normally until reaching a threshold, then sticks. h2 { position: sticky; top: 0; }

Backgrounds

CSS backgrounds allow you to control images, gradients, and positioning for decorative or structural design.

Common background image trio:

background-size: cover;
background-position: center;
background-repeat: no-repeat;
                        
Property Description Example
background-image Sets an image or gradient as the background. background-image: url(bg.png);
background-size Controls how the background image scales. background-size: cover;
background-position Sets the starting position of the background. background-position: center;
background-repeat Controls whether the image repeats. background-repeat: no-repeat;
Advanced ideas:
gradient + image layering
blend modes
fixed backgrounds
                        

Shadows

Shadows add depth and emphasis to elements, improving visual hierarchy.

box-shadow  → around element
text-shadow → behind text
                        
Type Description Example
box-shadow Adds shadow around an element's box. box-shadow: 0 4px 6px rgba(0,0,0,0.3);
text-shadow Adds shadow behind text. text-shadow: 1px 1px 2px black;

Transitions

Transitions allow smooth changes between property values, improving interactivity and user experience.

Normal:
button

Hover:
button changes smoothly
                        
Property Description Example
transition-property Specifies which property will animate. transition-property: background-color;
transition-duration Controls how long the change takes. transition-duration: 0.3s;
transition-timing-function Controls animation speed curve. transition-timing-function: ease;
transition-delay Waits before the transition starts. transition-delay: 0.1s;
transition Shorthand for all transition settings. transition: all 0.3s ease;

CSS Variables

CSS variables let you define a value once and reuse it everywhere. This makes your stylesheet much easier to update and maintain.

Why variables matter:

Without variables — changing your brand colour means hunting through every line:
button    { background-color: #3b82f6; }
a         { color: #3b82f6; }
.header   { border-bottom: 2px solid #3b82f6; }
.badge    { background-color: #3b82f6; }

With variables — change it in one place, it updates everywhere:
:root { --color-primary: #3b82f6; }

button    { background-color: var(--color-primary); }
a         { color: var(--color-primary); }
.header   { border-bottom: 2px solid var(--color-primary); }
.badge    { background-color: var(--color-primary); }
                    
Use Description Example
Colours Keep palette consistent. --brand-blue: #3498db;
Spacing Reuse spacing values. --space-md: 1rem;
Themes Update many styles from one place. background: var(--surface);
Colour palette starter:

:root {
    --color-primary:   #3b82f6;
    --color-secondary: #64748b;
    --color-accent:    #f59e0b;
    --color-bg:        #ffffff;
    --color-text:      #1e293b;
}

body {
    background-color: var(--color-bg);
    color: var(--color-text);
}

a { color: var(--color-primary); }
                    
To retheme the whole site:
update :root — not every selector
                    

Advanced Units

Relative and advanced units make CSS more flexible and responsive.

Unit Description Example
em Relative to parent font-size. padding: 2em;
rem Relative to root font-size. font-size: 1.2rem;
vw / vh Relative to viewport width and height. height: 50vh;
vmin / vmax Relative to the smallest or largest viewport side. font-size: 5vmin;
ch Based on the width of the "0" character. width: 60ch;
calc() Allows simple math in CSS. width: calc(100% - 40px);
clamp() Sets a min, preferred, and max value. font-size: clamp(1rem, 2vw, 2rem);
Use advanced units when:
fixed px becomes too rigid
                    

Animations

Animations create movement over time using keyframes.

Transition = simple state change
Animation  = full motion sequence
                    
Part Description Example
@keyframes Defines the animation stages. @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
animation Applies the animation. .box { animation: fadeIn 1s ease-in-out forwards; }

Buttons

Buttons combine typography, spacing, borders, and transitions.

Good button thinking:
default
hover
active
focus
                    
Idea Description Example
Readable text Text must stay clear and legible. color: white;
Comfortable spacing Padding improves usability. padding: 12px 20px;
Interactive feedback Hover/active states improve feel. transition: background 0.3s ease;

Specificity & Cascade

Specificity determines which CSS rule wins when multiple rules target the same element. The more specific the selector, the higher it scores.

Selector Type Specificity Value Example
Inline Styles 1000 <div style="color:red">
ID Selectors 100 #header { }
Class / Attribute / Pseudo-class 10 .box { }
Element Selectors 1 p { }
If a rule will not apply:
→ it may be losing the specificity battle
→ or a later rule in the cascade is overriding it
→ check both before reaching for !important
                    

Fast Reminders

If CSS does nothing:
→ check selector

If layout feels wrong:
→ check parent

If spacing feels wrong:
→ check margin / padding / gap

If image looks wrong:
→ check container first

If alignment feels wrong:
→ check flex direction

If one rule wins unexpectedly:
→ check specificity
→ check rule order in your file

State change?     → pseudo-class
Part of element?  → pseudo-element
Move in layout?   → positioning
Smooth change?    → transition
Motion sequence?  → animation
Reuse values?     → variables
Rule not applying?→ specificity or cascade