CSS Coding Problems & Solutions
Master CSS from selectors to Grid layouts with 150 hands-on coding problems. Each exercise shows a common mistake and the correct modern CSS solution. Click any problem to expand.
Module 1 – CSS Fundamentals
Learn proper CSS syntax, linking stylesheets, colour values, units of measurement, and basic property declarations.
Use a <link> element with the correct rel attribute. A <style> tag imports CSS inline, not from an external file.
<style src="styles.css"></style>
<link rel="stylesheet" href="styles.css">
CSS declarations use colons between property and value, and semicolons to terminate each declaration.
h1 {
color = blue
font-size = 24px
}
h1 {
color: blue;
font-size: 24px;
}
Prefer HSL or hex values over named colours for precise brand consistency across browsers.
.btn {
background-color: red;
color: darkblue;
}
.btn {
background-color: hsl(0, 84%, 60%);
color: #1e3a5f;
}
Pixel units don't scale with user font preferences. Use rem for font sizing to respect accessibility settings.
body { font-size: 16px; }
h1 { font-size: 32px; }
p { font-size: 14px; }
html { font-size: 100%; } /* 16px default */
h1 { font-size: 2rem; } /* 32px equivalent */
p { font-size: 0.875rem; } /* 14px equivalent */
Module 2 – Selectors & Specificity
Master CSS selectors, class vs ID targeting, pseudo-classes, combinators, and the specificity cascade hierarchy.
ID selectors have extremely high specificity, making them hard to override. Use classes for styling and reserve IDs for JavaScript hooks.
#main-button {
background: blue;
padding: 10px 20px;
}
.btn-primary {
background: blue;
padding: 10px 20px;
}
Apply :hover, :focus, and :active pseudo-classes instead of JavaScript class toggles for basic interaction states.
.link {
color: blue;
}
.link-hovered {
color: darkblue;
/* Requires JavaScript to add this class */
}
.link {
color: blue;
transition: color 0.2s ease;
}
.link:hover,
.link:focus {
color: darkblue;
}
Deeply nested selectors increase specificity unnecessarily and create brittle CSS. Keep selectors flat and descriptive.
body div.container section.hero div.content h1.title {
font-size: 2rem;
}
.hero-title {
font-size: 2rem;
}
Instead of adding classes like .odd and .even manually, leverage CSS structural pseudo-classes.
<tr class="odd">...</tr>
<tr class="even">...</tr>
<tr class="odd">...</tr>
tr:nth-child(even) {
background-color: #f9fafb;
}
tr:nth-child(odd) {
background-color: #ffffff;
}
Module 3 – Box Model & Layout
Understand margin, padding, border, box-sizing, display modes, and the document flow model for pixel-perfect layouts.
Without border-box, padding and border add to the element's width, breaking layouts unexpectedly.
.card {
width: 300px;
padding: 20px;
border: 2px solid #ccc;
/* Total rendered width: 344px, not 300px! */
}
*, *::before, *::after {
box-sizing: border-box;
}
.card {
width: 300px;
padding: 20px;
border: 2px solid #ccc;
/* Total rendered width: 300px exactly */
}
Vertical margins between adjacent block elements collapse to the larger value. Use padding or gap instead when spacing needs to be exact.
.section-a { margin-bottom: 40px; }
.section-b { margin-top: 30px; }
/* Gap between them is 40px, not 70px — margins collapse! */
.sections-wrapper {
display: flex;
flex-direction: column;
gap: 40px; /* Flex gap doesn't collapse */
}
Horizontal centring requires margin: 0 auto plus a defined width, or use Flexbox for more control.
.container {
text-align: center; /* Only centres inline content, not the div itself */
}
.container {
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
Module 4 – Flexbox
Build flexible, one-dimensional layouts using Flexbox alignment, distribution, wrapping, and ordering properties.
The classic centring problem is solved cleanly with three Flexbox properties on the parent container.
.hero {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* Works but creates positioning context issues */
}
.hero {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
Without flex-wrap, children overflow the container on small screens. Always enable wrapping for responsive card grids.
.card-row {
display: flex;
/* Items overflow on mobile — no wrapping! */
}
.card { width: 300px; }
.card-row {
display: flex;
flex-wrap: wrap;
gap: 24px;
}
.card {
flex: 1 1 300px; /* Grow, shrink, min 300px */
}
Use margin-left: auto on a flex child to push it to the end without adding spacer elements or using float.
.nav {
display: flex;
}
.nav-cta {
float: right; /* Float doesn't work inside flex */
}
.nav {
display: flex;
align-items: center;
}
.nav-cta {
margin-left: auto;
}
Module 5 – CSS Grid
Create complex two-dimensional page layouts using CSS Grid template areas, fractional units, auto-fit, and minmax functions.
Combine auto-fit with minmax() to create grids that automatically reflow without breakpoints.
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
/* Breaks on mobile — always 3 columns! */
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 24px;
}
Named grid areas make complex layouts readable and maintainable compared to line-number positioning.
.header { grid-column: 1 / 4; grid-row: 1; }
.sidebar { grid-column: 1; grid-row: 2 / 4; }
.main { grid-column: 2 / 4; grid-row: 2; }
.page {
display: grid;
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
grid-template-columns: 250px 1fr 1fr;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
Using margins creates uneven spacing at edges. The gap property provides consistent gutters between grid items only.
.grid-item {
margin: 12px;
/* Creates 24px gap between items but also 12px around edges */
}
.grid {
display: grid;
gap: 24px; /* Only between items, not at edges */
}
Module 6 – Responsive Design
Build mobile-first layouts using media queries, fluid typography, responsive images, and modern viewport units.
Start with mobile styles as defaults, then layer on complexity for larger screens using min-width breakpoints.
/* Desktop-first — styles break on mobile */
.grid { display: grid; grid-template-columns: 1fr 1fr 1fr; }
@media (max-width: 768px) {
.grid { grid-template-columns: 1fr; }
}
/* Mobile-first — single column default */
.grid { display: grid; gap: 24px; }
@media (min-width: 768px) {
.grid { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
.grid { grid-template-columns: 1fr 1fr 1fr; }
}
The clamp() function creates smoothly scaling font sizes without media query breakpoints.
h1 { font-size: 24px; }
@media (min-width: 768px) { h1 { font-size: 36px; } }
@media (min-width: 1200px) { h1 { font-size: 48px; } }
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
/* Min: 24px, scales with viewport, max: 48px */
}
Images with fixed width overflow their containers on small screens. Always constrain with max-width.
img {
width: 800px;
height: 600px;
}
img {
max-width: 100%;
height: auto;
display: block;
}
Module 7 – Animations & Transitions
Add smooth transitions, keyframe animations, hover effects, and performance-optimised motion to your elements.
Transitions declared on :hover only animate in, not out. Place them on the base selector for both directions.
.card:hover {
transform: translateY(-8px);
transition: transform 0.3s ease;
/* Snaps back instantly on mouse-out! */
}
.card {
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-8px);
}
Animating width, height, top, or left causes layout thrashing. Use transform and opacity for smooth 60fps animations.
.slide-in {
animation: slideIn 0.5s ease;
}
@keyframes slideIn {
from { left: -100%; }
to { left: 0; }
}
.slide-in {
animation: slideIn 0.5s ease;
}
@keyframes slideIn {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
Some users have vestibular disorders. Always provide a prefers-reduced-motion media query to disable animations.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Module 8 – CSS Variables & Best Practices
Use CSS custom properties for theming, implement a consistent design system, and follow maintainable coding standards.
Hard-coded colour values scattered across files create inconsistency. Define variables on :root for a single source of truth.
.header { background: #1e3a8a; }
.footer { background: #1e3a8a; }
.btn { background: #1e3a8a; }
/* Same colour repeated — hard to update globally */
:root {
--color-primary: #1e3a8a;
--color-primary-light: #3b82f6;
--radius-md: 12px;
--shadow-sm: 0 2px 8px rgba(0,0,0,0.08);
}
.header { background: var(--color-primary); }
.btn { background: var(--color-primary); }
.btn:hover { background: var(--color-primary-light); }
Override custom properties inside a prefers-color-scheme media query to implement dark mode with zero duplication.
:root {
--bg: #ffffff;
--text: #1f2937;
--surface: #f9fafb;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #111827;
--text: #f9fafb;
--surface: #1f2937;
}
}
body {
background: var(--bg);
color: var(--text);
}
Using !important is almost always a sign of a specificity problem. Fix the cascade instead of forcing overrides.
.nav-link {
color: red !important;
font-size: 18px !important;
padding: 10px !important;
/* Can't be overridden easily in future */
}
/* Use a more specific selector or reorder stylesheets */
.site-header .nav-link {
color: red;
font-size: 18px;
padding: 10px;
}