CSS Exercises

Practise what you've learned. Type the missing piece into each highlighted gap and press Check. Further down are styling challenges with live editors and model solutions.

Fill in the blanks

Syntax and selectors

Link an external stylesheet from the HTML head.

<link ="stylesheet" href="styles.css">

Select every element with the class "note".

 { color: #565d72; }

Select the element with the id "header".

 { padding: 1rem; }

Select only paragraphs that are direct children of an article.

article  p { margin-top: 0; }

Select links whose href starts with "https".

a[href"https"] { color: green; }

Style a button when the mouse is over it.

button: { background: #164c91; }

Select every odd row of a table.

tr:nth-child() { background: #f4f6fa; }

Insert generated content before each item.

li:: { content: "→ "; }

Values and colour

Size the text relative to the root font size.

h1 { font-size: 2.5; }

Make a semi-transparent black using the modern rgb() syntax.

.overlay { background: rgb(0 0 0  50%); }

Create a gradient that goes from left to right.

.bar { background: (to right, #1a5fb4, #d6336c); }

Use the custom property --brand.

a { color: (--brand); }

Make the heading size fluid, between 1.5rem and 3rem.

h1 { font-size: (1.5rem, 1rem + 3vw, 3rem); }

Boxes and text

Make width include padding and border.

*, *::before, *::after { box-sizing: ; }

Centre a block horizontally.

.container { max-width: 60rem; margin-inline: ; }

Round the corners of a card.

.card { : 12px; }

Add a soft shadow.

.card { : 0 4px 12px rgb(0 0 0 / 15%); }

Show an ellipsis when text overflows one line.

.title { white-space: nowrap; overflow: hidden; text-overflow: ; }

Keep text visible while a web font loads.

@font-face { font-family: "Inter"; src: url("inter.woff2") format("woff2"); font-display: ; }

Layout

Turn the container into a flex container.

.nav { display: ; gap: 1rem; }

Push flex items to opposite ends of the main axis.

.header { display: flex; justify-content: ; }

Let a flex item grow to fill the remaining space.

.search { flex: ; }

Create three equal grid columns.

.grid { display: grid; grid-template-columns: repeat(3, 1); }

Make as many 200px-minimum columns as fit.

.cards { display: grid; grid-template-columns: repeat(, minmax(200px, 1fr)); }

Centre a child both ways inside a grid container.

.box { display: grid; : center; }

Keep the header at the top while scrolling.

.header { position: ; top: 0; }

Apply styles only on screens at least 768px wide.

@media () { .sidebar { display: block; } }

Make the card a size container.

.card-wrap { : inline-size; }

Effects and modern CSS

Animate the colour change over 0.3 seconds.

a { transition:  0.3s ease; }

Define the keyframes for the "spin" animation.

@ spin { to { rotate: 1turn; } }

Crop an image to fill its box without distortion.

img { width: 100%; height: 200px; object-fit: ; }

Style a card that contains an image.

.card:(img) { border-color: #1a5fb4; }

Write a zero-specificity selector for base styles.

:(.card) p { color: #565d72; }

Refer to the parent selector in a nested rule.

.btn { :hover { background: #164c91; } }

Declare the order of cascade layers.

 reset, base, components, utilities;

Give a colour different values in light and dark mode.

body { color: (#10131c, #e8eaf2); }

Show a focus ring only for keyboard focus.

button: { outline: 3px solid #1a5fb4; }

Styling challenges

1. A profile card

Style the card: centred with a maximum width of 280px, rounded corners, a shadow, a circular avatar, and a button that changes colour on hover.

Try it yourself
Result
Show a model solution
CSS solution.css
.profile {
  max-width: 280px;
  margin: 2rem auto;
  padding: 1.5rem;
  text-align: center;
  font-family: system-ui, sans-serif;
  border-radius: 16px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 12%);
}

.avatar {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
}

.profile h2 {
  margin: 0.5rem 0 0;
}

.profile p {
  margin: 0.25rem 0 1rem;
  color: #565d72;
}

.follow {
  display: inline-block;
  padding: 0.5em 1.4em;
  border-radius: 999px;
  background: #1a5fb4;
  color: white;
  text-decoration: none;
  transition: background 0.2s;
}

.follow:hover {
  background: #164c91;
}

2. A navigation bar

Lay out the logo on the left and the links on the right with Flexbox. Remove the list bullets, add space between links, and on screens narrower than 500px stack everything vertically.

Try it yourself
Result
Show a model solution
CSS solution.css
.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem;
  background: #10131c;
  font-family: system-ui, sans-serif;
}

.site-header a {
  color: white;
  text-decoration: none;
}

.logo {
  font-weight: 800;
}

.links {
  display: flex;
  gap: 1.25rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (width < 500px) {
  .site-header,
  .links {
    flex-direction: column;
    gap: 0.5rem;
  }
}

3. A photo grid

Create a responsive grid where each column is at least 150px wide, images are square and cropped neatly, and the first image spans two columns and two rows.

Try it yourself
Result
Show a model solution
CSS solution.css
.photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  grid-auto-flow: dense;
  gap: 8px;
}

.photos img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 8px;
}

.photos img:first-child {
  grid-column: span 2;
  grid-row: span 2;
}

4. A themed alert with an entrance animation

Style the alerts with a coloured left border driven by a custom property, different colours for success and error, and a short slide-in animation that is turned off for users who prefer reduced motion.

Try it yourself
Result
Show a model solution
CSS solution.css
.alert {
  --tone: #1a5fb4;
  margin-bottom: 8px;
  padding: 10px 14px;
  border-inline-start: 5px solid var(--tone);
  border-radius: 6px;
  background: color-mix(in oklch, var(--tone), white 90%);
  font-family: system-ui, sans-serif;
  animation: slide-in 0.4s ease-out;
}

.alert.success {
  --tone: #1e6b3c;
}

.alert.error {
  --tone: #a12222;
}

@keyframes slide-in {
  from {
    opacity: 0;
    translate: -20px 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .alert {
    animation: none;
  }
}