Size Guide Modal — Size Chart HTML CSS JS

Size Guide Modal · Modals · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Inches / centimetres toggle
All values stored in inches and derived to cm on toggle, so the chart can never show inconsistent units.
Measurement-to-size finder
Enter a chest measurement and the recommended size highlights with a clear "You're a M" result.
Unit-aware finder conversion
Switching units converts the entered measurement too, keeping the recommendation accurate across the toggle.
Data-driven table
Rows and columns come from SIZES and COLS arrays — adapt the chart to any garment with a data edit.
"Size up to fit" logic
bestSize() picks the smallest size at or above the entered measurement, the standard body-measurement rule.
Derived highlight, never stale
The matching-row highlight is recomputed from the live input and unit, so it never drifts from the displayed numbers.
Accessible, animation-safe modal
role="dialog" with aria-modal, Escape/backdrop/close dismissal, and opacity/transform-only transitions.
Scrolls on any screen
Horizontal table scroll plus a max-height modal body keep even a long chart usable on mobile.

About this UI Snippet

Size Guide Modal — Size Chart with Unit Toggle & Measurement Finder

Screenshot of the Size Guide Modal snippet rendered live

Sizing uncertainty is one of the biggest causes of apparel cart abandonment and returns — shoppers either guess and hope, or leave to measure something and never come back. A good size-guide modal answers "which size am I?" right there on the product page, without a page load. This snippet builds the complete pattern in plain HTML, CSS, and vanilla JavaScript: a measurements table, an inches/centimetres toggle that re-renders every value, and a measurement finder that highlights the recommended size as the shopper types.

One unit toggle, every value converts

All measurements are stored once in inches, and the centimetre values are derived on the fly (× 2.54, rounded) when the user flips the units toggle. This single-source-of-truth approach means the table can never show inconsistent in/cm values, and adding a size is one data row, not two columns of hand-converted numbers. The column headers update their unit suffix too ("Chest (in)" → "Chest (cm)"), and crucially, if the shopper has already typed a measurement into the finder, that value is converted as well so their recommendation stays correct across the switch.

A finder that turns a measurement into a size

The real anxiety-killer is the chest-measurement finder. The shopper enters one number — their chest measurement in the current unit — and bestSize() walks the size table to find the smallest size whose chest measurement is at or above their input, the standard "size up to fit" rule for body measurements. The matching table row highlights in indigo and a "→ You're a M" result appears instantly. This converts the abstract table into a direct, personal answer, which is exactly what reduces both hesitation and wrong-size returns.

The table is data, the highlight is derived

The whole table renders from a SIZES array and a COLS list, so changing the garment's measurements, adding a chest/waist/hip column, or supporting more sizes is a data edit. The finder's highlight isn't stored state — it's recomputed from the current input and unit every time either changes, so it can never get out of sync with the displayed numbers. Clearing the input clears the highlight and result cleanly.

Modal mechanics done right

The guide opens from a subtle "Size guide" link beside the size selector (where shoppers actually look for it), as a role="dialog" modal with aria-modal="true". It closes via the ✕, a backdrop click, or the Escape key — all through one close() function — and animates in with opacity and transform only, staying smooth across every framework export. The table scrolls horizontally inside its wrapper and the modal body scrolls vertically (max-height: 90vh), so even a long size chart fits any screen.

Adapting it to your products

Different garment types need different columns — a shirt uses chest/waist, trousers use waist/inseam/hip, shoes use length. Because the columns and rows are both data-driven, you adapt the guide per product category by swapping the SIZES and COLS definitions, and the finder can key off whichever measurement is most diagnostic for that category. The FAQs cover per-product charts and international size mappings (US/UK/EU).

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to trace the unit-conversion and size-matching logic by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why measurements are stored only in inches with centimetres derived on the fly, or how bestSize walks the SIZES array to implement the "size up to fit" rule. The same assistant can help you optimize it, for example checking whether render() is doing unnecessary DOM rebuilding on every unit toggle versus only updating the cells that changed. It is just as useful for extending the modal: ask it to add waist- or hip-based finder logic for garments where chest isn't the diagnostic measurement, support a second measurement system like US/UK/EU labels, or remember the shopper's last unit choice across visits. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a size-guide modal for an apparel product page in plain HTML, CSS, and JavaScript — no framework, no dependencies.

