Web development module 2: CSS, the art of styling
Fourteen sessions to give shape to your pages: plug in a stylesheet, aim precisely with selectors, master the box model, lay out columns with flexbox and grid, and make it all responsive with a dark mode. Same method as ever: 20 minutes of theory, 30 of practice, 10 of recap.
Day 15 — Plugging in a stylesheet
Goal: create a CSS file, link it to your page, and understand what a CSS rule is.
Theory (20 min)
CSS (Cascading Style Sheets) is the language that describes appearance: colors, sizes, spacing, layout. HTML says what the content is, CSS says what it looks like. This separation is the most important principle of the craft: you change a site's whole look without touching its HTML.
CSS lives in its own file, by convention style.css, linked to the page by a <link> tag in the <head>:
<link rel="stylesheet" href="style.css">
CSS is made of rules. A rule has three parts: a selector (what to aim at), and between braces some declarations of the form property: value;:
h1 {
color: darkblue;
text-align: center;
}
This rule says: "every <h1>: dark blue text, centered". The semicolon ends each declaration — forgetting it breaks the next declaration; it is the number one CSS typo of beginners.
The "C" in CSS means cascade: when several rules aim at the same element, the browser settles the conflict by priority (tomorrow) and, at equal priority, the last one written wins.
Practice (30 min)
- In your
devwebfolder, create amodule2folder. Copy your day-13me.htmlinto it, and create an emptystyle.cssnext to it. - In
me.html, add the<link>tag above inside the<head>, under the<title>. - In
style.css, write theh1rule above. Save both files, reload. Success criterion: your main heading is dark blue and centered — your first style. - Add
p { line-height: 1.6; }(line spacing, as a multiple of the text size): your paragraphs breathe. - Change the
hrefpath to a wrong name, reload: all the style disappears. Open the developer tools console (F12): a 404 error onstyle.cssis displayed. This is how you diagnose a stylesheet that "doesn't work". Repair it.
Agent tips: "my page lost all its style, here is my head and my console: [paste]" — the diagnosis is immediate. Trap: paste only the HTML without the console error, and it will guess. Proof to demand: the exact cause (path, case, typo), not a rewritten style.
Recap (10 min)
Three lines: the three parts of a CSS rule, where the link tag lives, what "cascade" means. Then plug a stylesheet from memory onto a fresh file.
Day 16 — Selectors: aiming right
Goal: use element, class, id and descendant selectors, and understand priority.
Theory (20 min)
The selector chooses the elements the rule styles. The four basic ones:
- Element:
paims at every<p>. - Class:
.calloutaims at any element carryingclass="callout". The class is an attribute you can reuse at will, made for this: grouping what shares a style. It is the selector you will write most. - ID:
#introaims at the element carryingid="intro"— unique per page (the sameidas anchors use). - Descendant: a space between two selectors —
.callout paims at the<p>s inside an element of classcallout.
.callout { background: #eee; }
.callout p { margin: 0; }
#intro { font-size: 1.2rem; }
When two rules aim at the same element with contradictory declarations, specificity settles it: id beats class, class beats element. At equal specificity, the last rule in the file wins. Practical consequence: style with classes, keep ids for anchors and JavaScript, and you will avoid 90 % of priority wars.
Which wins between p { color: blue; } and .info { color: green; } on <p class="info">?
- blue, written first
- green: a class is more specific than an element
- blue and green mix
Answer
green: class > element in specificity, regardless of order.
Practice (30 min)
- In your
me.html, addclass="callout"to the div around a paragraph you want to highlight (or create one), and the two rules above intostyle.css. - Reload. Success criterion: only the callout paragraph has a greyed background; your other paragraphs are untouched — proof the class selector aims right.
- Add
#contact { border-top: 2px solid; }after givingid="contact"to your form section: a line appears above it only. - Test specificity: write
.callout { color: red; }thenp { color: blue; }below it. The callout paragraph stays red — order does not beat specificity. Delete this test. - Inspect (F12) the callout paragraph: the "Styles" panel lists the rules that apply and strikes through the losing ones. Read it: it is the best cascade teacher that exists.
Agent tips: "why does my rule X not apply while Y applies?" — paste both rules AND the element's HTML. Trap: without the HTML it cannot compute specificity and improvises. Proof: compare its explanation with the inspector's Styles panel, which never lies.
Recap (10 min)
Three lines: the four selectors, the specificity rule, why classes win the habit. Then write from memory a selector that aims at the links of a list of class menu.
Day 17 — Colors and units
Goal: write colors in hexadecimal and rgb, and pick the right size unit.
Theory (20 min)
Three ways to write a color. Names (red, darkblue, rebeccapurple…): readable, but only 148 exist. Hexadecimal: #1e90ff — six hex digits (0-9 then A-F) in pairs: red, green, blue, each from 00 to FF (255). #ff0000 is pure red, #000000 black, #ffffff white. The rgb(30, 144, 255) notation says the same in decimal, with a variant rgba(..., 0.5) whose fourth number is opacity from 0 (transparent) to 1 (opaque).
For sizes, four units to know:
px: the pixel, fixed, easy to reason about — but it ignores the user's accessibility settings;rem: the root size (16 px by default, changeable by the user in their browser) — the recommended unit for text, because it respects that setting;%: a percentage of the parent's size (or width, depending on the property);vh/vw: hundredths of the window height/width (viewport) — handy for full-screen banners.
A simple convention to start: text in rem, spacing in rem or px, widths in % or viewport units.
Which unit respects the browser's "text size" setting?
- px
- vh
- rem
Answer
rem: it computes from the base size, which the user can enlarge. px ignores it.
Practice (30 min)
- In
style.css, givebodya very light background (background: #faf7f2;) and an almost-black text color (color: #222;) — pure black on pure white strains the eye. - Pick an accent color (with the inspector's color picker: click the color swatch in the Styles panel) and apply it to your
h2s and your links (a). - Switch paragraph size to rem:
p { font-size: 1rem; }, and theh1to2.5rem. - Success criterion: in your browser settings, raise the default font size and reload: your rem texts grow. Switch one heading to
px, reload: it no longer moves. You have seen the difference. Put everything back to rem. - Note your three colors (background, text, accent) in the notebook with their hex code: the start of your design palette.
Agent tips: "suggest three background/text/accent palettes for a sober personal site, in hex" is a good creative use. Trap: it cannot know whether the contrast is enough. Proof: test every text/background pair on webaim.org/resources/contrastchecker (module 4), keep only what passes.
Recap (10 min)
Three lines: the three color notations, the four units, why rem for text. Then convert in your head: what is FF in decimal? (255.)
Day 18 — Typography
Goal: compose readable text: font, size, weight, line height, line length.
Theory (20 min)
Typography is 90 % of the design of a content site. Five properties do most of it:
font-family: the font. You list several in cascade — if the first is missing on the visitor's machine, the next is tried:font-family: Georgia, "Times New Roman", serif;. Names with spaces take quotes. The generic familiesserif,sans-serifandmonospaceat the end of the list are the safety net: the browser chooses.font-size: the size, in rem (day 17).font-weight: the weight,normal(400) orbold(700).line-height: the line spacing, unitless (a multiple of the text size):1.5to1.7for body text.max-widthon the text container: the golden rule wants lines of 60 to 75 characters; beyond that, the eye loses the thread coming back to the next line.max-width: 65ch;— thechunit is the width of one character.
"System" fonts (those already installed on the machine: Arial, Georgia, Courier…) are free, instant, and largely enough to start. Downloaded fonts (Google Fonts and the like) exist, but they cost loading time and raise privacy questions — module 4 will show why you will gladly skip them.
Why write font-family: Georgia, serif; with two values?
- If Georgia is missing, the browser picks a serif font of its choice
- Georgia for headings, serif for text
- It is a mistake, one font per rule
Answer
It is a fallback cascade: first available wins, serif is the generic net.
Practice (30 min)
- In
style.css, compose your base:body { font-family: system-ui, sans-serif; font-size: 1rem; line-height: 1.6; }.system-uiis a special value: the visitor's system interface font — always present, never downloaded. - Give headings a contrasting font:
h1, h2, h3 { font-family: Georgia, serif; line-height: 1.2; }. Yes, you can list several selectors separated by commas. - Limit content width:
main { max-width: 65ch; margin: 0 auto; }—margin: 0 autocenters a block whose width is limited. Reload: the text forms a centered, readable column. - Success criterion: reread your whole page: no line exceeds ~75 characters, the line spacing breathes, headings and text differ at a glance.
- Test degradation: replace
Georgiawith a font name that does not exist, reload: the page falls back to the generic font without breaking. Put Georgia back.
Agent tips: "review this CSS and tell me why my lines are too long" works well. Trap: it may rewrite your whole style "along the way". Proof: accept only a minimal diff — the faulty line quoted, not a rewritten file.
Recap (10 min)
Three lines: the five properties, the 60-75 character rule, why system fonts first. Then rewrite your body block from memory.
Day 19 — The box model
Goal: break any element down into content, padding, border, margin — and tune its spacing.
Theory (20 min)
To the browser, every element is a box of four nested layers, from inside out:
- the content: the text, the image;
- the padding: the space between the content and the border, inside the box — it takes the background color;
- the border: the line around, which may be invisible;
- the margin: the space outside, pushing neighbors away — always transparent.
.callout {
padding: 1rem; /* inner breathing room */
border: 1px solid #ccc;
margin-bottom: 2rem; /* space with what follows */
}
The three properties accept one to four values: one for all four sides, or four clockwise from the top (margin: 1rem 0 2rem 0;), and per-side variants: margin-top, padding-left…
One subtlety: two touching vertical margins collapse — a paragraph with a 2 rem bottom margin followed by a heading with a 1 rem top margin end up 2 rem apart, not 3. Not a bug: the larger wins.
The inspector (F12, "Computed" panel) draws the selected element's box model in colors: it is the X-ray of your spacing.
Practice (30 min)
- Give your
.calloutthe three properties above, plus a light background. Reload. - Inspect the callout, open the Computed panel: identify the box's four zones and their sizes. Success criterion: you can point on the diagram at your padding, your border and your margin.
- Play: set padding to 0 then to 3 rem, and watch the content squeeze then breathe. The padding/margin difference is now visible to the eye.
- Space your sections:
section { margin-bottom: 3rem; }, then observe margin collapse by adding a bottom margin to a section's last element. - Give
bodyapadding: 0 1rem;so text never touches the window edges on mobile.
Agent tips: "why is there a gap between these two blocks?" — paste both blocks' CSS. Trap: it may forget margin collapse in its explanation. Proof: check the Computed panel, which shows real margins.
Recap (10 min)
Three lines: the four layers, padding vs margin, vertical margin collapse. Then draw the box from memory, with a numbered example.
Day 20 — Display and box-sizing
Goal: change an element's display behavior and understand how sizes are computed.
Theory (20 min)
On day 8 you learned that every element is block or inline. The display property changes that:
display: block;forces block behavior (a link<a>spanning a menu's full width);display: inline-block;is the hybrid: the element stays in the text flow but accepts width, height and vertical margins — handy for aligned buttons;display: none;removes the element entirely: invisible AND gone from the layout (module 3's JavaScript will use it to show/hide).
Second notion, the one that saves hours: box-sizing. By default (content-box), width only sets the content: a box with width: 200px plus 20 px of padding and a 2 px border actually measures 244 px wide. The border-box mode includes padding and border in the declared width: the box is 200 px, period. So much more intuitive that nearly every project starts with:
*, *::before, *::after {
box-sizing: border-box;
}
The * selector aims at all elements. Remember this rule exists without making it a religion: above all, understand that there are two ways to count sizes, and border-box is the less surprising one.
With box-sizing: border-box, a box with width: 100px; padding: 10px; measures in total…
- 120 px
- 110 px
- 100 px
Answer
100 px: the padding is included in the declared width.
Practice (30 min)
- Add the
box-sizingrule above at the very top ofstyle.css. - In your nav, switch the links to
display: block;with some padding: the whole strip becomes clickable, not just the word. On a menu, that is a real comfort gain. - Create two side-by-side divs in your main with the class
demo, give themdisplay: inline-block; width: 45%;and a different background each. Success criterion: they fit on the same line. - Switch back to
content-box(comment out the universal rule) and watch your boxes change real size without the CSS changing. Re-enableborder-box. - Temporarily give your footer
display: none;: it disappears from the page AND its empty space closes up. Remove the rule.
Agent tips: "my box overflows its parent even though width is 100 %" — an agent knows the cause (content-box) by heart. Trap: it may answer with flexbox when the cause is box-sizing. Proof: the proposed fix must be minimal and you reproduce it by hand.
Recap (10 min)
Three lines: today's three display values, content-box vs border-box, what the * selector does. Then compute in your head a box's real width in both modes.
Day 21 — Backgrounds and borders
Goal: dress the boxes: background color, borders, rounded corners, discreet shadows.
Theory (20 min)
Three property families give boxes their relief:
- Background:
background-color(which you know) andbackground-image: url("pattern.png");. A gradient needs no image:background: linear-gradient(to right, #1e90ff, #7ec8ff);. - Border: the shorthand
border: 1px solid #ccc;packs thickness, style (solid, dashed, dotted…), color.border-radiusrounds corners:border-radius: 8px;, and50%on a square gives a circle — the classic trick for round avatars. - Shadow:
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);— horizontal offset, vertical offset, blur, color. A soft, discreet shadow makes the element "float"; a strong shadow makes a 2005 website.
Assembled, these properties make a "card", the web's most common component:
.card {
background: #fff;
border: 1px solid #e3e0da;
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
Keep the discipline: one card style defined ONCE on a class, reused everywhere. Visual coherence comes from repeating the same few decisions, not from inventing at every box.
Practice (30 min)
- Create the
.cardclass above and apply it to two or three blocks of your page (a section, your callout). - Reload. Success criterion: your cards have a white background, rounded corners and a light, even shadow.
- If you have an image, try the round avatar:
.avatar { border-radius: 50%; width: 96px; height: 96px; object-fit: cover; }—object-fit: coverfills the frame without distorting the photo. - Try a gradient on the header:
header { background: linear-gradient(135deg, #1e3a5f, #1e90ff); color: white; }. Judge with your eyes: if the text becomes hard to read, keep the gradient or go back to flat — both are choices. - Test zero:
border: none;on an element, to see how "remove" is written.
Agent tips: "write a sober card style with a discreet shadow" gives a good starting point. Trap: generated shadows are often too heavy. Proof: enforce the criterion "shadow visible only if you look for it" and tune the blur yourself.
Recap (10 min)
Three lines: the three property families, the circle trick, why a single .card class. Then rewrite the card style from memory.
Day 22 — Flexbox: aligning on one axis
Goal: align and distribute elements on a row (or a column) with flexbox.
Theory (20 min)
Flexbox solves a simple problem: laying elements side by side (or stacked) while controlling alignment and spacing. You declare a flexible container, and its direct children become flexible:
.row {
display: flex;
gap: 1rem; /* space between children */
justify-content: center; /* distribution on the main axis */
align-items: center; /* alignment on the cross axis */
}
Three ideas to keep:
- The main axis is horizontal by default (
flex-direction: row);flex-direction: columnmakes it vertical. Properties are always reasoned against this axis. justify-contentdistributes on the main axis:flex-start,center,flex-end, and above allspace-between(ends glued to the edges, space spread between) — the navbar tool.align-itemsaligns on the cross axis:centercenters vertically in a row — the answer to "how do I center vertically?", the question that blocked a generation of developers before flexbox.
On children, one property: flex: 1; says "take your equal share of the remaining space". Three children with flex: 1 split the width into equal thirds.
With display: flex, on which element do you write justify-content?
- On each child
- On the container
- On the body
Answer
On the container: it is the one distributing its children.
Practice (30 min)
- In your page, take the div holding your two or three cards (or create it:
<div class="row">around them) and apply the rules above to it. - Reload. Success criterion: your cards are side by side, aligned, with a regular gap between them.
- Try each value of
justify-contentin turn (flex-start, center, space-between, space-around) and watch the distribution change. Keep the one you like. - Give the cards
flex: 1;: they stretch to fill the width in equal shares. - Switch the container to
flex-direction: column;, observe, come back to row. You now know what each property controls.
Agent tips: "here is my HTML and my CSS, my cards won't align, why?" — paste both. Classic trap: the display: flex rule on the cards instead of the container; the agent spots it at once. Proof: move the rule yourself and reload.
Recap (10 min)
Three lines: container vs children, justify-content vs align-items, what flex: 1 does. Then reproduce a row of three equal boxes from memory.
Day 23 — Flexbox in practice: the navbar
Goal: build the classic navigation bar: site name on the left, links on the right.
Theory (20 min)
The header navbar is the quintessential flexbox exercise: the site name glued left, the links grouped right. The HTML structure is a list of links inside the <nav>:
<header class="site-header">
<p class="logo">My site</p>
<nav>
<ul class="menu">
<li><a href="index.html">Home</a></li>
<li><a href="me.html">About</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</nav>
</header>
And the CSS: two nested flex containers — the header pushes logo and nav to opposite ends, the menu aligns its links:
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem;
}
.menu {
display: flex;
gap: 1.5rem;
list-style: none; /* removes the bullets */
margin: 0;
padding: 0;
}
list-style: none removes the bullets: the list stays a list in meaning (a screen reader announces "list of three items"); only the visual bullet disappears.
Choosing a list for a menu is no whim: a menu IS a list of links. HTML states the meaning, CSS decides it displays in a row.
Practice (30 min)
- Restructure your page's header following the model above, with your real links.
- Apply the CSS, reload. Success criterion: the site name is on the left, the links aligned on the right, bullet-free, and everything stays clickable.
- Add a hover effect:
.menu a:hover { text-decoration: underline; }.:hoveris a pseudo-class: it aims at the element only while the mouse hovers it. - Shrink the window to minimum width: the bar crams. Fix nothing yet — tomorrow, grid, and on day 25, media queries will settle this properly. Just note the problem in the notebook.
- Check with the keyboard: the Tab key must step through the links one by one with a visible outline. If the focus is invisible, that is a defect to fix in module 4 — note it.
Agent tips: "write the CSS for a flex header: logo left, menu right, links without bullets" gives exactly this code. Trap: it may forget list-style: none or put it on the li instead of the ul. Proof: reload — the bullets must be gone and the links clickable.
Recap (10 min)
Three lines: the role of the two flex containers, why a list for a menu, what a pseudo-class is. Then redo the navbar from memory.
Day 24 — Grid: laying out a grid
Goal: create a two-dimensional layout with CSS Grid.
Theory (20 min)
Flexbox aligns on ONE axis; Grid lays out a grid in two dimensions — rows AND columns. It is the tool for whole-page layouts and galleries:
.gallery {
display: grid;
grid-template-columns: 1fr 1fr 1fr; /* three equal columns */
gap: 1rem;
}
The fr (fraction) unit shares the available space: 1fr 1fr 1fr makes three equal columns, 2fr 1fr a column twice the other. The container's children fill the cells automatically, left to right, creating rows as needed.
Two precious shortcuts: repeat(3, 1fr) equals 1fr 1fr 1fr; and above all repeat(auto-fill, minmax(200px, 1fr)) — the grid computes by itself how many columns of at least 200 px fit the available width, and stretches them. A responsive gallery with no media query:
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
Rule of choice between the two tools: flexbox for ONE row or ONE column of things (menu, button group, centering); grid for a two-dimensional plan (whole page, card gallery). They combine without trouble: a grid whose each cell holds a flex container.
For a photo gallery whose column count depends on screen width, the best base is…
- grid with repeat(auto-fill, minmax(200px, 1fr))
- flex with flex: 1 on each photo
- an HTML table
Answer
Grid with auto-fill/minmax: the column count adapts by itself, with no media query.
Practice (30 min)
- Replace your cards' flex container with the three-column
.gallerygrid. Reload: three equal, spaced columns. - Switch to the
auto-fill / minmaxversion and slowly shrink the window width. Success criterion: columns drop from three to two to one all by themselves, without you writing any media query. - Play with the minimum size: 150 px then 300 px, and watch the breaking point move. Keep the value that suits your content.
- Structure bonus: try a whole-page layout —
main { display: grid; grid-template-columns: 2fr 1fr; gap: 2rem; }with an<aside>after your content: wide column + narrow column.
Agent tips: "flex or grid for this need: [describe the layout]?" is a good design question. Trap: it often answers grid out of habit. Proof to demand: a one-sentence justification by the number of axes of the need — one axis = flex, two = grid.
Recap (10 min)
Three lines: the fr unit, the auto-fill/minmax formula, the flex vs grid rule of choice. Then write the responsive gallery from memory.
Day 25 — Responsive: media queries
Goal: adapt the layout to screen width, thinking mobile first.
Theory (20 min)
Responsive: the page adapts to the screen width — phone, tablet, monitor. The tool is the media query: a block of CSS that applies only if a condition is true, most often a minimum width:
/* base styles: designed for a phone, one column */
.gallery { display: grid; gap: 1rem; }
@media (min-width: 600px) {
/* from 600 px wide: two columns */
.gallery { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 900px) {
.gallery { grid-template-columns: 1fr 1fr 1fr; }
}
This approach is called mobile first: the base style targets the small screen (the most constrained), and media queries add columns as room grows. The reverse (starting big and removing) leads to cascades of patches.
Two indispensable technical points. First, the viewport meta tag, to have in the <head> of every responsive page:
<meta name="viewport" content="width=device-width, initial-scale=1">
Without it, mobile browsers simulate a ~980 px screen then zoom out: your responsive site would never kick in. Second, the breakpoints: 600 px and 900 px are common landmarks, but the right breakpoint is where YOUR layout turns ugly — widen the window and look.
The developer tools have a "device" mode (Ctrl+Shift+M) that simulates a phone: it will become your checking reflex.
Practice (30 min)
- Add the viewport meta to your page's
<head>if it is not there. - Replace your grid with the mobile-first version above: one column by default, two at 600 px, three at 900 px.
- Open device mode (Ctrl+Shift+M), pick a phone, reload. Success criterion: on the simulated phone, everything reads with no horizontal scrolling; widen the window and watch the columns appear at both breakpoints.
- Give your header the same treatment: under 600 px,
flex-direction: column;to stack logo and menu (the problem noted the day before yesterday is solved here). - Test your images: if one overflows, the rule
img { max-width: 100%; height: auto; }contains them all inside their box. One of those rules that goes into every project.
Agent tips: "make this page responsive, mobile first, breakpoints 600 and 900" is a clear order. Trap: it may forget the viewport meta — without it, everything else is invisible on phones. Proof: the dev tools device mode, not its claims.
Recap (10 min)
Three lines: what a media query is, why mobile first, the viewport meta's role. Then rewrite the responsive grid from memory.
Day 26 — CSS variables and dark mode
Goal: centralize your colors in CSS variables and offer a dark mode that follows the system.
Theory (20 min)
A CSS variable (custom property) is a named value, defined once and used everywhere. You declare them on :root (the document root, visible everywhere) with a name starting with two dashes, and read them with var():
:root {
--bg: #faf7f2;
--text: #222;
--accent: #1e5fa8;
}
body {
background: var(--bg);
color: var(--text);
}
a { color: var(--accent); }
Change the variable, the whole site follows: the end of "search and replace" in the stylesheet.
Dark mode is a media query of a new kind: prefers-color-scheme reads the user's system setting (their phone or computer is in dark or light mode):
@media (prefers-color-scheme: dark) {
:root {
--bg: #17181c;
--text: #e8e6e3;
--accent: #7db4f0;
}
}
Since all the style reads the variables, redefining the three variables is enough: the whole page flips. Notice the accent changes too: a blue readable on a light background is often too dark on a dark one — dark mode is not a simple negative, colors are re-chosen.
Practice (30 min)
- Take your three colors from the notebook (day 17) and replace them throughout
style.csswith the three variables above. Reload: nothing must change visually. Success criterion 1: change--accentand watch links and headings change together. - Add the
prefers-color-scheme: darkblock with your dark colors (very dark background but not pure black, light text but not pure white). - Switch your system to dark mode (computer settings) and reload: your site flips. Success criterion: the site follows the system both ways.
- Hunt the leftovers: a color hardcoded somewhere (a border, a card background) will stay light in dark mode — the inspector helps you find it. Replace it with a variable, even if it means creating
--card-bg.
Agent tips: "replace every hardcoded color in this CSS with :root variables" is a safe refactor. Trap: it will miss one in a corner. Proof: flip to dark mode and look for the remaining light stain — that is the one.
Recap (10 min)
Three lines: variable syntax, what prefers-color-scheme reads, why dark mode re-chooses colors. Then add a fourth variable from memory.
Day 27 — Mini-project: style your personal page
Goal: apply the whole module to your day-13 page: palette, cards, navigation, responsive, dark mode.
Theory (20 min)
No new notion: a spec and a method. The spec — your personal page me.html must have:
- a palette of three variables (background, text, accent) in
:root; - day-18 typography (system fonts, line height, a 65 ch column);
- the day-23 flex navbar;
- content organized in cards laid on a responsive grid;
- contained images (
max-width: 100%); - an automatic dark mode;
- the viewport meta.
The method: one thing at a time, reload between each. A problem? Inspect the element: the Styles panel says which rules apply and which lose. 90 % of "my CSS doesn't work" is readable right there.
Practice (30 min)
- Work point by point in the spec's order, reloading between each.
- Success criterion: the seven points are visible, the page reads comfortably in device mode on a phone AND a large screen, and the dark flip leaves no light stain.
- Get a review: show the page to someone for ten seconds, ask what they remember. If they remember the essential, your visual hierarchy works.
Agent tips: at the end only: "review this CSS like a proofreader: inconsistencies, duplicates, hardcoded colors?". Trap: it will propose full redesigns. Proof: accept only the list of defects quoted line by line — taste choices stay yours.
Recap (10 min)
Three lines: the longest point, what the inspector taught you, what you are proud of. This page is the base of the module 4 site.
Day 28 — Module 2 review
Goal: check the CSS skills before JavaScript.
Theory (20 min)
Test yourself without notes:
- Write a complete CSS rule and name its three parts.
- Who wins: a class or an id? And at equal specificity?
- Why
remrather thanpxfor text? - Draw the box model with its four layers.
- What is the difference between
justify-contentandalign-items? - When pick grid rather than flex?
- What does
@media (min-width: 600px)do, and why mobile first? - How does your site know the system is in dark mode?
Practice (30 min)
- Take the eight-question test in writing, without notes.
- For each failed question, redo the practice of the matching session.
- Success criterion: eight right answers, or the missing sessions redone.
- Timed drill: open a blank page, and in fifteen minutes, build three cards on a responsive grid with dark mode. Time yourself: this is the gesture module 3 will reuse.
- Tidy up: the whole module into your
module2folder.
Agent tips: "quiz me on CSS: selectors, box model, flex, grid, responsive — one question at a time, wait for my answer" works very well. Trap: it may ask off-syllabus questions (animations, preprocessors). Proof: rein it in — "only this syllabus: [paste your table of contents]".
Recap (10 min)
Three lines: your three skills, the fragile notion to watch. Tomorrow: JavaScript, and your pages start reacting.
Found this useful? Tell us what to measure next.
Comments
No account, no tracker: a comment is read by a human before it appears.