Tips & micro-lessons

Small wins, big impact. Each tip is something you can apply the next time you open the playground.

HTML

  • Always set the lang attribute

    <html lang="en"> tells screen readers and translation tools what language the page is in. It's a one-character change that improves accessibility and SEO.

  • Set a viewport meta tag

    Without <meta name="viewport" content="width=device-width, initial-scale=1"> mobile browsers will zoom out and render your page at 980px wide.

  • Use real <button> elements

    A clickable <div> isn't keyboard-accessible, doesn't focus, and isn't announced as a button by screen readers. <button> handles all of that for free.

  • Lazy-load below-the-fold images

    Add loading="lazy" to <img> tags that aren't visible on first paint. The browser will defer loading them until the user scrolls close.

    <img src="..." loading="lazy" alt="..." />
  • Use srcset for responsive images

    Let the browser pick the right image size for each device with srcset and sizes — smaller files on phones, sharper images on retina laptops.

CSS

  • Use clamp() for fluid typography

    font-size: clamp(1rem, 2vw + 0.5rem, 2rem) scales smoothly between a minimum and maximum without media queries.

    font-size: clamp(1rem, 2vw + 0.5rem, 2rem);
  • auto-fill + minmax = responsive grid

    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)) creates a fully responsive grid with zero media queries.

    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  • Use gap instead of margin

    Both Flexbox and Grid support the gap property. It's cleaner than per-item margins and never adds extra space at the edges.

  • Reserve image space with aspect-ratio

    aspect-ratio: 16/9 keeps space reserved while the image loads, eliminating cumulative layout shift.

  • Respect prefers-reduced-motion

    Wrap animations in @media (prefers-reduced-motion: no-preference) so users sensitive to motion get a still UI.

  • Use color-mix() for tints

    color-mix(in oklab, var(--primary) 20%, transparent) gives you a translucent tint of any color, without needing separate variables.

JavaScript

  • Use optional chaining

    user?.profile?.name returns undefined if any link in the chain is null or undefined — no more nested && checks.

  • ?? vs ||

    Nullish coalescing (??) only falls back when the value is null or undefined. || falls back on any falsy value, which can hide bugs around 0 or empty strings.

  • Clone with the spread operator

    const copy = [...arr] or { ...obj } gives you a shallow clone with one character — no need for slice() or Object.assign().

  • fetch() doesn't reject on 4xx/5xx

    fetch() only rejects on network errors. You have to manually check res.ok and throw if it's false.

  • Debounce expensive handlers

    Wrap scroll, resize, or keystroke handlers in a debounce so they only run once after the user stops, not on every event.

  • Use event delegation

    Attach one listener to a parent instead of one to every child. Use event.target.closest() to find the matching element.

  • Format dates and numbers with Intl

    Intl.DateTimeFormat and Intl.NumberFormat ship with the browser. Skip the date-fns dependency for simple formatting.