Skip to content
Chapter 03 · Slide Breakdown

CSS: Selectors, Cascade and Layout

The longest deck in the course and the one with the most missing content: the flexbox and grid property tables are screenshots, so the slide text alone will not teach you them. Everything those slides skipped is reconstructed here as code you can run.

85 slidesTwo decks in oneMost screenshot-heavyBook ch. 4 + 5 + 7

What this chapter is really for

Split again: Part 1 (slides 1–60) is selectors, the cascade, the box model and text/table/form styling; Part 2 (slides 61–84) is flexbox, grid and responsive design.

Be warned about this deck specifically. A large share of its most important slides — the flexbox container properties (65–66), the flex item properties (67), the grid structure slides (69–71) — are images with almost no text on them. If you revise from the slide text alone you will have a chapter with a hole in the middle exactly where the layout marks are. That gap is what the code sections below are for.

The two ideas everything hangs off

The cascade decides which rule wins when several apply: inheritance, then specificity, then location. The box model decides how big things are: content, padding, border, margin. Almost every "why does my page look wrong" question is one of these two.

Engineering framing worth quoting

Slide 3 gives the reason CSS exists in engineering terms: separation of concerns and reuse. The listed benefits — control over formatting, maintainability, accessibility, download speed, output flexibility — all follow from those two.

All 85 slides, weighted

SlidesTopicWeightWhat to do with it
1–3What CSS is; benefitsMemorizeSeparation of concerns + reuse, then five benefits. A likely short-answer question.
4–5Rule, selector, declaration, declaration block, valuesMemorizeGet the vocabulary exactly right — questions are worded using these terms.
6The five ways to write a colourMemorizeName, RGB, hexadecimal, RGBa, HSL/HSLA. Know which are CSS3-only.
7Units: relative vs absoluteMemorizepx, em, vw are the ones asked about; in and cm are absolute.
8–11Inline, embedded and external stylesWrite itKnow the syntax of all three and why external wins: one change updates every page, and the browser can cache it.
12–15Element, class and ID selectorsWrite itThe id is unique to one element; a class targets many. An element can carry several classes.
16–18Attribute selectors — all six operatorsWrite it[] [=] [~=] [^=] [*=] [$=]. Very examinable, and easy marks once memorised.
19–22Pseudo-classes and pseudo-elementsWrite itLink states in order, :hover, :active, :first-child, :first-letter, :first-line, :is().
23Task: last child red; links whose href contains "example"Write itDo it. It is two lines and it tests both halves of the selector material.
25–26Contextual selectors / combinatorsWrite itSpace, >, +, ~. Learn what each one actually matches, not just its name.
27Nested CSS rulesSkimNew, and shown side by side with the flat equivalent. Understand the translation both ways.
28–32The cascade: inheritance, specificity, locationMemorizeThe highest-value block in Part 1. Slide 31 gives the a-b-c-d specificity algorithm — learn to compute it.
33–36Block vs inline elementsMemorizeTwo block elements cannot share a line without styling. Inline elements flow within lines and wrap.
37–42Margins, padding, the box model, dimensions, overflowWrite itLearn the four-value / two-value / one-value shorthand rules and how total element size is calculated.
43–50Text and font properties, web font stacks, @import, remWrite itA font stack exists because your font may not be on the user’s machine. rem is relative to the root element.
51–53CSS variables / custom propertiesWrite itDeclared in :root, named with --, read with var(). Almost certain to appear in a lab.
54–57Styling tables: borders, border-collapse, zebra stripingWrite itBorders can go on table, th and td only — not on tr, thead, tbody, tfoot. That exact fact is examinable.
58–60Styling forms, placeholders, labels, form designWrite itTies chapter 2 forms to CSS. ::placeholder is the pseudo-element to remember.
61–62Part 2 title and objectivesSkimTransition slides.
63–67Flexbox: containers and itemsWrite itScreenshot slides. The property tables are images. Use the reconstruction below.
68–77Grid: structure, column widths, placement, cells, nesting, named areasWrite itMostly screenshots too, except the named-areas listing on slide 76. Highest-value practical block in the chapter.
78Grid and flexbox togetherMemorizeOne sentence that answers the "which do I use" question: grid for the page structure, flexbox for the contents of a cell.
79–84Responsive design, viewports, media queries, <picture>Write itMemorize the viewport meta tag verbatim. Know why max-width:100% is not enough on its own.
85Supporting material and linksSkimThe code repository for every chapter: github.com/skanderturki/se371.