Requirements:
- A modal dialog with role="dialog" and aria-modal="true", opened by a "Size guide" link and closable via a close button, a backdrop click, and the Escape key, all routed through one shared close function. Animate the open/close purely with opacity and transform so it stays smooth across any framework port.
- A size table rendered entirely from a data array of size objects (each with a size label and measurements) and a separate column-definition array — no hardcoded table rows in the HTML.
- A unit toggle between inches and centimetres. Store every measurement once, in inches, and derive centimetre values on the fly with a single conversion function (multiply by 2.54 and round) rather than maintaining separate inch and centimetre data — the table, including the column header unit suffixes, must fully re-render from that one conversion function when the toggle changes.
- A "chest measurement finder": a number input where, on every keystroke, a function walks the size array in order and returns the first (smallest) size whose chest measurement is at or above the entered value — the standard size-up-to-fit rule — then highlights that matching row in the table and shows a "You're a [size]" result text.
- When the user switches units after already typing a measurement, convert the entered value in place (inches to cm or back) so the highlighted recommendation stays correct instead of becoming wrong or resetting.
- The matching-row highlight must never be stored as separate state — it must be recomputed from the current input value and current unit every time either one changes, so it cannot drift out of sync with the displayed numbers.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA product row with a "Size guide" link renders. Click the link to open the size-chart modal.
  2. 2
    Toggle unitsSwitch between Inches and CM — every measurement in the table re-renders, and the column headers update their unit.
  3. 3
    Use the size finderEnter your chest measurement in the box — the matching size row highlights and a "You're a M" result appears instantly.
  4. 4
    Switch units with a value enteredFlip the unit toggle after typing — your entered measurement converts too, so the recommendation stays correct.
  5. 5
    Close the modalClick ✕, the backdrop, or press Escape to dismiss the guide.
  6. 6
    Adapt to your productsEdit the SIZES and COLS arrays to match your garment's real measurements and the columns that matter for it.

Real-world uses

Common Use Cases

Apparel product pages
The standard "Size guide" link beside the size selector — pair with a product quick view and a variant selector.
Footwear and accessories
Swap the columns for length/width or band sizes; the finder keys off whichever measurement is most diagnostic.
Made-to-order and custom fitting
Show a measurement chart and capture the customer's numbers to recommend a base size before customization.
International storefronts
Add US/UK/EU columns so shoppers map their home sizing — pair with a language switcher for localized stores.
Return-reduction initiatives
Surface the finder prominently to cut wrong-size orders, the leading cause of apparel returns.
Learning data-driven table + modal
A reference for unit conversion, derived highlighting, and modal mechanics in one component.

Got questions?

Frequently Asked Questions

Because the table is built from the SIZES and COLS arrays, give each product (or category) its own measurement data and pass it into the component when opening the modal. A t-shirt uses chest/waist, trousers use waist/inseam/hip, shoes use length — swap the arrays and the table, headers, and finder all adapt with no other changes.

bestSize() walks the sizes from smallest up and returns the first whose chest measurement is at or above the entered value — the standard "size up to fit" rule, since a garment must be at least as large as the body measurement. For ease-of-fit you can add a small allowance, or pick the nearest size rather than rounding up, depending on the garment's intended fit.

Add the international labels as extra columns in COLS and corresponding fields in each SIZES entry, rendering them like the measurement columns. Since they're just labels (not measurements), they don't need unit conversion — they display as-is regardless of the in/cm toggle.

A single source of truth prevents the classic bug where the inch and cm columns drift out of sync after an edit. Storing one unit and deriving the other (× 2.54) guarantees consistency and halves the data you maintain — you change one number and both unit views update together.

In React, hold the unit and the finder input in useState and derive the table values and recommended size with useMemo; in Vue, use ref()/computed(); in Angular, use component fields with getters or pipes. The conversion and bestSize logic are plain functions that port unchanged, and the modal open/close maps to each framework's event handlers.