
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.
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.
- 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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> - 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.