Syntax and every selector type

The vocabulary, precisely

anatomy.cssSlides 4–5
/*  ── one RULE ──────────────────────────────── */
h1, h2 {                    ← SELECTOR  (comma groups several)
    color: #431c5d;         ← DECLARATION: property : value
    font-size: 24pt;        ← another declaration
}                            ← the { } is the DECLARATION BLOCK

/*  A stylesheet is one or more rules.
    The unit of a value depends on the property: keywords, percentages,
    lengths, unitless numbers, colour values and URLs are all possible.  */

Colour: five ways to say red

MethodDescriptionExample
Name17 standard names; CSS3 has 140.color: red; · color: hotpink; (CSS3)
RGBThree numbers 0–255 for red, green and blue.color: rgb(255,0,0);
HexadecimalA six-digit hex number for the same three values.color: #FF0000;
RGBaAdds alpha — transparency.color: rgba(255,0,0,0.5);
HSL / HSLAHue, saturation, lightness. CSS3 only.color: hsl(0,100%,100%);

Units

Units are either relative (based on the value of something else) or absolute (a real-world size).

UnitKindMeaning
pxRelative in CSS2, absolute in CSS31/96 of an inch, so roughly 1.06 mm.
emRelativeThe computed font-size of the element it is used on. 2em = twice the current font size.
remRelativeAlways relative to the root <html> element — introduced because nested ems become impossible to calculate.
vwRelative1% of the viewport width. If the viewport is 30 cm wide, 1vw = 0.3 cm.
in, cmAbsoluteReal-world inches and centimetres.

Where styles live — three locations, not mutually exclusive

the three locationsSlides 8–11[ RUN IT → ]
<!-- 1. INLINE — style attribute. Affects only this element.
        Overrides other definitions for the properties it sets. -->
<h2 style="font-size: 24pt; font-weight: bold;">Reviews</h2>

<!-- 2. EMBEDDED (internal) — a <style> element in the <head>.
        Better than inline, but still discouraged. -->
<head>
  <style>
    h1 { font-size: 24pt; }
    h2 { font-size: 18pt; font-weight: bold; }
  </style>
</head>

<!-- 3. EXTERNAL — a .css file. THE ONE TO USE.
        • change it once, every page that links it updates
        • the browser can CACHE it, which improves performance -->
<head>
  <link rel="stylesheet" href="styles.css">
</head>

Basic selectors

selectors.cssSlides 12–15[ RUN IT → ]
/* ELEMENT — every instance of the element */
p { margin: 0; }

/* UNIVERSAL — every element */
* { box-sizing: border-box; }

/* GROUPED — commas. These two are exactly equivalent: */
p, div, aside { margin: 0; padding: 0; }
/*   ≡  p{margin:0;padding:0} div{...} aside{...}  */

/* CLASS — a period. Targets MANY elements. */
.orange { background-color: orange; }
.circle { border-radius: 50%; }

/* ID — a hash. UNIQUE: one element per document. */
#first { border: 2px solid black; }

An element may carry several classes — <div class="orange circle"> — and where two of its classes set the same property, priority goes to whichever rule appears last in the document. That is the location principle, arriving early.

Attribute selectors — all six operators

attribute-selectors.cssSlides 16–18[ RUN IT → ]
[title]                          /* has the attribute at all                        */
a[title="posts from this country"]  /* exact value                                     */
[title~="Countries City"]         /* value contains this WORD in a space-separated list */
a[href^="mailto"]                /* value BEGINS with  (^ = start, like regex)      */
img[src*="flag"]                 /* value CONTAINS the substring anywhere           */
a[href$=".pdf"]                  /* value ENDS with    ($ = end, like regex)        */

/* The slide's own example: mark PDF links with an icon */
a[href$=".pdf"] {
    background: url(pdf.jpg) no-repeat left center;
    padding-left: 20px;
}
Remember the three symbol operators through regex: ^ is “starts with” and $ is “ends with” in regular expressions too (chapter 5), and * is the greedy one — anywhere at all. Only ~= is CSS-specific: a whole word in a space-separated list.

