One set of exercises per chapter. Work through them in the Playground after studying each chapter. Exercises progress from Easy to Challenging — the final exercise in each set combines all chapter concepts.
Practise targeting elements precisely and understanding which rules win when two conflict.
Link a CSS file to an HTML page and write three basic CSS rules using element selectors. Style the body background, the h1 colour, and the p font-size.
<link rel="stylesheet">Create a card component using a class selector, and a unique hero section using an ID selector. Style them differently and explain in a comment why you chose each selector type.
.card class applied to 3 elements — all styled identically#hero applies to exactly one elementStyle a navigation using all four combinators. Each rule must use a different combinator.
Style form inputs differently based on their type attribute — without adding any extra classes to the HTML.
Write 4 CSS rules targeting the same paragraph. Predict which colour will win before running. Then verify your prediction in the playground.
/* Rule 1 */ p { color: red; } /* Rule 2 */ .intro { color: blue; } /* Rule 3 */ div .intro { color: green; } /* Rule 4 */ #main .intro p { color: orange; }
The CSS below uses !important everywhere. Rewrite it to achieve the same visual result without using !important even once. Fix the specificity instead.
p { color: gray !important; } .card p { color: white !important; } .card { background: #111 !important; } nav a { color: #888 !important; } nav a:hover { color: white !important; }
Write 3 CSS rules with identical specificity (all class selectors, same score). Observe that the last rule wins — the cascade order. Then demonstrate this by moving the winning rule to the top — confirm the result changes.
Style a complete navigation bar using as many selector types as naturally fit. The nav has a logo, a list of links, and a CTA button. Use element, class, combinator, attribute, and pseudo-class selectors.
Practise the four layers of the box model, the border-box fix, display types, and overflow — the building blocks of every CSS layout.
Create a box that is exactly 300px wide with 24px padding and a 2px border. First measure its actual width without box-sizing. Then add the universal fix and confirm it stays at exactly 300px.
*, *::before, *::after { box-sizing: border-box; } is at the very top of CSSStyle 4 elements using the 4 padding shorthand patterns. Each must use a different shorthand form and display the resulting spacing visibly with a background colour.
Vertical margins between block elements collapse — the larger value wins and they do not add. Demonstrate this, then prevent it using a flexbox wrapper.
Create three identical-looking buttons using block, inline, and inline-block elements. Then demonstrate the key difference — block takes full width, inline ignores width/height, inline-block respects both but sits in text flow.
Create a fixed-height container with too much content. Apply overflow: hidden, then overflow: auto, then overflow: scroll. Note the visual differences and when each is appropriate.
hidden: content is clipped — no scrollbarauto: scrollbar only when content overflows ✓ preferredscroll: scrollbar always visible even when not neededBuild a profile card using only box model properties — no flexbox or grid yet. Control everything with width, padding, margin, border, border-radius, and overflow.
Create 5 boxes demonstrating different border styles (solid, dashed, dotted, double, none) and 4 boxes demonstrating different border-radius values (4px, 16px, 50%, pill shape).
Recreate the box model diagram from the course chapter — nested boxes showing margin (outermost), border, padding, and content — using only CSS boxes with different backgrounds and borders. Each layer must be visually distinct with a label.
Practise font stacks, rem sizing, fluid clamp(), line-height, and the text effects used in professional UIs.
Set the body font to a Google Font, with two system font fallbacks and a generic fallback. Also set a different monospace font for code elements with its own fallback stack.
Create two identical paragraphs — one with font-size in px, one in rem. Then add a rule that changes the root font size to 20px. Observe: the rem paragraph scales, the px paragraph does not.
/* Add this to see the difference */ html { font-size: 20px; } .px-text { font-size: 16px; } /* stays 16px */ .rem-text { font-size: 1rem; } /* becomes 20px */
Set all 6 heading sizes (h1–h6) using clamp() so they scale fluidly between mobile and desktop. Each heading should have a distinct minimum, preferred viewport width value, and maximum.
Create two text blocks and one heading. Set unitless line-height on the body text (1.7), a tighter line-height on the heading (1.05), and positive letter-spacing on an uppercase label (3px).
Create a card with a fixed width. Add a long title that overflows. Apply the three-property truncation pattern to show an ellipsis instead.
/* All three required together */ .card-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
Apply a gradient text effect to an h1 heading using the three required properties. The gradient should go from purple (#7c6af7) to cyan (#5af7c0) at a 135deg angle.
background: linear-gradient(...) applied-webkit-background-clip: text and background-clip: text-webkit-text-fill-color: transparentCreate a blog post layout. Left-align body text, centre the article header, right-align a date, and style links with no underline by default but underline on hover.
Build a complete typography system for a blog. Define a type scale using CSS variables for all sizes, weights, and line-heights. Then apply the system to a realistic page layout: hero, section headings, body paragraphs, labels, captions, and code snippets.
Practise distributing space, aligning items, wrapping rows, and building common UI patterns using flexbox.
Take a div with 3 child elements. Add display: flex to the parent. Observe how they line up in a row. Add gap: 16px between them. Then change flex-direction to column and observe the change.
Build a navbar with a logo on the left and navigation links on the right. Use justify-content: space-between to push them apart and align-items: center to vertically centre them.
Create a full-viewport hero section with a heading and subtitle perfectly centred both horizontally and vertically. Use flexbox.
Create a row of 3 cards. Make the middle card twice as wide as the others using flex-grow. Then make one card fixed at 200px using flex: 0 0 200px.
Create a row of 5 cards that wraps automatically. Each card should be at least 250px wide and grow to fill space. Use flex-wrap: wrap and flex: 1 1 250px.
Build a two-column layout with a fixed 260px sidebar and a fluid main content area. The sidebar should never grow or shrink.
In a navbar, push the Sign In and Register buttons to the far right using margin-left: auto on the first button — without changing justify-content. The logo and links stay left, buttons go right.
Build a complete page layout using only flexbox: sticky navbar (flex, space-between, align-items), hero (flex, column, center, 100vh), card grid (flex, wrap, gap), and footer (flex, space-between). No grid, no absolute positioning.
Practise two-dimensional layouts — auto-fit card grids, named areas, spanning, and full-page layouts.
Create a 3-column grid with 4 rows of items. Use display: grid with repeat(3, 1fr) and gap: 16px. Add a background to each cell to see the grid clearly.
Create a responsive card grid using repeat(auto-fit, minmax(250px, 1fr)). Resize the browser — it should go from 1 column on mobile to 4+ on a wide screen with zero media queries.
In a 3-column grid, make the first card span all 3 columns (featured hero). Make the second card span 2 columns and 2 rows. Use grid-column: span X and grid-row: span X.
Build a page layout using grid-template-areas. Define header spanning full width, a sidebar and main side by side, and a footer spanning full width.
.page { grid-template-areas: "header header" "sidebar main" "footer footer"; }
Build these two layouts and decide which tool (grid or flexbox) is more natural for each. Write a comment explaining your choice: (A) a row of nav items that wrap on small screens; (B) a dashboard with 4 equal quadrants.
Create a 3-column layout: 200px fixed sidebar, fluid auto main column, 160px fixed right panel. Use grid-template-columns: 200px auto 160px.
Build a grid that is 1 column on mobile, 2 on tablet (768px+), and 3 on desktop (1200px+). Use grid-template-columns inside media queries.
Build a 12-column magazine layout. Featured article spans 8 columns, sidebar spans 4. Below: 3 equal article cards span 4 columns each. Use grid-column: X / X for precise placement.
Practise the five position values through real-world patterns — sticky navbars, badge overlays, centred modals, and tooltips.
Add position: relative to a parent div. Then add position: absolute to a child. Move the child to the top-right corner of the parent using top: 0 right: 0. Confirm the child positions relative to parent, not the page.
Build a product card with a "PRO" badge in the top-right corner. The badge must be positioned relative to the card, not the page.
Make a navbar stick to the top of the screen when the user scrolls past it. Add enough page content to make it scrollable. The nav must have a background colour or content will show through.
Build a full-screen overlay backdrop and a centred modal card using position: fixed. Centre the modal using the transform trick.
.modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); }
Create a button that shows a tooltip above it on hover. The tooltip is absolutely positioned relative to the button wrapper. No JavaScript — CSS only.
Create a cookie consent banner fixed to the bottom of the screen. It must stay visible when the user scrolls up the page, and sit above all other content.
Create 4 overlapping cards, each with a different z-index. Confirm that higher z-index appears on top. Demonstrate that z-index only works on positioned elements — test it by removing position from one card.
Build an image card where hovering reveals a dark gradient overlay with the image title and tags. Use position: absolute to place the overlay, and transition to reveal it on hover.
Practise mobile-first CSS, media queries, responsive units, and user preference queries.
Write base CSS for a single-column page layout — no media queries yet. Padding 16px, font-size 1rem, single column grid, full-width images. This is your mobile baseline.
Add two min-width media queries to the layout from EX 01. At 768px: 2-column grid, 32px padding. At 1200px: 3-column grid, max-width 1200px centered, 48px padding.
Build a light-themed page. Add a CSS variables layer and a prefers-color-scheme: dark media query that swaps the colour tokens. No JavaScript — pure CSS dark mode.
Create 5 boxes with widths set using px, %, vw, em, and rem. Resize the browser for each and observe how each unit behaves. Add a comment explaining when each unit is most appropriate.
Create a mobile hamburger menu icon and a desktop navigation bar. The mobile icon is visible only on small screens; the desktop nav is hidden on small screens.
Add a bouncing animation to a page element. Then add a prefers-reduced-motion media query that sets animation-duration to 0.01ms for users who have enabled reduce motion in their OS settings.
Build a container that has proportional horizontal padding at every screen size without any media queries — using padding-inline: clamp(). Min 16px, max 64px, preferred 5vw.
Build a fully responsive landing page from scratch: mobile-first base → tablet 768px → desktop 1200px. Must include: fluid typography with clamp, auto-fit card grid, responsive navbar that switches from stacked to horizontal, dark mode support, and reduced motion override.
Define 3 cascade layers: base, components, utilities. Put conflicting colour rules in each. Confirm that utilities always win over components which always win over base — regardless of specificity.
The stylesheet below has 6 !important declarations. Refactor every single one using proper specificity or cascade layers instead.
p { color: gray !important; } .hero p { color: white !important; } .card { padding: 24px !important; } .hidden { display: none !important; } nav a { color: #888 !important; } nav a:hover{ color: white !important; }
Build a button component system using BEM. Base .btn block + size modifiers (--sm, --lg) + colour modifiers (--primary, --danger, --ghost) + state element (--loading with spinner).
Build a small utility class library covering: display (flex, grid, hidden), text alignment (text-left, text-center, text-right), margin helpers (mt-1 through mt-4), and the sr-only pattern.
Write a production-ready CSS file for a full page — applying every concept from all 12 chapters. Modern reset → design tokens → fluid typography → flexbox nav → grid layout → position badge → responsive breakpoints → hover transitions → entrance animations → dark mode → BEM components → utilities in @layer.
Write your CSS alongside the HTML, switch to the Preview tab to see results instantly, and use the browser DevTools to inspect the box model.
⚡ Open Playground