{
  "id": "web-capabilities-reference",
  "version": "2026-03-15",
  "source": {
    "filename": "All Web Features - 3.13.26.html",
    "copied_from": "C:\\Users\\Paul\\Downloads\\All Web Features - 3.13.26.html",
    "captured_date": "2026-03-15",
    "type": "local-html-catalog"
  },
  "summary": {
    "total_features": 71,
    "total_categories": 12,
    "verdict_counts": {
      "overused": 6,
      "underused": 41,
      "emerging": 8,
      "justright": 11,
      "essential": 5
    },
    "categories": [
      {
        "name": "Layout",
        "count": 8
      },
      {
        "name": "Visual",
        "count": 8
      },
      {
        "name": "Animation",
        "count": 7
      },
      {
        "name": "Interactive",
        "count": 8
      },
      {
        "name": "Forms",
        "count": 4
      },
      {
        "name": "Modern CSS",
        "count": 9
      },
      {
        "name": "Scroll",
        "count": 4
      },
      {
        "name": "Performance",
        "count": 6
      },
      {
        "name": "Canvas & APIs",
        "count": 6
      },
      {
        "name": "Text",
        "count": 4
      },
      {
        "name": "Media",
        "count": 3
      },
      {
        "name": "Semantic",
        "count": 4
      }
    ]
  },
  "usage_rule": {
    "role": "implementation-technique reference for IFX engines",
    "not_for": [
      "template selection",
      "raw prompt stuffing",
      "novelty for novelty's sake"
    ],
    "choose_features_by": [
      "wedge fit",
      "browser support",
      "accessibility",
      "performance",
      "clarity"
    ]
  },
  "features": [
    {
      "cat": "Layout",
      "cap": "Flexbox",
      "desc": "1D layout — row or column alignment",
      "verdict": "overused",
      "adoption": 98,
      "browser": 99,
      "opp": "The default for everything, which is the problem. Devs use nested Flexbox to fake grids instead of using Grid. Fine for navbars, toolbars, centering, and single-axis alignment. Wrong for page layouts and card grids.",
      "examples": "Every site on earth",
      "miss": "justify-content:space-evenly exists and is cleaner than space-around. align-self on individual children is underused."
    },
    {
      "cat": "Layout",
      "cap": "CSS Grid",
      "desc": "2D layout — rows AND columns simultaneously",
      "verdict": "underused",
      "adoption": 72,
      "browser": 98,
      "opp": "The correct tool for page layouts, dashboards, image galleries, and any 2D arrangement. Grid-template-areas lets you NAME regions ('header', 'sidebar', 'main') — reads like a blueprint.",
      "examples": "<b>Best:</b> Stripe dashboard, GitHub issues, Notion. <b>Most sites:</b> Still faking grids with Flexbox rows",
      "miss": "subgrid (nested grids inheriting parent tracks) is now supported everywhere and almost nobody uses it. grid-template-areas is the most readable layout syntax in CSS."
    },
    {
      "cat": "Layout",
      "cap": "Container Queries",
      "desc": "Style components based on their container size, not viewport",
      "verdict": "emerging",
      "adoption": 15,
      "browser": 91,
      "opp": "The biggest paradigm shift in responsive design since media queries. Components become truly portable — a card in a sidebar auto-adjusts vs. the same card in a main content area. Kills the 'responsive component' problem.",
      "examples": "<b>Best:</b> Shopify Polaris, some design systems. <b>Most:</b> Still using media queries for everything",
      "miss": "container-type: inline-size is all you need for most cases. Combine with container query units (cqi, cqw) for truly fluid components."
    },
    {
      "cat": "Layout",
      "cap": "Multi-column Layout",
      "desc": "columns property — newspaper-style text flow",
      "verdict": "underused",
      "adoption": 18,
      "browser": 98,
      "opp": "Perfect for text-heavy content, masonry-like card layouts, and long lists. One CSS line: columns: 3 250px. Auto-wraps into columns that fit.",
      "examples": "<b>Best:</b> Wikipedia, news sites. <b>Most sites:</b> Don't know it exists",
      "miss": "break-inside: avoid prevents elements from splitting across columns. column-gap works just like grid gap."
    },
    {
      "cat": "Layout",
      "cap": "aspect-ratio",
      "desc": "Set width-to-height ratio on any element",
      "verdict": "underused",
      "adoption": 42,
      "browser": 95,
      "opp": "Replaces the infamous padding-bottom percentage hack. Critical for responsive video embeds, image placeholders, card thumbnails. One property: aspect-ratio: 16/9.",
      "examples": "<b>Best:</b> YouTube embeds, modern image grids. <b>Most:</b> Still using padding-bottom: 56.25%",
      "miss": "Works on any element, not just media. Great for consistent card layouts: aspect-ratio: 1 makes perfect squares."
    },
    {
      "cat": "Layout",
      "cap": "position: sticky",
      "desc": "Element sticks within scroll container at defined offset",
      "verdict": "justright",
      "adoption": 85,
      "browser": 98,
      "opp": "Table headers, nav bars, sidebar TOCs, section labels. One CSS line. The iOS contacts-style sticky section headers pattern.",
      "examples": "<b>Best:</b> Apple docs, GitHub file browser, MDN sidebar",
      "miss": "Sticky fails silently if any ancestor has overflow: hidden. This causes 90% of 'why isn't sticky working' bugs."
    },
    {
      "cat": "Layout",
      "cap": "CSS logical properties",
      "desc": "margin-inline, padding-block, inset — direction-agnostic box model",
      "verdict": "underused",
      "adoption": 22,
      "browser": 95,
      "opp": "Write CSS that works for LTR and RTL layouts automatically. margin-inline-start instead of margin-left. Essential for internationalization.",
      "examples": "<b>Best:</b> Google products, apps with Arabic/Hebrew support",
      "miss": "inset: 0 replaces top:0;right:0;bottom:0;left:0 in one property. padding-inline replaces padding-left + padding-right."
    },
    {
      "cat": "Layout",
      "cap": "display: contents",
      "desc": "Element becomes invisible to layout — children promote to parent grid/flex",
      "verdict": "underused",
      "adoption": 8,
      "browser": 96,
      "opp": "Solves the wrapper-div problem. Need a semantic grouping element that doesn't break your grid? display: contents. Children lay out as if the wrapper doesn't exist.",
      "examples": "<b>Best:</b> Advanced component libraries",
      "miss": "Critical for component composition — lets you wrap elements for logic without breaking parent layout."
    },
    {
      "cat": "Visual",
      "cap": "CSS Gradients (linear, radial, conic)",
      "desc": "Color transitions without images",
      "verdict": "overused",
      "adoption": 95,
      "browser": 99,
      "opp": "Linear and radial are everywhere. Conic gradients are underused — great for pie charts, color wheels, loading spinners. Repeating gradients create patterns without images.",
      "examples": "<b>Overused:</b> Purple-to-blue gradient = 'AI product starter pack'. <b>Good:</b> Stripe's mesh gradients, Linear's accent gradients",
      "miss": "Gradients can have multiple color stops with positions. Gradient text via background-clip:text. Conic-gradient + border-radius = instant pie chart."
    },
    {
      "cat": "Visual",
      "cap": "backdrop-filter",
      "desc": "Blur/saturate what's BEHIND an element — glassmorphism",
      "verdict": "justright",
      "adoption": 70,
      "browser": 96,
      "opp": "Frosted glass nav bars, modal overlays, tooltip backgrounds. The Apple design language. Creates depth without z-index complexity.",
      "examples": "<b>Best:</b> Apple.com nav, macOS UI, Vercel dashboard",
      "miss": "backdrop-filter: blur(x) saturate(1.5) on a semi-transparent background is the full recipe. Performance cost is real — use sparingly on mobile."
    },
    {
      "cat": "Visual",
      "cap": "CSS Filters",
      "desc": "blur, brightness, grayscale, hue-rotate, saturate, sepia, invert on any element",
      "verdict": "underused",
      "adoption": 45,
      "browser": 99,
      "opp": "Instant image effects without Photoshop. grayscale(1) on logos until hover = elegant client showcase. brightness + contrast = dark mode image adjustment. Combine multiple filters in one declaration.",
      "examples": "<b>Best:</b> Client logo walls (grayscale → color on hover), disabled states, dark mode adjustments",
      "miss": "filter: drop-shadow() respects alpha transparency unlike box-shadow. Use it on PNGs/SVGs for accurate shadows. filter: invert(1) hue-rotate(180deg) is a one-line dark mode hack."
    },
    {
      "cat": "Visual",
      "cap": "mix-blend-mode",
      "desc": "Photoshop-style layer blending in CSS",
      "verdict": "underused",
      "adoption": 15,
      "browser": 98,
      "opp": "Duotone effects, creative overlays, text that 'cuts through' backgrounds. multiply, screen, difference — all the Photoshop modes, in CSS.",
      "examples": "<b>Best:</b> Spotify Wrapped, editorial design sites, award-winning agency work",
      "miss": "mix-blend-mode: difference on text over images creates automatic contrast. isolation: isolate prevents blend modes from affecting elements outside a container."
    },
    {
      "cat": "Visual",
      "cap": "clip-path",
      "desc": "Clip elements to circles, polygons, custom shapes",
      "verdict": "underused",
      "adoption": 25,
      "browser": 96,
      "opp": "Non-rectangular sections, creative hero shapes, avatar clipping, diagonal layouts. Fully animatable — morph between shapes on hover/scroll.",
      "examples": "<b>Best:</b> Award-winning agency sites, creative portfolios. <b>Most:</b> Everything is rectangles",
      "miss": "clip-path transitions smoothly between shapes if both have the same number of points. polygon() with matching point counts = smooth morphing."
    },
    {
      "cat": "Visual",
      "cap": "box-shadow",
      "desc": "Drop shadows, inset shadows, elevation",
      "verdict": "overused",
      "adoption": 98,
      "browser": 99,
      "opp": "Used correctly for elevation/depth. Overused as decoration — stacking 3+ shadows, glowing borders, etc. that tank performance on scroll.",
      "examples": "<b>Overused:</b> Dribbble-style 'everything floats'. <b>Good:</b> Material Design elevation, Notion card hover",
      "miss": "Layered shadows (comma-separated) with decreasing opacity look more realistic than one big shadow. inset shadows create debossed effects. Shadows don't work on images with transparency — use filter: drop-shadow() instead."
    },
    {
      "cat": "Visual",
      "cap": "color-mix()",
      "desc": "Blend two colors in CSS — no preprocessor needed",
      "verdict": "emerging",
      "adoption": 8,
      "browser": 90,
      "opp": "Dynamic hover states from one base color. Theming without Sass. color-mix(in srgb, var(--primary) 80%, white) = instant lighter variant.",
      "examples": "<b>Best:</b> Modern design systems starting to adopt. <b>Most:</b> Don't know it exists",
      "miss": "Replace hardcoded hover colors with color-mix(in srgb, var(--btn-color) 85%, black). One base color generates your entire palette."
    },
    {
      "cat": "Visual",
      "cap": "CSS Shapes (shape-outside)",
      "desc": "Text wraps around circles, polygons, images",
      "verdict": "underused",
      "adoption": 5,
      "browser": 96,
      "opp": "Magazine-style text flowing around a circular image or custom shape. Pure CSS, no JavaScript. Editorial layouts become trivial.",
      "examples": "<b>Best:</b> NYT long-form articles, editorial design",
      "miss": "Combine with float and clip-path for text that wraps around AND clips to the same shape. shape-margin adds breathing room."
    },
    {
      "cat": "Animation",
      "cap": "CSS Transitions",
      "desc": "Smooth interpolation between two states on property change",
      "verdict": "essential",
      "adoption": 98,
      "browser": 99,
      "opp": "Every interactive element needs a transition. Buttons, links, cards, form inputs. No transition = the UI feels broken. This is table stakes.",
      "examples": "<b>Every professional site</b>. Missing transitions feel like a bug",
      "miss": "transition: all is a performance anti-pattern. Specify exact properties: transition: transform 0.2s, opacity 0.2s. cubic-bezier() custom easing is underused — Google 'cubic-bezier.com' for visual editor."
    },
    {
      "cat": "Animation",
      "cap": "@keyframes Animations",
      "desc": "Multi-step animations with full timeline control",
      "verdict": "overused",
      "adoption": 88,
      "browser": 99,
      "opp": "Correct for loading spinners, entrance sequences, attention pulses. Overused when everything bounces, fades, and spins simultaneously. If more than 2 things animate at once, reconsider.",
      "examples": "<b>Good:</b> Stripe's page load stagger, Linear's entrance animations. <b>Bad:</b> Landing pages where every element 'flies in'",
      "miss": "animation-delay with staggered values creates sequenced reveals without JS. animation-fill-mode: both prevents elements from snapping back. animation-play-state: paused + JS toggle = controllable animations."
    },
    {
      "cat": "Animation",
      "cap": "CSS Transforms",
      "desc": "rotate, scale, translate, skew — GPU-accelerated visual changes",
      "verdict": "justright",
      "adoption": 92,
      "browser": 99,
      "opp": "The correct way to animate position and size. GPU-accelerated, doesn't trigger layout reflow. Always use transform: translateX() instead of animating left/top.",
      "examples": "<b>Best:</b> Card hover lifts, 3D flips, parallax. Universal",
      "miss": "transform-origin changes the pivot point — critical for rotation effects. will-change: transform hints the browser to prepare GPU acceleration (but don't put it on everything). translate, rotate, scale are now individual CSS properties — no need for the transform shorthand."
    },
    {
      "cat": "Animation",
      "cap": "Web Animations API (WAAPI)",
      "desc": "JavaScript animation with play/pause/reverse/timeline control",
      "verdict": "underused",
      "adoption": 20,
      "browser": 96,
      "opp": "Full programmatic control without a library. element.animate() with play(), pause(), reverse(), finish(). Replace GSAP for 80% of use cases.",
      "examples": "<b>Best:</b> Google's material motion, progressive web apps",
      "miss": "getAnimations() lets you query running animations. Animation.finished returns a Promise for sequencing. Combine with ScrollTimeline for scroll-linked animations."
    },
    {
      "cat": "Animation",
      "cap": "CSS scroll-driven animations",
      "desc": "Animate elements based on scroll position — pure CSS, no JS",
      "verdict": "emerging",
      "adoption": 5,
      "browser": 78,
      "opp": "Progress bars that fill as you scroll, parallax without JS, elements that animate into view on scroll. animation-timeline: scroll() or view() replaces all Intersection Observer animation code.",
      "examples": "<b>Best:</b> Chrome demos, bleeding-edge portfolio sites",
      "miss": "view() timeline triggers animation when element enters viewport — replaces scroll-triggered JS. animation-range controls when in the scroll the animation starts and ends."
    },
    {
      "cat": "Animation",
      "cap": "prefers-reduced-motion",
      "desc": "Detect user's motion sensitivity setting and disable/reduce animations",
      "verdict": "essential",
      "adoption": 30,
      "browser": 98,
      "opp": "Required for accessibility. 1 in 3 people experience motion sickness from web animations. Wrap all animations in @media (prefers-reduced-motion: no-preference) {}.",
      "examples": "<b>Best:</b> Apple, GitHub, Stripe all respect this. <b>Most:</b> Completely ignore it",
      "miss": "This isn't optional accessibility — it's a legal requirement in many jurisdictions. Use it as the DEFAULT check: no-preference means they're fine with motion. Anything else, reduce or remove."
    },
    {
      "cat": "Animation",
      "cap": "View Transitions API",
      "desc": "Smooth animated transitions between page loads or DOM states",
      "verdict": "emerging",
      "adoption": 5,
      "browser": 72,
      "opp": "The SPA-feeling smooth page transition for MPAs. Also works for in-page state changes — list items reordering, layout shifts, tab changes. document.startViewTransition(() => { updateDOM() }).",
      "examples": "<b>Best:</b> Chrome team demos, some progressive blogs. <b>Most:</b> Don't know it exists",
      "miss": "Works for MPAs with a meta tag: <meta name='view-transition' content='same-origin'>. Assign view-transition-name to elements that should morph between states."
    },
    {
      "cat": "Interactive",
      "cap": "<dialog> element",
      "desc": "Native modal with backdrop, focus trapping, Escape key",
      "verdict": "underused",
      "adoption": 30,
      "browser": 96,
      "opp": "Replaces every modal library. showModal() handles focus trap, backdrop, escape-to-close, scroll lock, and top-layer stacking — all natively. Zero dependencies.",
      "examples": "<b>Best:</b> GitHub (switched to native dialog). <b>Most:</b> Still installing 30KB modal libraries",
      "miss": "dialog::backdrop is styleable. The open attribute is toggled automatically. returnValue captures form submission results from within the dialog."
    },
    {
      "cat": "Interactive",
      "cap": "<details> / <summary>",
      "desc": "Native collapsible/accordion — zero JavaScript",
      "verdict": "underused",
      "adoption": 35,
      "browser": 98,
      "opp": "Every FAQ, collapsible panel, and accordion should use this. Keyboard accessible, screen reader friendly, works without JS. The name attribute creates exclusive accordions (only one open at a time).",
      "examples": "<b>Best:</b> MDN, some design systems. <b>Most:</b> Install accordion components",
      "miss": "The name attribute for exclusive accordions is new and powerful. The toggle event fires on open/close. You can animate open/close with CSS (though it requires interpolate-size or calc-size for height animation)."
    },
    {
      "cat": "Interactive",
      "cap": "Popover API",
      "desc": "Native popover with light dismiss, top-layer, no z-index fights",
      "verdict": "emerging",
      "adoption": 10,
      "browser": 90,
      "opp": "Tooltips, dropdowns, menus, notification toasts. Lives in the top-layer — above everything, no z-index needed. Light dismiss = click outside to close.",
      "examples": "<b>Best:</b> Cutting-edge design systems starting to adopt",
      "miss": "popovertarget attribute on a button auto-toggles the popover — zero JS. anchor positioning (CSS Anchor Positioning) pairs with this to position popovers relative to their trigger."
    },
    {
      "cat": "Interactive",
      "cap": "Drag & Drop API",
      "desc": "Native drag-and-drop with dataTransfer",
      "verdict": "justright",
      "adoption": 55,
      "browser": 99,
      "opp": "Kanban boards, file uploads, list reordering, dashboard customization. The native API works but is clunky — most production apps add a library (dnd-kit, SortableJS) for polish.",
      "examples": "<b>Best:</b> Trello, Notion, Linear (all use libraries on top). Native API for simple cases",
      "miss": "dataTransfer.setDragImage() lets you customize the ghost image. effectAllowed and dropEffect control cursor appearance. For simple cases, the native API is sufficient."
    },
    {
      "cat": "Interactive",
      "cap": "<datalist>",
      "desc": "Native autocomplete/typeahead for any input — zero JS",
      "verdict": "underused",
      "adoption": 15,
      "browser": 96,
      "opp": "Autocomplete search, tag suggestions, location pickers. One HTML element gives you browser-native fuzzy matching. Replaces 90% of autocomplete library use cases.",
      "examples": "<b>Best:</b> Rare in production — most over-engineer this with React components",
      "miss": "Works with input types: text, email, url, tel, search, range, color, date, time. On range inputs, datalist creates tick marks. On color inputs, it creates preset swatches."
    },
    {
      "cat": "Interactive",
      "cap": "<progress> & <meter>",
      "desc": "Semantic progress bars and gauges",
      "verdict": "underused",
      "adoption": 20,
      "browser": 98,
      "opp": "Upload progress, skill bars, disk usage, health indicators. Screen readers understand these — a styled div with a width percentage is meaningless to assistive tech.",
      "examples": "<b>Best:</b> GitHub (uses native progress). <b>Most:</b> Divs with percentage widths",
      "miss": "<progress> without a value attribute shows an indeterminate loading bar. <meter> has low/high/optimum attributes that change color automatically. Both are styleable with pseudo-elements."
    },
    {
      "cat": "Interactive",
      "cap": "contenteditable",
      "desc": "Make any element editable — inline text editing",
      "verdict": "justright",
      "adoption": 40,
      "browser": 99,
      "opp": "Rich text editors, inline editing, editable tables, WYSIWYG interfaces. The foundation of every web-based text editor (Google Docs, Notion).",
      "examples": "<b>Best:</b> Notion, Google Docs, Medium (all built on top of this)",
      "miss": "contenteditable='plaintext-only' prevents rich text paste. The input event fires on every keystroke. execCommand is deprecated — use the Clipboard API and document.getSelection() instead."
    },
    {
      "cat": "Interactive",
      "cap": "Fullscreen API",
      "desc": "Make any element fullscreen — not just video",
      "verdict": "justright",
      "adoption": 50,
      "browser": 97,
      "opp": "Video players, presentations, games, dashboards, image viewers, data visualization. Works on any element — a div, a canvas, a section.",
      "examples": "<b>Best:</b> YouTube, Google Slides, web-based games",
      "miss": "requestFullscreen() works on any element, not just video. The :fullscreen pseudo-class lets you style the fullscreen state. fullscreenchange event fires on enter/exit."
    },
    {
      "cat": "Forms",
      "cap": "Form validation (required, pattern, min, max)",
      "desc": "Built-in HTML5 validation without JavaScript",
      "verdict": "underused",
      "adoption": 45,
      "browser": 99,
      "opp": "required, pattern (regex), min/max, minlength/maxlength, type-based validation (email, url, number). Browser provides error messages, prevents submission, and highlights invalid fields — all without JS.",
      "examples": "<b>Most:</b> Write custom JS validation from scratch. <b>Should:</b> Use native first, enhance with JS",
      "miss": "The :valid, :invalid, :user-valid, :user-invalid pseudo-classes let you style fields based on validation state. setCustomValidity() lets you write custom error messages. The constraint validation API gives you full programmatic control."
    },
    {
      "cat": "Forms",
      "cap": "input types (color, date, range, etc.)",
      "desc": "Native pickers for dates, colors, numbers, ranges",
      "verdict": "underused",
      "adoption": 50,
      "browser": 95,
      "opp": "date, time, datetime-local, color, range, number, email, tel, url, search — each type gets a native picker optimized for the device. Mobile keyboards switch based on input type.",
      "examples": "<b>Best:</b> Mobile-first apps that use type='tel' for number entry. <b>Most:</b> Text inputs for everything",
      "miss": "inputmode attribute controls mobile keyboard without changing the input type. type='search' gets a native clear button. type='color' is a full color picker. type='date' eliminates date picker libraries on mobile."
    },
    {
      "cat": "Forms",
      "cap": "FormData API",
      "desc": "Collect all form data in one line — no querySelector loops",
      "verdict": "underused",
      "adoption": 35,
      "browser": 99,
      "opp": "new FormData(formElement) grabs everything — selects, checkboxes, file inputs, radio buttons. Serializes to JSON, sends to fetch(). Eliminates manual form data collection.",
      "examples": "<b>Best:</b> Modern SPAs. <b>Most:</b> document.getElementById() for each field individually",
      "miss": "FormData works with fetch() directly: fetch(url, {method:'POST', body: new FormData(form)}). Object.fromEntries(new FormData(form)) converts to a plain object in one line."
    },
    {
      "cat": "Forms",
      "cap": "autocomplete attribute",
      "desc": "Tell browsers what to autofill — names, addresses, cards",
      "verdict": "underused",
      "adoption": 25,
      "browser": 99,
      "opp": "autocomplete='given-name', 'email', 'street-address', 'cc-number' — browsers autofill intelligently. Reduces checkout abandonment by 25%+. Most forms leave this as 'on' or 'off'.",
      "examples": "<b>Best:</b> Shopify checkout, Amazon. <b>Most:</b> Generic autocomplete='on' that guesses wrong",
      "miss": "There are 50+ autocomplete values. 'new-password' triggers password generator. 'one-time-code' helps with SMS verification. 'section-*' groups related fields for autofill."
    },
    {
      "cat": "Modern CSS",
      "cap": "CSS Custom Properties (variables)",
      "desc": "Runtime-changeable variables: --color, --spacing, --radius",
      "verdict": "essential",
      "adoption": 85,
      "browser": 98,
      "opp": "The foundation of every design system. Theming, dark mode, component APIs, runtime changes via JavaScript. Unlike Sass variables, these cascade and can be changed dynamically.",
      "examples": "<b>Every design system.</b> <b>Best:</b> Tailwind v4 is built entirely on CSS variables",
      "miss": "Custom properties cascade — set on parent, inherit to all children. Use with calc(): calc(var(--spacing) * 2). JavaScript reads/writes them: el.style.setProperty('--color', '#ff0'). They work in media queries with @property registration."
    },
    {
      "cat": "Modern CSS",
      "cap": ":has() selector",
      "desc": "Style a parent based on what's inside it — the 'parent selector'",
      "verdict": "underused",
      "adoption": 20,
      "browser": 91,
      "opp": "The most powerful CSS selector ever added. Style a form when it has an invalid input. Style a card when it contains an image. Style a nav when a dropdown is open. All pure CSS, no JS.",
      "examples": "<b>Best:</b> Cutting-edge design systems. <b>Most:</b> Still using JS to add/remove parent classes",
      "miss": "form:has(input:invalid) styles the form itself. .card:has(img) applies only to cards with images. body:has(dialog[open]) styles the body when a dialog is open. Eliminates entire categories of JS."
    },
    {
      "cat": "Modern CSS",
      "cap": "CSS Nesting",
      "desc": "Native nesting — & parent selector, nested media queries",
      "verdict": "underused",
      "adoption": 25,
      "browser": 88,
      "opp": "The #1 reason people used Sass was nesting. It's now native CSS. Cleaner scoping, co-located media queries, reduced specificity issues.",
      "examples": "<b>Best:</b> New projects dropping Sass. <b>Most:</b> Still using Sass/PostCSS for nesting",
      "miss": "Media queries can be nested inside selectors — keeps responsive styles co-located with their component. The & selector works like Sass but with native specificity rules."
    },
    {
      "cat": "Modern CSS",
      "cap": "accent-color",
      "desc": "Theme all native form controls with one property",
      "verdict": "underused",
      "adoption": 12,
      "browser": 93,
      "opp": "One line of CSS brands every checkbox, radio button, range slider, and progress bar. accent-color: var(--brand). Replaces massive custom checkbox/radio CSS hacks.",
      "examples": "<b>Best:</b> Minimal design systems that embrace native controls",
      "miss": "Works on checkbox, radio, range, progress. Combine with color-scheme: dark for proper dark mode form controls. Most devs still write 50 lines of CSS to customize a checkbox when one property would suffice."
    },
    {
      "cat": "Modern CSS",
      "cap": "text-wrap: balance",
      "desc": "Balanced line breaks for headings — no orphaned words",
      "verdict": "underused",
      "adoption": 8,
      "browser": 85,
      "opp": "Fixes the #1 typography complaint — one word orphaned on the last line of a heading. One CSS property. text-wrap: pretty does the same for paragraphs.",
      "examples": "<b>Best:</b> Typography-focused blogs and editorial sites",
      "miss": "text-wrap: balance is for short text (headlines, captions). text-wrap: pretty is for paragraphs — prevents orphans at paragraph ends. Both are pure CSS, zero JS."
    },
    {
      "cat": "Modern CSS",
      "cap": ":focus-visible",
      "desc": "Focus ring only for keyboard users — not mouse clicks",
      "verdict": "essential",
      "adoption": 55,
      "browser": 95,
      "opp": "Solves the oldest UX/accessibility tension: focus outlines are necessary for keyboard users but ugly for mouse users. This pseudo-class only matches keyboard focus.",
      "examples": "<b>Best:</b> GitHub, Google, any accessibility-conscious site",
      "miss": "Combine with :focus:not(:focus-visible) to remove the default focus ring on mouse clicks while keeping it for keyboard. This should be in every reset stylesheet."
    },
    {
      "cat": "Modern CSS",
      "cap": "@property (registered custom properties)",
      "desc": "Define types, initial values, and inheritance for CSS variables",
      "verdict": "emerging",
      "adoption": 5,
      "browser": 85,
      "opp": "Makes CSS variables animatable. Register --angle as <angle> and you can transition it — enabling animated gradients, color animations, and more that were impossible before.",
      "examples": "<b>Best:</b> Animated gradient borders, hue rotation effects",
      "miss": "The killer feature: animated gradients. Register --gradient-angle as <angle>, then transition it. Also enables type checking for CSS variables and proper initial values."
    },
    {
      "cat": "Modern CSS",
      "cap": "@layer (Cascade Layers)",
      "desc": "Control CSS specificity with explicit ordering — no more specificity wars",
      "verdict": "emerging",
      "adoption": 10,
      "browser": 92,
      "opp": "Define layers: @layer reset, base, components, utilities. Styles in later layers always win regardless of specificity. Eliminates !important hacks and specificity battles.",
      "examples": "<b>Best:</b> Modern CSS frameworks (Tailwind v4, Open Props). <b>Most:</b> Don't know it exists",
      "miss": "@layer is the fix for the #1 CSS maintenance problem. Third-party styles go in a low layer, your overrides go in a high layer. No more fighting specificity with increasingly specific selectors."
    },
    {
      "cat": "Modern CSS",
      "cap": "@scope",
      "desc": "Scope styles to a specific DOM subtree — native CSS Modules",
      "verdict": "emerging",
      "adoption": 2,
      "browser": 78,
      "opp": "Style isolation without Shadow DOM, CSS Modules, or BEM naming. @scope (.card) to (.card-footer) { } applies styles only within that subtree.",
      "examples": "<b>Best:</b> Very early adoption. <b>Most:</b> Still using BEM or CSS Modules",
      "miss": "The 'to' part is the scope limit — styles stop applying at that boundary. Proximity-based specificity means the closest scope wins, which is how developers intuitively expect CSS to work."
    },
    {
      "cat": "Scroll",
      "cap": "scroll-snap-type / scroll-snap-align",
      "desc": "CSS-only snap-to-grid scrolling — carousels without JS",
      "verdict": "underused",
      "adoption": 30,
      "browser": 96,
      "opp": "Horizontal carousels, full-page sections, image galleries, onboarding flows. Scroll-snap-type: x mandatory on the container, scroll-snap-align: center on the children. Done.",
      "examples": "<b>Best:</b> App Store (iOS-style horizontal scroll), some e-commerce product carousels",
      "miss": "scroll-snap-stop: always forces users to see every item (they can't flick past). Combine with overscroll-behavior: contain to prevent page scroll when reaching carousel edges."
    },
    {
      "cat": "Scroll",
      "cap": "scroll-behavior: smooth",
      "desc": "One CSS line for smooth scrolling on anchor links",
      "verdict": "justright",
      "adoption": 60,
      "browser": 96,
      "opp": "html { scroll-behavior: smooth } — that's the entire implementation. Works for anchor links, scrollIntoView(), and any hash-based navigation.",
      "examples": "<b>Most sites with anchor navigation</b> should have this",
      "miss": "Respect prefers-reduced-motion — wrap in @media (prefers-reduced-motion: no-preference). scrollIntoView({behavior:'smooth', block:'nearest'}) gives you fine control from JS."
    },
    {
      "cat": "Scroll",
      "cap": "overscroll-behavior",
      "desc": "Prevent scroll chaining — modal scrolls don't scroll the page behind",
      "verdict": "underused",
      "adoption": 25,
      "browser": 95,
      "opp": "Without this, scrolling to the end of a modal/sidebar then keeps scrolling the page behind it. overscroll-behavior: contain on the modal fixes it. One line.",
      "examples": "<b>Best:</b> Well-built modal implementations. <b>Most:</b> Let scroll chain through to the body",
      "miss": "overscroll-behavior: none also prevents pull-to-refresh on mobile — useful for web apps that handle their own refresh. Works on any scrollable container, not just modals."
    },
    {
      "cat": "Scroll",
      "cap": "Intersection Observer",
      "desc": "Detect when elements enter/exit the viewport — no scroll listeners",
      "verdict": "underused",
      "adoption": 40,
      "browser": 97,
      "opp": "Lazy loading, infinite scroll, scroll-triggered animations, analytics tracking, ad viewability. Asynchronous and off-main-thread — dramatically more performant than scroll event listeners.",
      "examples": "<b>Best:</b> Instagram (infinite scroll), Medium (lazy images), any site with scroll animations",
      "miss": "threshold can be an array — trigger at 0%, 25%, 50%, 75%, 100% visibility. rootMargin creates a buffer zone — start loading images 200px before they're visible."
    },
    {
      "cat": "Performance",
      "cap": "loading='lazy'",
      "desc": "One HTML attribute defers loading off-screen images/iframes",
      "verdict": "underused",
      "adoption": 40,
      "browser": 96,
      "opp": "Every image below the fold should have loading='lazy'. Every third-party iframe should have it. Zero JS. Saves megabytes on image-heavy pages.",
      "examples": "<b>Should be everywhere.</b> <b>Most:</b> Load all images eagerly on page load",
      "miss": "Don't lazy-load above-the-fold images — it delays LCP. Pair with decoding='async' for images. fetchpriority='high' on hero images tells the browser to prioritize them."
    },
    {
      "cat": "Performance",
      "cap": "content-visibility: auto",
      "desc": "Browser skips rendering off-screen content entirely",
      "verdict": "underused",
      "adoption": 5,
      "browser": 82,
      "opp": "The single biggest rendering performance win for long pages. Tell the browser to skip layout, paint, and style calculations for off-screen sections. Can cut render time 90%+ on long pages.",
      "examples": "<b>Best:</b> Google Search (uses this internally). <b>Most:</b> Don't know it exists",
      "miss": "Requires contain-intrinsic-size to prevent layout jumps: content-visibility: auto; contain-intrinsic-size: 0 500px. The browser estimates section height and only renders when approaching the viewport."
    },
    {
      "cat": "Performance",
      "cap": "will-change",
      "desc": "Hint the browser to prepare GPU resources for upcoming animations",
      "verdict": "overused",
      "adoption": 55,
      "browser": 96,
      "opp": "Correctly used: applied just before an animation starts, removed after. Incorrectly used (90% of the time): permanently applied to everything as a 'make it faster' cheat. Each will-change allocates GPU memory.",
      "examples": "<b>Misuse:</b> * { will-change: transform } in production CSS. <b>Correct:</b> Applied on :hover before animation triggers",
      "miss": "will-change is a last resort for jank, not a default optimization. Each instance creates a GPU layer that consumes memory. A page with 100 will-change elements will HURT performance."
    },
    {
      "cat": "Performance",
      "cap": "<link rel='preload'> / <link rel='prefetch'>",
      "desc": "Tell the browser what to load next — fonts, scripts, data",
      "verdict": "underused",
      "adoption": 35,
      "browser": 96,
      "opp": "Preload critical fonts, above-the-fold images, key JS. Prefetch next-page resources for instant navigation. The difference between a 2s and 200ms page feel.",
      "examples": "<b>Best:</b> Next.js (auto-prefetches links), Shopify. <b>Most:</b> Let the browser discover resources late",
      "miss": "rel='preload' is for current page critical resources. rel='prefetch' is for likely next navigation. rel='preconnect' establishes early connections to third-party domains. rel='dns-prefetch' for less critical third-party domains."
    },
    {
      "cat": "Performance",
      "cap": "fetchpriority attribute",
      "desc": "Tell the browser which resources are high/low priority",
      "verdict": "underused",
      "adoption": 8,
      "browser": 88,
      "opp": "fetchpriority='high' on hero images/LCP elements. fetchpriority='low' on below-fold images. Directly impacts Core Web Vitals LCP score.",
      "examples": "<b>Best:</b> Performance-optimized e-commerce sites",
      "miss": "Works on <img>, <link>, <script>, and fetch(). The browser already prioritizes, but this gives you explicit control. High priority on your LCP image can improve LCP by 500ms+."
    },
    {
      "cat": "Performance",
      "cap": "<script type='module'> / async / defer",
      "desc": "Control when JavaScript loads and executes",
      "verdict": "essential",
      "adoption": 70,
      "browser": 99,
      "opp": "defer: downloads during HTML parse, executes after. async: downloads during parse, executes immediately. type='module': auto-deferred, supports import/export. Most sites load all JS render-blocking.",
      "examples": "<b>Essential for every site with JS</b>",
      "miss": "type='module' scripts are deferred by default AND support import/export. async is for independent scripts (analytics, ads). defer is for scripts that depend on DOM. Default (no attribute) blocks HTML parsing — the worst option."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "<canvas> 2D context",
      "desc": "Pixel-level drawing — charts, games, image processing, signatures",
      "verdict": "justright",
      "adoption": 55,
      "browser": 99,
      "opp": "The right tool for pixel manipulation, real-time graphics, and procedural generation. Wrong for things SVG or CSS can handle (icons, simple shapes, charts).",
      "examples": "<b>Best:</b> Chart.js, Figma, Excalidraw, games. <b>Overuse:</b> Using canvas for things CSS can do",
      "miss": "OffscreenCanvas moves rendering to a web worker — keeps UI thread free. Canvas is resolution-dependent — always set actual pixel dimensions AND CSS dimensions separately for sharp rendering."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "Clipboard API (navigator.clipboard)",
      "desc": "Async read/write clipboard — copy buttons, paste handling",
      "verdict": "justright",
      "adoption": 50,
      "browser": 95,
      "opp": "Copy-to-clipboard buttons, paste-from-clipboard handlers, rich text clipboard manipulation. Replaces deprecated document.execCommand('copy').",
      "examples": "<b>Best:</b> GitHub (copy code blocks), Vercel (copy deploy URLs), documentation sites",
      "miss": "navigator.clipboard.write() can copy rich content (HTML, images). navigator.clipboard.read() can paste images from clipboard. Always handle the permission denial gracefully."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "ResizeObserver",
      "desc": "Detect when any element changes size — not just the viewport",
      "verdict": "underused",
      "adoption": 30,
      "browser": 96,
      "opp": "Responsive charts that rerender on container resize, dynamic text fitting, layout-aware components. Like a media query but for any individual element.",
      "examples": "<b>Best:</b> Chart libraries, embeddable widgets, responsive dashboards",
      "miss": "Fires on initial render too — use it for initialization. Reports borderBoxSize, contentBoxSize, and devicePixelContentBoxSize. Replaces all window.onresize hacks for component-level responsiveness."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "Web Workers",
      "desc": "Run JavaScript off the main thread — no UI blocking",
      "verdict": "underused",
      "adoption": 15,
      "browser": 99,
      "opp": "Heavy computation (data parsing, image processing, encryption, sorting large datasets) without freezing the UI. Critical for apps that process data client-side.",
      "examples": "<b>Best:</b> Figma (heavy canvas operations), Google Sheets, VS Code web",
      "miss": "SharedArrayBuffer enables shared memory between workers and main thread. Comlink library makes worker communication feel like normal function calls. Transferable objects avoid copying large data."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "Service Workers",
      "desc": "Offline capability, push notifications, background sync, caching",
      "verdict": "underused",
      "adoption": 20,
      "browser": 96,
      "opp": "Make any website work offline. Cache critical resources, serve stale-while-revalidate, handle push notifications. The foundation of Progressive Web Apps.",
      "examples": "<b>Best:</b> Twitter/X, Pinterest, Starbucks — all PWAs. <b>Most:</b> Websites that break completely offline",
      "miss": "Workbox library simplifies service worker creation. Cache strategies: network-first (API data), cache-first (static assets), stale-while-revalidate (best of both). Background Sync retries failed requests when connection returns."
    },
    {
      "cat": "Canvas & APIs",
      "cap": "Web Components (Custom Elements + Shadow DOM)",
      "desc": "Framework-agnostic components with encapsulated styles",
      "verdict": "underused",
      "adoption": 18,
      "browser": 96,
      "opp": "Build components that work in React, Vue, Angular, or plain HTML. Shadow DOM provides true style encapsulation — no CSS leaking in or out. Used by YouTube, GitHub, Salesforce.",
      "examples": "<b>Best:</b> YouTube (uses custom elements), GitHub (uses custom elements), Salesforce Lightning",
      "miss": "Declarative Shadow DOM (new) enables SSR. Slot elements enable content projection. :host and :part pseudo-elements bridge the shadow boundary for styling. Custom elements auto-register with customElements.define()."
    },
    {
      "cat": "Text",
      "cap": "clamp() for fluid typography",
      "desc": "Responsive font sizes without media queries",
      "verdict": "underused",
      "adoption": 30,
      "browser": 95,
      "opp": "font-size: clamp(1rem, 2.5vw, 2rem) creates font sizes that scale smoothly between a min and max. No breakpoints needed. Replaces 5+ media queries with one line.",
      "examples": "<b>Best:</b> Modern design systems, typography-first blogs",
      "miss": "Works for any CSS property, not just font-size. Use for padding, margin, gap. The formula clamp(min, preferred, max) where preferred is usually a viewport unit."
    },
    {
      "cat": "Text",
      "cap": "font-variant-numeric",
      "desc": "Control number rendering — tabular-nums, oldstyle-nums, fractions",
      "verdict": "underused",
      "adoption": 10,
      "browser": 92,
      "opp": "tabular-nums makes numbers monospaced — critical for tables, prices, dashboards. oldstyle-nums for editorial body text. Proper fractions: 1/2 renders as ½.",
      "examples": "<b>Best:</b> Financial dashboards, editorial sites. <b>Most:</b> Numbers misalign in tables",
      "miss": "font-variant-numeric: tabular-nums should be on every data table. Without it, numbers have proportional widths and columns don't align. Also: ordinal (1st, 2nd), slashed-zero (0 vs O)."
    },
    {
      "cat": "Text",
      "cap": "text-decoration-* properties",
      "desc": "Thickness, color, offset, skip-ink for underlines",
      "verdict": "underused",
      "adoption": 15,
      "browser": 94,
      "opp": "Style underlines properly: text-decoration-thickness, text-underline-offset, text-decoration-color, text-decoration-skip-ink. Replaces border-bottom hacks for link styling.",
      "examples": "<b>Best:</b> Editorial/magazine sites. <b>Most:</b> Use border-bottom for styled underlines",
      "miss": "text-underline-offset creates space between text and underline. text-decoration-skip-ink: auto makes underlines skip descenders (g, y, p) beautifully. These replaced decades of border-bottom workarounds."
    },
    {
      "cat": "Text",
      "cap": "::selection pseudo-element",
      "desc": "Style highlighted/selected text",
      "verdict": "underused",
      "adoption": 20,
      "browser": 99,
      "opp": "Brand your text selection color. ::selection { background: var(--brand); color: white; }. Small detail that signals design intentionality.",
      "examples": "<b>Best:</b> Branded websites, portfolio sites",
      "miss": "Only color, background-color, text-shadow, and a few other properties work in ::selection. Keep it simple — a branded background color is usually enough."
    },
    {
      "cat": "Media",
      "cap": "<picture> / srcset / sizes",
      "desc": "Serve different images based on viewport, resolution, format",
      "verdict": "underused",
      "adoption": 35,
      "browser": 97,
      "opp": "Serve WebP to modern browsers, JPEG to old ones. Serve 400px images to phones, 1200px to desktops. Saves bandwidth and improves Core Web Vitals.",
      "examples": "<b>Best:</b> E-commerce (product images), news sites (hero images)",
      "miss": "<source type='image/avif'> serves next-gen formats with automatic fallback. sizes attribute tells the browser how wide the image will display BEFORE downloading it. Without sizes, srcset is guessing."
    },
    {
      "cat": "Media",
      "cap": "<video> and <audio> elements",
      "desc": "Native media playback with controls, autoplay, captions",
      "verdict": "justright",
      "adoption": 65,
      "browser": 99,
      "opp": "Native video player with poster, controls, preload strategies. <track> element adds subtitles/captions. Most sites still use YouTube embeds when native video would be faster.",
      "examples": "<b>Best:</b> Landing pages with background video, podcast sites",
      "miss": "preload='metadata' loads just dimensions/duration without downloading the video. poster sets the preview image. <track kind='subtitles'> adds proper captioning. Media Session API controls system media notifications."
    },
    {
      "cat": "Media",
      "cap": "@media (prefers-color-scheme)",
      "desc": "Detect system dark/light mode preference",
      "verdict": "justright",
      "adoption": 55,
      "browser": 96,
      "opp": "Automatically match OS theme. Combined with CSS variables, a full dark mode is ~20 lines of CSS. Users increasingly expect sites to respect their system preference.",
      "examples": "<b>Best:</b> GitHub, Twitter/X, MDN — all respect system preference",
      "miss": "Pair with color-scheme: light dark on :root to automatically adjust form controls, scrollbars, and default colors. The meta tag <meta name='color-scheme' content='light dark'> enables this early, before CSS loads."
    },
    {
      "cat": "Semantic",
      "cap": "<header>, <main>, <nav>, <aside>, <footer>, <article>, <section>",
      "desc": "Semantic landmarks — structure that assistive tech understands",
      "verdict": "underused",
      "adoption": 50,
      "browser": 99,
      "opp": "Screen readers use landmarks to navigate. <nav> = skip to navigation. <main> = skip to content. <aside> = complementary content. Most sites are <div> soup with zero landmarks.",
      "examples": "<b>Essential for every site.</b> <b>Most:</b> <div class='header'> instead of <header>",
      "miss": "Each landmark element creates an ARIA role automatically — no need for role attributes. <article> means independently redistributable content (blog post, comment, product card). <section> is for thematic grouping with a heading."
    },
    {
      "cat": "Semantic",
      "cap": "<time> element",
      "desc": "Machine-readable dates and times",
      "verdict": "underused",
      "adoption": 10,
      "browser": 99,
      "opp": "<time datetime='2025-02-24'>Feb 24, 2025</time> lets machines parse your dates while humans see friendly text. Used by search engines, RSS readers, social media scrapers.",
      "examples": "<b>Best:</b> Blog posts, news articles, event listings",
      "miss": "The datetime attribute accepts ISO 8601 format. Enables Google's structured data understanding. Relative time libraries (timeago) can enhance this with 'posted 3 hours ago' without losing the machine-readable date."
    },
    {
      "cat": "Semantic",
      "cap": "<abbr>, <mark>, <cite>, <code>, <kbd>, <samp>",
      "desc": "Inline semantic elements — abbreviations, highlights, citations, code",
      "verdict": "underused",
      "adoption": 8,
      "browser": 99,
      "opp": "<abbr title='HyperText Markup Language'>HTML</abbr> shows tooltip on hover. <mark> highlights text. <kbd> shows keyboard shortcuts. <code> for inline code. Most devs use <span class='highlight'> instead.",
      "examples": "<b>Best:</b> Documentation sites, technical writing",
      "miss": "<kbd> inside a <samp> means output that should be typed. <cite> is for work titles (books, films), not people. <mark> is for search result highlighting or attention points. These carry semantic meaning that screen readers announce."
    },
    {
      "cat": "Semantic",
      "cap": "ARIA attributes (aria-label, aria-live, etc.)",
      "desc": "Bridge gaps where HTML semantics fall short",
      "verdict": "overused",
      "adoption": 60,
      "browser": 99,
      "opp": "ARIA is a LAST RESORT — native HTML semantics should come first. 'No ARIA is better than bad ARIA.' Most devs add role='button' to a <div> instead of using <button>.",
      "examples": "<b>Misuse:</b> ARIA on elements that already have semantics. <b>Good:</b> aria-live for dynamic content, aria-expanded for custom disclosures",
      "miss": "The first rule of ARIA: don't use ARIA. Use semantic HTML. Second rule: don't override native semantics. aria-live='polite' for toast notifications. aria-expanded for custom accordions (but <details> is better). aria-describedby links help text to inputs."
    }
  ]
}
