Ad – 728×90
💼 Interview Prep

CSS Exercises – 15 Practice Challenges with Solutions

The best way to solidify CSS knowledge is to write it. Each exercise below has a clear goal, a difficulty rating, a hint, and a full solution you can reveal. Work through the challenge first — then check the solution. Exercises cover every major CSS area from box model to animations to responsive design.

⏱️ Self-paced 🎯 Beginner – Intermediate 📅 Updated 2026

Box Model & Sizing

Exercise 1 Easy Box Model Sizing

Create a .box that is exactly 300px wide and 200px tall regardless of padding. Give it 20px padding all around and a 2px solid #1572B6 border. The total visible size should remain 300×200px.

▶ Show Solution
CSS
.box {
  box-sizing: border-box;
  width: 300px;
  height: 200px;
  padding: 20px;
  border: 2px solid #1572B6;
}

Why: box-sizing: border-box makes width/height include padding and border. Without it, the total would be 344×244px.

Exercise 2 Easy Margin Collapse

Two <p> elements: first has margin-bottom: 32px, second has margin-top: 24px. What is the actual space between them? Then explain how to prevent margin collapse.

▶ Show Solution

Answer: 32px — the larger margin wins (margins collapse). The space is NOT 56px.

How to prevent collapse:

CSS
/* Method 1: Add padding (or border) to the parent */
.parent { padding-top: 1px; }

/* Method 2: Use overflow */
.parent { overflow: hidden; }

/* Method 3: Use flexbox/grid (margins don't collapse in flex/grid) */
.parent { display: flex; flex-direction: column; }

/* Best: just use gap in flex/grid instead of margins */
.parent { display: flex; flex-direction: column; gap: 32px; }
Ad – 336×280

Flexbox

Exercise 3 Easy Center Everything

Make a .hero section that fills the full viewport height and perfectly centers its content both horizontally and vertically using Flexbox. Use two methods.

▶ Show Solution
CSS
/* Method 1: Flexbox */
.hero {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

/* Method 2: Grid */
.hero {
  display: grid;
  place-items: center;
  min-height: 100vh;
}
Exercise 4 Medium Navigation Bar with Flexbox

Build a navigation bar where the logo is on the left, nav links are in the center, and a button is on the right — all using Flexbox. On screens below 768px, stack everything vertically.

▶ Show Solution
CSS
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 2rem;
  background: #1572B6;
}
.navbar__logo { color: #fff; font-weight: 800; }
.navbar__links {
  display: flex;
  gap: 1.5rem;
  list-style: none;
  margin: 0; padding: 0;
}
.navbar__links a { color: rgba(255,255,255,.85); text-decoration: none; }
.navbar__links a:hover { color: #fff; }
.navbar__btn { /* see projects/navigation.html for full implementation */ }

@media (max-width: 768px) {
  .navbar { flex-direction: column; gap: 1rem; text-align: center; }
  .navbar__links { flex-direction: column; gap: .75rem; }
}

CSS Grid

Exercise 5 Easy Auto-fill Card Grid

Create a responsive card grid where columns automatically fill the container — each column is at least 250px wide. Cards should fill remaining space equally. No media queries allowed.

▶ Show Solution
CSS
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1.5rem;
}
/* auto-fill: creates as many columns as fit, even empty ones
   minmax(250px, 1fr): each column is at least 250px, grows to fill space */
Exercise 6 Medium Holy Grail Layout

Create the "Holy Grail" page layout: a full-height page with a header, a footer, and a three-column middle section (left sidebar, main content, right sidebar) using CSS Grid.

▶ Show Solution
CSS
.page {
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header  header  header"
    "sidebar main    aside"
    "footer  footer  footer";
  grid-template-columns: 220px 1fr 220px;
  min-height: 100vh;
  gap: 1rem;
}
.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-aside   { grid-area: aside; }
.page-footer  { grid-area: footer; }

@media (max-width: 768px) {
  .page {
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "aside"
      "footer";
    grid-template-columns: 1fr;
  }
}
Ad – 336×280

Positioning & Stacking

Exercise 7 Medium Sticky Header

Make a .header that sticks to the top of the viewport when the user scrolls past it, but scrolls normally until it reaches the top.

▶ Show Solution
CSS
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #fff;
  box-shadow: 0 2px 8px rgba(0,0,0,.1);
}
/* sticky requires that no ancestor has overflow: hidden/auto/scroll */
Exercise 8 Medium Overlay Badge

Create a card component with an image that has an absolutely positioned "NEW" badge in the top-right corner of the image. The badge should not affect the image's layout.

