Course outline
Full-Stack course / Tools and the web

A weather card that respects preferences

Lab

How to fetch and submit this exercise

Once: install the tool and connect your account.

curl -fsSL https://gonomicon.com/install.sh | sh
gonomicon login

Each exercise: download it, edit the file named in the instructions, then submit.

gonomicon fetch fs-week-1/06-06-weather-card-preferences
cd 06-06-weather-card-preferences
gonomicon submit

The runner depends on the exercise: JavaScript/TypeScript/React labs run with Vitest, Python labs with pytest, and config-file labs (Docker, CI, Terraform, Nginx) are checked by parsing your file. gonomicon test runs the visible checks on your computer first; submitting also runs the hidden checks on our server.

Goal

Style a weather card so its colors come from custom properties that swap for prefers-color-scheme: dark, and give its link a focus-visible style whose color transition turns off for prefers-reduced-motion: reduce.

Example

Declare the light colors once, then override just the custom properties inside the dark-mode query — everything that reads var(--card-bg) updates automatically, without a second copy of the rest of the card's styles:

:root {
  --card-bg: #ffffff;
  --card-ink: #1f2933;
}

@media (prefers-color-scheme: dark) {
  :root {
    --card-bg: #1e2430;
    --card-ink: #e8edf3;
  }
}

.weather-card {
  background: var(--card-bg);
  color: var(--card-ink);
}

A transition and its reduced-motion opt-out work the same way — the reduced-motion query only ever touches transition, never the colors themselves:

.weather-card__link {
  transition: color 200ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .weather-card__link {
    transition: none;
  }
}

Rules

  • Edit only styles.css. index.html is already correct and must not change — it has one .weather-card containing a .weather-card__link.
  • Declare at least two color custom properties on :root (for example --card-bg and --card-ink), and re-declare both of them — with different values — inside @media (prefers-color-scheme: dark) { :root { ... } }. Don't give .weather-card a second, plain :root rule outside the media query — that would silently overwrite whichever one comes first.
  • In both light and dark mode, the two custom properties must actually be different colors from each other — a card whose text and background match isn't readable.
  • Apply the custom properties to .weather-card with var(...).
  • Give .weather-card__link a transition on color or background-color with a positive duration, and a .weather-card__link:focus-visible { ... } rule with a visible style such as outline. A :hover-only rule doesn't help someone navigating by keyboard.
  • Inside @media (prefers-reduced-motion: reduce), set .weather-card__link's transition to none (or every duration to 0) — don't touch its colors there.
  • Don't use flexbox, grid, or layout properties — this lesson is only about preference-based colors, transitions and focus styles.

What you'll practice

Driving light/dark colors from CSS custom properties re-declared inside @media (prefers-color-scheme: dark), giving an interactive element both a :hover and a :focus-visible style, and turning off a transition — without touching color — for prefers-reduced-motion: reduce.

Run it

gonomicon fetch fs-week-1/06-06-weather-card-preferences
cd 06-06-weather-card-preferences
gonomicon test
gonomicon submit

Hints

  1. Declare the card's colors as custom properties on :root (e.g. --card-bg, --card-ink), then re-declare those same property names, with different values, inside @media (prefers-color-scheme: dark) { :root { ... } }. .weather-card should read them back with var(--card-bg) and var(--card-ink).
  2. .weather-card__link needs a transition on color or background-color with a real duration (not 0s), plus its own .weather-card__link:focus-visible { ... } rule — a :hover rule alone isn't enough, since it never fires for keyboard users.
  3. Turn the transition off for visitors who'd rather not see it: @media (prefers-reduced-motion: reduce) { .weather-card__link { transition: none; } } — this only removes the motion, it doesn't touch any color.