CSS course
css programming language icon

CSS Exercises: 22 Practice Problems with Solutions

CSS clicks when you stop guessing and start naming what you want: selector, box model, layout, then polish. These problems cover selectors and specificity, the box model, flexbox, grid, typography, custom properties, responsive design and animation.

Each solution is a complete page with its styles in a style tag, so you can run it in the editor below and see the result immediately. Resize the preview to test the responsive problems.

Run your answer here

Type your solution, press Run, and use the Input box when a problem asks you to read from standard input.

CSS Compiler
Output
Code runs in a sandboxed preview inside your browser — your code is saved locally for next time.

How to practise so it actually sticks

Attempt the problem before opening the solution, even if your first version is clumsy. A working ugly answer teaches more than a beautiful one you read. When you get stuck for more than five minutes, read the hint — not the solution — and try again.

After you pass, open the solution and ask what is different about it. Shorter? Fewer variables? A built-in you did not know? That comparison is where most of the growth happens. Then change the problem slightly: sort the other direction, handle an empty input, read a value instead of hard-coding it.

Aim for three to five problems a day rather than thirty in one sitting. Spacing practice over days is what moves syntax from "I can look it up" to "my fingers know it".

The exercises

Showing 22 of 22 exercises.

  1. BeginnerSelectors

    1. Element, class and id selectors

    Style a paragraph by element, a highlighted paragraph by class and one unique paragraph by id.

    Hint: Classes use a dot, ids use a hash.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <p>Plain</p>
        <p class="note">Note</p>
        <p id="lead">Lead</p>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          p { color: #333; }
          .note { background: #fff8c4; padding: 8px; }
          #lead { font-size: 1.25rem; font-weight: 700; }
        </style>
      </head>
      <body>
        <p>Plain</p>
        <p class="note">Note</p>
        <p id="lead">Lead</p>
      </body>
    </html>
  2. IntermediateSelectors

    2. Descendant, child and sibling

    Style only direct children of a list, and the paragraph immediately after a heading.

    Hint: > is child, + is adjacent sibling.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <h2>Title</h2>
        <p>Intro</p>
        <p>Body</p>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          h2 + p { font-style: italic; color: #555; }
          ul > li { list-style: square; }
        </style>
      </head>
      <body>
        <h2>Title</h2>
        <p>Intro</p>
        <p>Body</p>
      </body>
    </html>
  3. IntermediateSelectors

    3. Pseudo-classes

    Style link hover and focus states, the first and last list items, and every even row.

    Hint: :nth-child(even) targets alternate rows.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <a href="#">Link</a>
        <ul><li>One</li><li>Two</li><li>Three</li></ul>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          a:hover, a:focus-visible { color: #2563eb; text-decoration: underline; }
          li:first-child { font-weight: 700; }
          li:last-child { color: #777; }
          li:nth-child(even) { background: #f3f4f6; }
        </style>
      </head>
      <body>
        <a href="#">Link</a>
        <ul><li>One</li><li>Two</li><li>Three</li></ul>
      </body>
    </html>
  4. AdvancedSelectors

    4. Resolve a specificity clash

    Given three competing rules on one element, predict the winning colour and then make the class win without !important.

    Hint: Ids beat classes; increase the class selector's specificity instead of shouting.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          p { color: black; }
          .warn { color: orange; }
          #msg { color: red; }
        </style>
      </head>
      <body>
        <p id="msg" class="warn">Which colour wins?</p>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* #msg wins: id (1-0-0) beats class (0-1-0) beats element (0-0-1) */
          p { color: black; }
          #msg.warn { color: orange; }
          #msg { color: red; }
        </style>
      </head>
      <body>
        <p id="msg" class="warn">Which colour wins?</p>
      </body>
    </html>
  5. BeginnerBox model

    5. The box model

    Give a box 200px width, 16px padding, a 4px border and 24px margin, then make the width include padding and border.

    Hint: box-sizing: border-box changes what width means.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .box { }
        </style>
      </head>
      <body>
        <div class="box">Box</div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          * { box-sizing: border-box; }
          .box {
            width: 200px;
            padding: 16px;
            border: 4px solid #2563eb;
            margin: 24px;
            background: #eff6ff;
          }
        </style>
      </head>
      <body>
        <div class="box">Box</div>
      </body>
    </html>
  6. BeginnerBox model

    6. Three ways to centre

    Centre a block horizontally with margin auto, centre text, and centre a child both ways with flexbox.

    Hint: margin-inline: auto needs a set width.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="wrap"><div class="child">Centred</div></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .wrap {
            max-width: 400px;
            margin-inline: auto;
            height: 200px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #f3f4f6;
          }
          .child { text-align: center; padding: 12px 20px; background: white; }
        </style>
      </head>
      <body>
        <div class="wrap"><div class="child">Centred</div></div>
      </body>
    </html>
  7. IntermediateBox model

    7. Positioning a badge

    Place a small badge in the top-right corner of a card using relative and absolute positioning.

    Hint: The parent needs position: relative to be the reference.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="card">Card<span class="badge">New</span></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .card {
            position: relative;
            padding: 24px;
            border: 1px solid #e5e7eb;
            border-radius: 12px;
            width: 240px;
          }
          .badge {
            position: absolute;
            top: -10px;
            right: -10px;
            background: #ef4444;
            color: white;
            border-radius: 999px;
            padding: 2px 10px;
            font-size: 12px;
          }
        </style>
      </head>
      <body>
        <div class="card">Card<span class="badge">New</span></div>
      </body>
    </html>
  8. BeginnerFlexbox

    8. A flexbox navigation bar

    Build a nav with the logo on the left, links on the right and even spacing between links.

    Hint: justify-content: space-between plus a gap on the link group.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <nav><span class="logo">PWC</span><ul><li>Home</li><li>Courses</li></ul></nav>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          nav {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 12px 20px;
            background: #111827;
            color: white;
          }
          nav ul {
            display: flex;
            gap: 20px;
            list-style: none;
            margin: 0;
            padding: 0;
          }
        </style>
      </head>
      <body>
        <nav><span class="logo">PWC</span><ul><li>Home</li><li>Courses</li></ul></nav>
      </body>
    </html>
  9. IntermediateFlexbox

    9. Flexible card row

    Lay out four cards that wrap onto new lines and grow to fill the row.

    Hint: flex: 1 1 200px is the classic wrapping card recipe.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="row"><div class="card">1</div><div class="card">2</div><div class="card">3</div><div class="card">4</div></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .row { display: flex; flex-wrap: wrap; gap: 16px; }
          .card {
            flex: 1 1 200px;
            padding: 24px;
            background: #eff6ff;
            border-radius: 12px;
            text-align: center;
          }
        </style>
      </head>
      <body>
        <div class="row"><div class="card">1</div><div class="card">2</div><div class="card">3</div><div class="card">4</div></div>
      </body>
    </html>
  10. AdvancedFlexbox

    10. Sticky footer layout

    Make the footer sit at the bottom of the viewport even when the page content is short.

    Hint: A column flex body with flex: 1 on main.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <header>Header</header>
        <main>Short content</main>
        <footer>Footer</footer>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          html, body { height: 100%; margin: 0; }
          body { display: flex; flex-direction: column; }
          main { flex: 1; padding: 20px; }
          header, footer { background: #111827; color: white; padding: 12px 20px; }
        </style>
      </head>
      <body>
        <header>Header</header>
        <main>Short content</main>
        <footer>Footer</footer>
      </body>
    </html>
  11. IntermediateGrid

    11. A responsive grid

    Create a grid that fits as many 220px cards per row as the width allows.

    Hint: repeat(auto-fit, minmax(220px, 1fr)).

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="grid"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
            gap: 16px;
          }
          .grid > div { background: #f3f4f6; padding: 32px; text-align: center; border-radius: 10px; }
        </style>
      </head>
      <body>
        <div class="grid"><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div></div>
      </body>
    </html>
  12. AdvancedGrid

    12. Named grid areas

    Build a holy-grail layout (header, sidebar, main, footer) using grid-template-areas.

    Hint: Each string in grid-template-areas is one row.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="page">
          <header>Header</header>
          <aside>Sidebar</aside>
          <main>Main</main>
          <footer>Footer</footer>
        </div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .page {
            display: grid;
            min-height: 100vh;
            grid-template-columns: 200px 1fr;
            grid-template-rows: auto 1fr auto;
            grid-template-areas:
              "header header"
              "sidebar main"
              "footer footer";
            gap: 8px;
          }
          header { grid-area: header; }
          aside { grid-area: sidebar; }
          main { grid-area: main; }
          footer { grid-area: footer; }
          header, footer { background: #111827; color: white; padding: 12px; }
          aside { background: #f3f4f6; padding: 12px; }
        </style>
      </head>
      <body>
        <div class="page">
          <header>Header</header>
          <aside>Sidebar</aside>
          <main>Main</main>
          <footer>Footer</footer>
        </div>
      </body>
    </html>
  13. AdvancedGrid

    13. Span rows and columns

    In a four-column grid, make one feature tile span two columns and two rows.

    Hint: grid-column: span 2 and grid-row: span 2.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="grid"><div class="feature">Feature</div><div>a</div><div>b</div><div>c</div><div>d</div></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .grid {
            display: grid;
            grid-template-columns: repeat(4, 1fr);
            grid-auto-rows: 100px;
            gap: 12px;
          }
          .grid > div { background: #f3f4f6; display: grid; place-items: center; border-radius: 8px; }
          .feature { grid-column: span 2; grid-row: span 2; background: #dbeafe; }
        </style>
      </head>
      <body>
        <div class="grid"><div class="feature">Feature</div><div>a</div><div>b</div><div>c</div><div>d</div></div>
      </body>
    </html>
  14. BeginnerTypography & colour

    14. Readable typography

    Set a comfortable base font size, line height, measure of about 65 characters and heading scale.

    Hint: max-width in ch units controls the measure directly.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <h1>Title</h1>
        <p>Long paragraph of text…</p>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          body {
            font-family: system-ui, sans-serif;
            font-size: 18px;
            line-height: 1.6;
            color: #1f2937;
          }
          h1 { font-size: 2.25rem; line-height: 1.15; }
          p { max-width: 65ch; }
        </style>
      </head>
      <body>
        <h1>Title</h1>
        <p>Long paragraph of text…</p>
      </body>
    </html>
  15. IntermediateTypography & colour

    15. Custom properties

    Define colour and spacing custom properties on :root and use them in two components.

    Hint: var(--name, fallback) supports a fallback value.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <button class="primary">Save</button>
        <button class="ghost">Cancel</button>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          :root {
            --brand: #2563eb;
            --radius: 10px;
            --space: 12px;
          }
          button {
            border-radius: var(--radius);
            padding: var(--space) calc(var(--space) * 2);
            border: 1px solid var(--brand);
            cursor: pointer;
          }
          .primary { background: var(--brand); color: white; }
          .ghost { background: transparent; color: var(--brand); }
        </style>
      </head>
      <body>
        <button class="primary">Save</button>
        <button class="ghost">Cancel</button>
      </body>
    </html>
  16. AdvancedTypography & colour

    16. Respect the system theme

    Support light and dark colour schemes by swapping custom properties in a media query.

    Hint: @media (prefers-color-scheme: dark).

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <h1>Theme aware</h1>
        <p>This page follows your system setting.</p>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          :root { --bg: #ffffff; --fg: #111827; }
          @media (prefers-color-scheme: dark) {
            :root { --bg: #0f172a; --fg: #e5e7eb; }
          }
          body { background: var(--bg); color: var(--fg); padding: 24px; }
        </style>
      </head>
      <body>
        <h1>Theme aware</h1>
        <p>This page follows your system setting.</p>
      </body>
    </html>
  17. IntermediateResponsive design

    17. Mobile-first breakpoints

    Style a one-column layout first, then switch to two columns above 700px and three above 1000px.

    Hint: Write the mobile rules outside any query.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="grid"><div>1</div><div>2</div><div>3</div></div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
          @media (min-width: 700px) {
            .grid { grid-template-columns: repeat(2, 1fr); }
          }
          @media (min-width: 1000px) {
            .grid { grid-template-columns: repeat(3, 1fr); }
          }
        </style>
      </head>
      <body>
        <div class="grid"><div>1</div><div>2</div><div>3</div></div>
      </body>
    </html>
  18. AdvancedResponsive design

    18. Fluid type with clamp

    Make a heading scale smoothly between 1.75rem and 3rem with the viewport.

    Hint: clamp(min, preferred, max) with a vw unit in the middle.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <h1>Fluid heading</h1>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          h1 {
            font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
            line-height: 1.15;
            margin: 0;
          }
        </style>
      </head>
      <body>
        <h1>Fluid heading</h1>
      </body>
    </html>
  19. BeginnerTransitions & animation

    19. Smooth transitions

    Make a button lift and change colour on hover over 200ms, and respect reduced-motion preferences.

    Hint: Transition transform and background, not all.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <button>Hover me</button>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          button {
            padding: 12px 20px;
            border: 0;
            border-radius: 10px;
            background: #2563eb;
            color: white;
            transition: transform 200ms ease, background 200ms ease;
          }
          button:hover { transform: translateY(-2px); background: #1d4ed8; }
          @media (prefers-reduced-motion: reduce) {
            button { transition: none; }
            button:hover { transform: none; }
          }
        </style>
      </head>
      <body>
        <button>Hover me</button>
      </body>
    </html>
  20. IntermediateTransitions & animation

    20. A keyframe animation

    Animate a loading dot that pulses forever, and a card that fades in once.

    Hint: animation: name duration timing iteration-count.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <div class="dot"></div>
        <div class="card">Fades in</div>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          @keyframes pulse {
            0%, 100% { transform: scale(1); opacity: 1; }
            50% { transform: scale(1.4); opacity: 0.6; }
          }
          @keyframes fade-in {
            from { opacity: 0; transform: translateY(8px); }
            to { opacity: 1; transform: none; }
          }
          .dot {
            width: 14px;
            height: 14px;
            border-radius: 50%;
            background: #2563eb;
            animation: pulse 1.2s ease-in-out infinite;
          }
          .card {
            margin-top: 20px;
            padding: 24px;
            background: #f3f4f6;
            animation: fade-in 400ms ease-out both;
          }
        </style>
      </head>
      <body>
        <div class="dot"></div>
        <div class="card">Fades in</div>
      </body>
    </html>
  21. IntermediateTransitions & animation

    21. Shadows and gradients

    Give a hero panel a linear-gradient background and a soft layered box-shadow.

    Hint: Two shadows separated by a comma read as depth.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <section class="hero">Hero</section>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          .hero {
            padding: 64px 32px;
            color: white;
            border-radius: 18px;
            background: linear-gradient(135deg, #1d4ed8, #7c3aed);
            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), 0 20px 40px -12px rgba(29, 78, 216, 0.5);
          }
        </style>
      </head>
      <body>
        <section class="hero">Hero</section>
      </body>
    </html>
  22. AdvancedPutting it together

    22. Build a polished card

    Style a course card with an image, title, description, tag pills and a hover state.

    Hint: Combine flexbox, custom properties and a transition.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          /* your styles */
        </style>
      </head>
      <body>
        <article class="card">
          <h3>Python</h3>
          <p>17 chapters, quiz and certificate.</p>
          <ul class="tags"><li>Beginner</li><li>Popular</li></ul>
        </article>
      </body>
    </html>
    Show solution
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <style>
          :root { --brand: #2563eb; --radius: 14px; }
          .card {
            max-width: 320px;
            padding: 20px;
            border: 1px solid #e5e7eb;
            border-radius: var(--radius);
            transition: transform 200ms ease, box-shadow 200ms ease;
          }
          .card:hover {
            transform: translateY(-4px);
            box-shadow: 0 12px 30px -12px rgba(0, 0, 0, 0.3);
          }
          .card h3 { margin: 0 0 6px; }
          .card p { margin: 0 0 14px; color: #4b5563; }
          .tags { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0; }
          .tags li {
            font-size: 12px;
            padding: 4px 10px;
            border-radius: 999px;
            background: #eff6ff;
            color: var(--brand);
          }
        </style>
      </head>
      <body>
        <article class="card">
          <h3>Python</h3>
          <p>17 chapters, quiz and certificate.</p>
          <ul class="tags"><li>Beginner</li><li>Popular</li></ul>
        </article>
      </body>
    </html>

What to do next

If a whole topic feels shaky, go back to that chapter in the 17-chapter CSS course and re-read it, then return here. When the advanced problems feel routine, take the final CSS quiz and claim your certificate, or open the CSS online compiler and build something of your own.