▶ Show Solution
CSS
.card { position: relative; } /* positioning context */
.card__img { display: block; width: 100%; }
.card__badge {
  position: absolute;
  top: 12px;
  right: 12px;
  background: #e44d26;
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  padding: .25rem .6rem;
  border-radius: 12px;
  text-transform: uppercase;
  letter-spacing: .05em;
}

Typography & Colors

Exercise 9 Easy Fluid Typography with clamp()

Create a heading font size that is 1rem on small screens, grows proportionally with the viewport, and maxes out at 3rem — without using any media queries.

▶ Show Solution
CSS
h1 {
  font-size: clamp(1rem, 3vw + 0.5rem, 3rem);
  /* clamp(min, preferred, max)
     min: 1rem on tiny screens
     preferred: 3vw + 0.5rem — grows with viewport
     max: 3rem on large screens */
}
Exercise 10 Medium Dark Mode with CSS Variables

Set up a simple dark/light theme system using CSS custom properties. The theme should switch by toggling a data-theme="dark" attribute on <html>.

▶ Show Solution
CSS
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --surface: #f5f5f5;
  --primary: #1572B6;
}
[data-theme="dark"] {
  --bg: #121212;
  --text: #f1f1f1;
  --surface: #1e1e1e;
  --primary: #4fc3f7;
}
body { background: var(--bg); color: var(--text); transition: background .3s, color .3s; }
.card { background: var(--surface); }
JS – Toggle
document.getElementById('themeBtn').addEventListener('click', () => {
  const html = document.documentElement;
  html.setAttribute('data-theme',
    html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'
  );
});

Animations & Effects

Exercise 11 Easy Hover Button Effect

Create a button that lifts up 4px and has a deeper shadow on hover. The animation must be smooth and must only use GPU-composited properties.

▶ Show Solution
CSS
.btn {
  background: #1572B6;
  color: #fff;
  padding: .75rem 1.5rem;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(0,0,0,.2);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.btn:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0,0,0,.25);
}
/* transform is GPU-composited — no layout reflow */
Exercise 12 Medium Skeleton Loading Screen

Create a skeleton loading placeholder for a card component. Use a shimmering animation that travels left to right across the grey placeholder areas.

▶ Show Solution
CSS
@keyframes shimmer {
  from { background-position: -200% 0; }
  to   { background-position: 200% 0; }
}
.skeleton {
  background: linear-gradient(
    90deg,
    #e0e0e0 25%,
    #f0f0f0 50%,
    #e0e0e0 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 4px;
}
.skeleton-title  { height: 20px; width: 70%; margin-bottom: 12px; }
.skeleton-text   { height: 14px; width: 100%; margin-bottom: 8px; }
.skeleton-image  { height: 180px; width: 100%; margin-bottom: 16px; }

Responsive Design

Exercise 13 Medium Mobile-First Responsive Grid

Create a card grid that shows 1 column on mobile, 2 columns on tablet (≥600px), and 3 columns on desktop (≥1024px). Use mobile-first media queries.

▶ Show Solution
CSS
/* Mobile first: 1 column */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}
/* Tablet: 2 columns */
@media (min-width: 600px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}
/* Desktop: 3 columns */
@media (min-width: 1024px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
}
Exercise 14 Hard CSS-Only Accordion

Build a working accordion (expandable/collapsible sections) using only CSS — no JavaScript. Clicking a section header reveals its content; clicking again collapses it.

▶ Show Solution
HTML
<details class="accordion">
  <summary class="accordion__header">Section 1 <span>+</span></summary>
  <div class="accordion__body">Content here...</div>
</details>
CSS
.accordion {
  border: 1px solid var(--border-color);
  border-radius: 6px;
  margin-bottom: .5rem;
}
.accordion__header {
  padding: 1rem 1.25rem;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  font-weight: 600;
}
.accordion__header::-webkit-details-marker { display: none; }
.accordion[open] .accordion__header span { transform: rotate(45deg); }
.accordion__header span { transition: transform .2s; display: inline-block; }
.accordion__body { padding: 0 1.25rem 1rem; }
/* The <details> element handles open/close natively */
Exercise 15 Hard CSS Card Flip Animation

Build a card that flips 180° on hover to reveal a back face, using 3D CSS transforms. The front shows a question; the back shows the answer.

▶ Show Solution
CSS
.flip-card {
  width: 280px;
  height: 180px;
  perspective: 800px; /* creates 3D depth */
}
.flip-card__inner {
  position: relative;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
}
.flip-card:hover .flip-card__inner {
  transform: rotateY(180deg);
}
.flip-card__front,
.flip-card__back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden; /* hides the reverse face */
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  text-align: center;
}
.flip-card__front { background: #1572B6; color: #fff; }
.flip-card__back  { background: #e44d26; color: #fff; transform: rotateY(180deg); }

📋 Next Steps