Skip to main content

ADVERTISEMENT

320x100

HTML & CSS Practice

Semantic markup, modern layout, and CSS that works. Practice the patterns that show up in every front-end project.

Semantic HTML Form

A login form with fieldset, label/input pairs, and proper types. Getting attribute order consistent builds speed.

Part 1 of 1
<form method="post" action="/login" novalidate> <fieldset> <legend>Sign in</legend> <label for="email">Email</label> <input type="email" id="email" name="email" required autocomplete="email"> <label for="password">Password</label> <input type="password" id="password" name="password" required> <button type="submit">Sign in</button> </fieldset> </form>
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 25 WPM
⏱️ Start typing...

Flexbox Layout

A flex container with gap, wrapping, and alignment. These properties go together constantly so they should feel automatic.

Part 1 of 1
.nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; padding: 0.75rem 1.5rem; } .nav__links { display: flex; gap: 0.5rem; list-style: none; margin: 0; padding: 0; }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 30 WPM
⏱️ Start typing...

CSS Grid

A named grid layout with template areas. The quotes and the area names are the fiddly parts.

Part 1 of 1
.layout { display: grid; grid-template-columns: 240px 1fr 320px; grid-template-rows: auto 1fr auto; grid-template-areas: 'header header header' 'sidebar main aside' 'footer footer footer'; min-height: 100vh; gap: 0; }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 28 WPM
⏱️ Start typing...

Media Query

Responsive breakpoints with a mobile-first stacking layout that switches to columns at wider screens.

Part 1 of 1
@media (max-width: 768px) { .card-grid { grid-template-columns: 1fr; } .sidebar { display: none; } .header__nav { flex-direction: column; align-items: flex-start; } } @media (min-width: 1200px) { .container { max-width: 1140px; } }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 28 WPM
⏱️ Start typing...

CSS Keyframe Animation

A slide-in animation with easing. Keyframe percentages and transform values need precise typing.

Part 1 of 1
@keyframes slideInUp { 0% { opacity: 0; transform: translateY(24px); } 60% { opacity: 1; transform: translateY(-4px); } 100% { opacity: 1; transform: translateY(0); } } .modal { animation: slideInUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 25 WPM
⏱️ Start typing...

Accessibility Attributes

ARIA attributes on a dialog and button. Getting role, aria-labelledby, and aria-expanded right matters for accessibility.

Part 1 of 1
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title" aria-describedby="dialog-desc"> <h2 id="dialog-title">Confirm deletion</h2> <p id="dialog-desc">This action cannot be undone.</p> <button aria-label="Close dialog" type="button" class="btn-close">x</button> </div>
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 25 WPM
⏱️ Start typing...

CSS Custom Properties

A design token setup using CSS variables and a dark mode override. The -- prefix is the thing to nail.

Part 1 of 1
:root { --color-primary: #4f46e5; --color-text: #111827; --color-surface: #ffffff; --spacing-base: 1rem; --radius-md: 0.5rem; --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); } @media (prefers-color-scheme: dark) { :root { --color-text: #f9fafb; --color-surface: #1f2937; } }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 28 WPM
⏱️ Start typing...

Pseudo-elements

::before and ::after for decorative content. The content property and absolute positioning combo is a common pattern.

Part 1 of 1
.required-field label::after { content: ' *'; color: var(--color-error, #dc2626); font-size: 0.875rem; } .blockquote::before { content: '\201C'; font-size: 4rem; line-height: 0; vertical-align: -1.5rem; color: var(--color-primary); }
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 28 WPM
⏱️ Start typing...

Responsive Image

A picture element with art direction and a srcset fallback. The media and type attributes are easy to mix up.

Part 1 of 1
<picture> <source media="(min-width: 1024px)" srcset="hero-desktop.webp 1x, [email protected] 2x" type="image/webp"> <source media="(min-width: 640px)" srcset="hero-tablet.webp" type="image/webp"> <img src="hero-mobile.jpg" alt="Team working together in a modern office" loading="lazy" width="800" height="450"> </picture>
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 22 WPM
⏱️ Start typing...

HTML Table

A proper table with thead, tbody, scope attributes, and a caption. Tables need more boilerplate than most people remember.

Part 1 of 1
<table> <caption>Monthly sales by region</caption> <thead> <tr> <th scope="col">Region</th> <th scope="col">Units</th> <th scope="col">Revenue</th> </tr> </thead> <tbody> <tr> <th scope="row">North</th> <td>1,240</td> <td>$62,000</td> </tr> </tbody> </table>
WPM 0
Accuracy 100%
Progress 0%
Streak 0 🔥
Speed Target: 25 WPM
⏱️ Start typing...

ADVERTISEMENT

336×280