Pseudo-classes and pseudo-elements

A pseudo-element selects something that does not exist as an element in the document tree — the first line or first letter of a block. A pseudo-class targets a state or a family relationship.

pseudo.cssSlides 19–23[ RUN IT → ]
/* LINK STATES — write them in this order or later ones stop working */
a:link    { color: #0000EE; }   /* not yet visited            */
a:visited { color: #551A8B; }   /* already visited            */
a:hover   { color: #b829ea; }   /* pointer is currently above */
a:active  { color: red; }       /* being activated / clicked  */

/* FAMILY + TEXT */
li:first-child   { font-weight: bold; }  /* first child of its parent */
li:last-child    { color: red; }           /* ← the slide 23 task       */
p::first-letter  { font-size: 3em; }       /* pseudo-ELEMENT: ::        */
p::first-line    { font-variant: small-caps; }

/* :is() takes a selector LIST — far shorter than repeating :hover */
:is(input, label, button, select):hover { outline: 2px solid #b829ea; }
/*   instead of  input:hover, label:hover, button:hover, select:hover  */

/* The other half of the slide 23 task */
a[href*="example"] { color: red; }

Contextual selectors (combinators)

combinators.cssSlides 25–26
/* Given this markup:
   <section>
     <h2>Title</h2>
     <p>One</p>
     <div><p>Nested</p></div>
     <p>Two</p>
   </section>                                                    */

section p    { }   /* DESCENDANT, a SPACE. Matches One, Nested AND Two —
                       every p contained anywhere inside section.       */

section > p  { }   /* CHILD, a >. Matches One and Two only —
                       Nested is a child of div, not of section.        */

h2 + p       { }   /* ADJACENT, a +. Matches One only —
                       the NEXT SIBLING immediately after h2.           */

h2 ~ p       { }   /* GENERAL SIBLING, a ~. Matches One and Two —
                       ALL following siblings sharing the same parent.  */
Four combinators, four questions: space = anywhere inside? · > = directly inside? · + = immediately after? · ~ = anywhere after, same parent?

Nested rules (new)

nesting.cssSlide 27
/* NESTED — implemented by all major browsers, still a W3C draft */
.card {
    padding: 1rem;
    & h2   { margin: 0; }
    & p    { color: gray; }
    &:hover { border-color: #b829ea; }
}

/* ── is exactly equivalent to ── */
.card       { padding: 1rem; }
.card h2    { margin: 0; }
.card p     { color: gray; }
.card:hover { border-color: #b829ea; }

The cascade — the most examinable idea in CSS

The cascade is how conflicting rules are resolved, and it applies three principles in this order: inheritance, specificity, location.

1. Inheritance

Many CSS properties affect descendants as well as the element itself. The division is not arbitrary and is worth learning as two lists:

InheritedNot inherited
Font properties — font-family, font-size, font-weightLayout properties — display, position, float
ColorcolorSizingwidth, height
List properties — list-style-typeBorder properties
Text properties — text-align, line-heightBackground and spacingmargin, padding
inherit.cssSlide 29[ RUN IT → ]
/* You can FORCE inheritance of a property that normally does not inherit */
button { color: inherit; font-family: inherit; }
/* ↑ the classic use: form controls do not inherit page fonts by default */

2. Specificity — and how to actually compute it

The more specific selector wins: id beats class, class beats element. Slide 31 gives the simplified algorithm as four counters, written as abcd:

specificity — compute it, do not guessSlide 31
  a = is it an INLINE style?         (1 or 0)
  b = count the IDs                  (#)
  c = count the CLASSES + ATTRIBUTES + pseudo-classes   (. [ ] :)
  d = count the ELEMENTS             (tag names + pseudo-elements)

  Read a-b-c-d as one number, LEFT TO RIGHT. Higher wins.
  A single id beats any number of classes: 0-1-0-0 > 0-0-9-9.

─── worked examples ───────────────────────────────────────────
p                       a=0 b=0 c=0 d=1  →  0001
.orange                 a=0 b=0 c=1 d=0  →  0010
div p                   a=0 b=0 c=0 d=2  →  0002
div p.intro             a=0 b=0 c=1 d=2  →  0012
#first                  a=0 b=1 c=0 d=0  →  0100   ← beats all of the above
#first p.intro:hover    a=0 b=1 c=2 d=1  →  0121
style="color:red"       a=1 b=0 c=0 d=0  →  1000   ← beats everything

Question style: "which colour is applied?" — compute abcd for each
rule that could match, take the largest. If TWO tie, go to location.

3. Location

When inheritance and specificity cannot decide, location does: with equal specificity, the later rule wins. Which is why an inline style overrides an embedded or external stylesheet, and why the last of two competing classes on an element is the one that applies.

Order of resolution, in three words: inherit → specificity → location. Ask them in that order and you can answer any “which rule wins” question mechanically instead of by intuition.

Box model, text, variables, tables and forms

Block vs inline

Block-levelInline
<p> <div> <h2> <ul> <table>normal text, <em> <a> <img> <span>
Each sits on its own line. Without styling, two block elements cannot share a line.Displayed within lines; does not form its own block.
Uses the normal CSS box model, with width and height.When there is not enough room on the line, content moves to a new line.

The box model

box modelSlides 37–42[ RUN IT → ]
   ┌─────────────────── MARGIN ──────────────────────┐  ← space AROUND the element
   │  ┌──────────────── BORDER ────────────────────┐ │     (divides margin from padding)
   │  │  ┌───────────── PADDING ─────────────────┐ │ │  ← space INSIDE the element
   │  │  │                                       │ │ │
   │  │  │             CONTENT                   │ │ │  ← width and height apply HERE ONLY
   │  │  │        (width × height)               │ │ │
   │  │  └───────────────────────────────────────┘ │ │
   │  └────────────────────────────────────────────┘ │
   └─────────────────────────────────────────────────┘

   TOTAL WIDTH = width + padding-left/right + border-left/right + margin-left/right
   ← this is why a 100%-wide box with padding overflows its parent.

/* Shorthand: 4 values, 2 values, or 1 */
.a { border-color: red green orange blue; }  /* top right bottom left — clockwise */
.b { border-color: red yellow; }             /* top+bottom = red, right+left = yellow */
.c { border-color: red; }                     /* all four sides */

/* Or set one side at a time */
.d { border-top-color: red; border-right-color: green;
     border-bottom-color: yellow; border-left-color: blue; }

/* The fix everybody uses: make width MEAN total width */
* { box-sizing: border-box; }

Block-level elements also have min-width, min-height, max-width and max-height, which matter when a width is expressed as a percentage of the parent. And overflow controls what happens when the box is not large enough for its content: visible (default), hidden, scroll, auto.

Text and fonts

text.cssSlides 43–50
/* A WEB FONT STACK: fallbacks, because your font may not be installed
   on the user's computer. Always end with a generic family. */
body {
    font-family: 'Roboto Slab', Georgia, 'Times New Roman', serif;
    font-size: 1rem;        /* rem = relative to the ROOT html element */
    font-weight: 400;        /* 100–900, or normal / bold */
    font-style: normal;      /* normal | italic | oblique */
    line-height: 1.7;
    text-align: left;
    text-decoration: none;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

/* Using a font that is NOT installed anywhere — two ways */
/* 1. a link in <head>:
      <link href="https://fonts.googleapis.com/css?family=Droid+Sans" rel="stylesheet">   */
/* 2. an @import at the TOP of a CSS file: */
@import url('https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400&display=swap');

CSS variables (custom properties)

Slide 52 shows a stylesheet where #431c5d, 4px, 5px, 18px and one long box-shadow are each repeated several times. Slide 53 rewrites it. This is the pattern to reproduce in labs.

variables.cssSlides 51–53
/* Declare in :root — names MUST begin with a double hyphen */
:root {
    --bg-color-main: #431c5d;
    --bg-color-secondary: #e05915;
    --fg-color-main: #e6e9f0;
    --radius-boxes: 5px;
    --padding-boxes: 4px;
    --fontsize-default: 18px;
    --shadow-color: rgba(0,0,0,0.22);
    --dropshadow: 6px 5px 20px 1px var(--shadow-color);  /* variables can use variables */
}

/* Read with the var() function */
header {
    background-color: var(--bg-color-main);
    color: var(--bg-color-secondary);
    padding: var(--padding-boxes);
    box-shadow: var(--dropshadow);
    margin: 0;
}
header button {
    background-color: var(--bg-color-secondary);
    border-radius: var(--radius-boxes);
    border-color: var(--fg-color-main);
    font-size: var(--fontsize-default);
    margin-top: calc(var(--fontsize-default) / 2);   /* note: var() INSIDE calc() */
}

Styling tables

tables.cssSlides 54–57[ RUN IT → ]
/* WHERE BORDERS CAN GO — an examinable fact:
   ✓ table, th, td
   ✗ tr, thead, tbody, tfoot   ← borders CANNOT be assigned to these */

table {
    border-collapse: collapse;   /* adjacent cells SHARE one border      */
    /* border-collapse: separate;  ← the DEFAULT: each cell has its own */
    width: 100%;
}
th, td { border: 1px solid #ccc; padding: 0.6rem; text-align: left; }

/* ZEBRA STRIPING with the nth-child pseudo-class */
tbody tr:nth-child(even) { background-color: #f4f0fa; }

/* ROW HIGHLIGHT on hover */
tbody tr:hover { background-color: #e6d8f5; }

Styling forms

forms.cssSlides 58–60
/* The common change described on slide 58: drop the border,
   round the corners, add padding. */
input[type="text"], input[type="email"], textarea {
    border: none;
    border-bottom: 2px solid #ccc;
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
    font: inherit;              /* controls do NOT inherit fonts by default */
}

input:focus { outline: 2px solid #b829ea; }

/* ::placeholder — the pseudo-element for the placeholder text */
input::placeholder { color: #948da3; font-style: italic; }

/* Labels on their own line, with a click target */
label { display: block; margin-bottom: 0.3rem; font-weight: 600; }

Layout — the screenshot slides, reconstructed

Slide 63 opens with a rule: tables were once used for page layout and this should never be done — it pollutes the HTML, makes SEO harder and is not maintainable.

Everything below this point is what the slide images contained. Nothing here is in the slide text, which is why this section is the one to work through with a browser open.

Flexbox — for one-dimensional layouts

Properties go in two places: on the flex container and on the flex items inside it. Any direct child of a flex container automatically becomes a flex item.

flex-intro.htmlSlides 63–65 — the example the slide names[ RUN IT → ]
<style>
  .flex-container {
      display: flex;                /* this ONE line creates the flex context */
      background-color: DodgerBlue;
      flex-direction: row;           /* row | row-reverse | column | column-reverse */
      flex-wrap: wrap;               /* wrap | nowrap (default) | wrap-reverse */
  }
  .flex-container > div {           /* direct children ARE the flex items */
      background-color: #f1f1f1;
      margin: 10px;
      font-size: 30px;
  }
</style>

<div class="flex-container">
  <div>1</div><div>2</div><div>3</div>
</div>

Container properties — the table from slides 65–66

PropertyValuesWhat it does
displayflex · inline-flexMakes the element a flex container. Nothing else works without it.
flex-directionrow · row-reverse · column · column-reverseSets the main axis. Everything else is described relative to it.
flex-wrapnowrap (default) · wrap · wrap-reverseWhether items may overflow onto more lines.
flex-flowrow wrapShorthand for direction + wrap.
justify-contentflex-start · flex-end · center · space-between · space-around · space-evenlyAligns items along the main axis.
align-itemsstretch (default) · flex-start · flex-end · center · baselineAligns items across the cross axis.
align-contentSame values as justify-contentAligns the lines when content has wrapped. No effect on a single line.
gapA lengthSpace between items, without margin arithmetic.

Item properties — slide 67

PropertyDefaultWhat it does
order0Reorders items visually without touching the HTML. Lower first.
flex-grow0Share of the leftover space this item takes. This is the fraction the slide mentions: grow 2 takes twice as much extra space as grow 1.
flex-shrink1How readily the item shrinks when there is not enough room. 0 = never shrink.
flex-basisautoThe item’s size before growing or shrinking — its starting width on a row.
flex0 1 autoShorthand for grow / shrink / basis. flex: 1 is the everyday one.
align-selfautoOverrides the container’s align-items for this item alone.
flex-basis.htmlSlide 67[ RUN IT → ]
.flex-container { display: flex; }

/* Give each child a FRACTION of the container — the slide 67 note */
.item-a { flex: 1; }   /* 1 share  → 1/6 of the free space */
.item-b { flex: 2; }   /* 2 shares → 2/6                    */
.item-c { flex: 3; }   /* 3 shares → 3/6                    */

/* Longhand equivalent of flex: 2 */
.item-b { flex-grow: 2; flex-shrink: 1; flex-basis: 0%; }

/* The centring everyone memorises: dead centre, both axes */
.centre { display: flex; justify-content: center; align-items: center; }
The one confusion to settle now: justify-content works along the main axis, align-items across the cross axis. With flex-direction: row that means justify = horizontal, align = vertical — but switch to column and they swap. Learn them as main/cross, never as horizontal/vertical.

Grid — for two-dimensional layouts

Every block-level child of a container with display: grid is automatically placed into a grid cell.

grid-structure.cssSlides 68–71
.container {
    display: grid;

    /* COLUMNS — the fr unit is a FRACTION of the free space */
    grid-template-columns: 1fr 1fr 1fr;        /* three equal columns   */
    grid-template-columns: 200px 1fr 1fr;      /* fixed + two flexible  */
    grid-template-columns: repeat(3, 1fr);     /* repeat() — same thing */
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    /*   ↑ responsive with NO media query: as many 240px-min columns as fit  */

    /* ROWS work identically */
    grid-template-rows: 100px 150px 100px;

    gap: 10px;                /* or row-gap / column-gap / grid-gap */
}
grid-placement.cssSlides 72–74[ RUN IT → ]
/* EXPLICIT PLACEMENT — count grid LINES, not cells.
   3 columns means 4 vertical lines: 1 2 3 4                       */

.header { grid-column: 1 / 4; }        /* from line 1 to line 4 = all 3 columns */
.header { grid-column: 1 / span 3; }   /* identical, written as a span         */
.header { grid-column: 1 / -1; }       /* identical: -1 is the LAST line       */

.sidebar { grid-row: 2 / 4; }          /* two rows tall                        */

/* CELL ALIGNMENT — slide 74.
   *-items on the CONTAINER sets the default for every cell;
   *-self  on an ITEM overrides it for that one cell.             */
.container { justify-items: center; align-items: center; }
.blue      { justify-self: start;  align-self: end; }
/*   justify = horizontal (along the row), align = vertical (down the column) */

Named areas — the full listing from slide 76

grid-areas.htmlSlides 76–77 — LISTING 7.2[ RUN IT → ]
<style>
.container {
    display: grid;
    grid-gap: 10px;
    grid-template-rows: 100px 150px 100px;
    grid-template-columns: 75px 1fr 1fr 1fr 1fr;

    /* Each STRING is a row; each WORD is a column.
       A name repeated across adjacent cells makes one merged area.
       A dot ( . ) leaves that cell empty.                         */
    grid-template-areas: ".  a1 a2 a3 a4"
                         "b1 b2 b2 b2 b3"     /* b2 spans 3 columns */
                         "b1 c1 c2 c2 c2";    /* b1 spans 2 rows    */
}
.a1 { grid-area: a1; }   .b1 { grid-area: b1; }   .c1 { grid-area: c1; }
.a2 { grid-area: a2; }   .b2 { grid-area: b2; }   .c2 { grid-area: c2; }
.a3 { grid-area: a3; }   .b3 { grid-area: b3; }
.a4 { grid-area: a4; }
</style>

<section class="container">
  <div class="yellow a1">A1</div>  <div class="yellow a2">A2</div>
  <div class="yellow a3">A3</div>  <div class="yellow a4">A4</div>
  <div class="orange b1">B1</div>  <div class="orange b2">B2</div>
  <div class="orange b3">B3</div>  <div class="cyan c1">C1</div>
  <div class="cyan c2">C2</div>
</section>

Grid and flexbox together — the decision rule

Grid builds the layout structure of the page. Flexbox lays out the contents of a grid cell. That single sentence from slide 78 answers the "which should I use" question in an exam, and it is also just good practice: grid is two-dimensional, flexbox is one-dimensional.

together.cssSlide 78[ RUN IT → ]
/* GRID for the page skeleton */
.page {
    display: grid;
    grid-template-columns: 240px 1fr;
    grid-template-rows: 64px 1fr auto;
    grid-template-areas: "head head"
                         "side main"
                         "foot foot";
    min-height: 100vh;
}

/* FLEXBOX inside one of those cells */
.page > header {
    grid-area: head;
    display: flex;
    align-items: center;             /* vertical centring within the bar */
    justify-content: space-between;  /* logo left, actions right         */
    gap: 1rem;
}

Responsive design

In a responsive design the page responds to changes in browser size beyond simple percentage scaling: smaller images are served, and navigation elements are replaced as the window shrinks.

The viewport — memorize this tag

every page you writeSlides 80–81
<meta name="viewport" content="width=device-width, initial-scale=1">
                              ↑ size of the viewport   ↑ zoom level

WHY: the viewport is the part of the browser window that shows web content.
Mobile browsers DEFAULT to scaling a whole desktop-width page down to fit the
screen. The result works, but is very difficult to read and use. This tag tells
the browser to use the device's real width instead — after which your media
queries actually fire.

Media queries

A media query applies style rules based on the medium displaying the file. Contemporary responsive sites give rules for phones first, then tablets, then desktops — an approach the slide names progressive enhancement.

responsive.cssSlides 82–83
/* MOBILE FIRST: the base rules are the phone layout.
   No media query needed — this is the default. */
.page { display: grid; grid-template-columns: 1fr; }
nav ul { display: none; }          /* nav replaced by a menu button */

/* TABLET and up */
@media (min-width: 600px) {
    .page { grid-template-columns: 200px 1fr; }
    nav ul { display: flex; gap: 1.5rem; }
}

/* DESKTOP and up */
@media (min-width: 1024px) {
    .page { grid-template-columns: 240px 1fr 300px; }
}

/* Other media types and features you can query */
@media print                    { nav, footer { display: none; } }
@media (orientation: landscape) { /* … */ }
@media (prefers-color-scheme: dark) { /* … */ }

Images: scaling is not the same as downloading less

picture.htmlSlide 84
/* Making an image SCALE is one line — but the browser still downloads
   the full-size file. On a phone that is wasted bandwidth. */
img { max-width: 100%; }

<!-- <picture> (HTML5.1) lets you offer SEVERAL images and lets the
     browser choose which one to download, based on viewport size. -->
<picture>
  <source media="(min-width: 1024px)" srcset="banner-large.jpg">
  <source media="(min-width: 600px)"  srcset="banner-medium.jpg">
  <img src="banner-small.jpg" alt="Campus banner">  <!-- fallback, always last -->
</picture>
The distinction slide 84 is testing: max-width: 100% changes how big the image looks. <picture> changes which file gets downloaded. Only the second one saves the user's data.

The eight things people get wrong

Guessing specificity instead of computing it

You assume the last rule wins, but a rule further up with an id in it is beating it. Location only applies after specificity ties.

Fix: Compute a-b-c-d for every competing rule and compare left to right. One id (0-1-0-0) beats nine classes (0-0-9-0).

A 100%-wide box that overflows its parent

width: 100% plus padding: 1rem plus a border is wider than the parent, because width sizes the content area only.

Fix: Either subtract the padding yourself, or set box-sizing: border-box so width means the full outside width. This is why almost every stylesheet starts with * { box-sizing: border-box; }.

Treating justify-content as "horizontal"

It is horizontal only while flex-direction is row. Switch the container to column and justify-content becomes vertical, so a layout that centred correctly suddenly does not.

Fix: Learn them as main axis (justify) and cross axis (align). The direction sets which is which.

Counting grid cells instead of grid lines

grid-column: 1 / 3 spans two columns, not three, because those numbers are line numbers. Three columns are bounded by four lines.

Fix: Sketch the lines and number them, or avoid the arithmetic entirely with span: grid-column: 1 / span 3. And -1 always means the last line.

Media queries that never fire on a phone

Your breakpoints work perfectly when you resize the desktop browser but do nothing on an actual phone. The viewport meta tag is missing, so the mobile browser is rendering at a fake desktop width and scaling the result down.

Fix: Put <meta name="viewport" content="width=device-width, initial-scale=1"> in the <head> of every page. Nothing responsive works reliably without it.

Putting a border on a <tr>

Nothing happens, and it looks like a CSS bug. Slide 54 states it directly: borders can be assigned to <table>, <th> and <td>, and cannot be assigned to <tr>, <thead>, <tfoot> or <tbody>.

Fix: Style the cells instead: tr:hover td { ... } or a border-bottom on every td in the row.

Link styles that stop working when you reorder them

Writing a:hover before a:visited means a visited link never shows its hover colour — both selectors have the same specificity, so the later one wins.

Fix: Keep the order :link, :visited, :hover, :active. It is a location problem wearing a costume.

Expecting form controls to inherit the page font

You set font-family on body and every input still renders in the browser’s default. Font properties inherit, but form controls are a documented exception.

Fix: Add input, select, textarea, button { font: inherit; } — this is exactly the use case for the inherit keyword on slide 29.

Chapter 3 on a single screen

Selector types

  • p element · * universal
  • .class many · #id one
  • p, div group
  • [attr] [a="v"] [a~="w"]
  • [a^=] starts · [a*=] contains · [a$=] ends

Combinators

  • a b — descendant, anywhere inside
  • a > b — direct child
  • a + b — next sibling
  • a ~ b — all following siblings

Cascade order

  • 1. Inheritance — font/color/list/text yes; layout/size/border/background/spacing no
  • 2. Specificitya=inline b=id c=class/attr d=element
  • 3. Location — later wins on a tie

Box model

  • content → padding → border → margin
  • width sizes the content only
  • 4 values = top right bottom left
  • 2 values = top/bottom, right/left
  • box-sizing: border-box fixes the maths

Flex container

  • display: flex
  • flex-direction row | column (+reverse)
  • flex-wrap nowrap | wrap
  • justify-content — main axis
  • align-items — cross axis
  • gap

Flex item

  • flex: grow shrink basis (0 1 auto)
  • flex: 1 — equal share of free space
  • order — visual reordering
  • align-self — override for one item

Grid

  • display: grid
  • grid-template-columns: 1fr 1fr
  • repeat(3, 1fr) · minmax(240px, 1fr)
  • grid-column: 1 / 4 — LINE numbers
  • 1 / span 3 · 1 / -1
  • grid-template-areas + grid-area

Responsive

  • <meta name="viewport" content="width=device-width, initial-scale=1">
  • @media (min-width: 600px) { }
  • Phone first, then tablet, then desktop
  • img { max-width: 100% } scales
  • <picture> downloads less

Variables

  • Declare in :root, names start --
  • Read with var(--name)
  • Variables may reference variables
  • calc(var(--x) / 2)

Build these, do not read about them

Layout is not learnable by reading, and this is the chapter where that bites hardest, because the layout slides are pictures. Open a file, open the browser, and build.

  1. Write the same rule three ways: inline, embedded and external. Then explain in one sentence why external wins.
  2. Write one selector for each of the six attribute operators, and say in words what each matches.
  3. Style a link’s four states in the correct order, then deliberately reorder them and observe what breaks.
  4. Complete the slide 23 task: colour the last child of a ul red, and style every <a> whose href contains “example”.
  5. Given four rules that all match one element, compute abcd for each and predict the winner. Then check in DevTools — the Styles panel strikes through the losers.
  6. Build a box with an explicit width, padding and border. Measure the real rendered width in DevTools, then add box-sizing: border-box and measure again.
  7. Convert a stylesheet with five repeated values into CSS variables declared in :root.
  8. Style a table: collapsed borders, zebra striping with nth-child, and a hover highlight on rows.
  9. Build a flex row of five items, then use flex: 1 / 2 / 3 to give three of them different shares of the free space.
  10. Centre a box perfectly in the viewport using three lines of flexbox.
  11. Take that same flex container, switch it to column, and predict what happens to justify-content before you reload.
  12. Build a three-column grid with repeat(auto-fit, minmax(240px, 1fr)) and resize the window — a responsive layout with no media query.
  13. Reproduce the slide 76 named-areas layout exactly, then move one area by editing only the grid-template-areas strings.
  14. Build a page skeleton with grid and lay out its header with flexbox, following the slide 78 rule.
  15. Write a mobile-first stylesheet with breakpoints at 600px and 1024px, then delete the viewport meta tag and test it on a phone to see what happens.

Worked examples for almost all of this already sit in your study material: the CSS example folder, the CSS layout handout with exercises, and the two solved CSS labs (lab 03a, lab 03b). Slide 85 also gives the repository for every chapter’s code: github.com/skanderturki/se371.

Can you answer these without scrolling up?

Question 1