Prefer native HTML and SVG

Without hover or zoom, ship SVG and <details>, not a library.

From nextjs-pagespeed.

An FAQ, two ways

Press Reload, then click a question in both panes.

JS accordionBad

Loading JS: … Dead clicks: 0
details / summaryGood
Can I export to CSV?

Yes. Every table has an Export button in its header.

Is my data encrypted?

At rest and in transit.

Can I cancel any time?

Yes, from Settings. No call needed.

0 ms JS: 0 B Dead clicks: 0
<details name="faq">  <!-- same name: one open at a time -->
  <summary>Can I export to CSV?</summary>
  <p>Yes. Every table has an Export button in its header.</p>
</details>

summary { list-style: none; cursor: pointer; }
summary::-webkit-details-marker { display: none; }
details[open] .chevron { transform: rotate(180deg); }

A sparkline, two ways

Press Load chart, then type in the box.

Client chart libraryBad
Revenue, 24 months$92k
Not loaded

 

Download – Main thread blocked – Painted at –
Inline SVG in the HTMLGood
Revenue, 24 months$92k

+119% since month 1

Markup … Main thread blocked 0 ms Painted at …

Worst input delay: –

// Server Component: the client gets markup only
export function Sparkline({ values }: { values: number[] }) {
  const min = Math.min(...values), max = Math.max(...values);
  const points = values
    .map((v, i) => `${(i / (values.length - 1)) * 240},${60 - ((v - min) / (max - min)) * 56}`)
    .join(" ");
  return (
    <svg viewBox="0 0 240 64" role="img" aria-label="Revenue up 119% over 24 months">
      <polyline points={points} fill="none" stroke="currentColor" vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

Accessibility for free

Click Start here, then press Tab and Enter.

Hand-rolled divBad
Shipping options
Focus: – Exposed: generic, no state
Native detailsGood
Shipping options

Standard, express, or pickup.

Focus: – Exposed: button, collapsed
<details>
  <summary>Shipping options</summary>
  <p>Standard, express, or pickup.</p>
</details>

details.addEventListener("toggle", () => track(details.open));

Why it matters, pros and cons

Why it matters

The browser already does static figures and disclosure; a library adds bytes.

Pros

  • Zero JS to download or hydrate.
  • Works when the bundle fails or lags.
  • Keyboard and screen reader support built in.

Cons

  • Tooltips, zoom or drill-down need a client chart.
  • Animating <details> height lacks full browser support.
  • Tabs and comboboxes have no native element.