More Modals Snippets
Size Guide Modal — Size Chart HTML CSS JS
Size Guide Modal · Modals · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Size Guide Modal — Size Chart with Unit Toggle & Measurement Finder

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:
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
- 1Paste HTML, CSS, and JSA product row with a "Size guide" link renders. Click the link to open the size-chart modal.
- 2Toggle unitsSwitch between Inches and CM — every measurement in the table re-renders, and the column headers update their unit.
- 3Use the size finderEnter your chest measurement in the box — the matching size row highlights and a "You're a M" result appears instantly.
- 4Switch units with a value enteredFlip the unit toggle after typing — your entered measurement converts too, so the recommendation stays correct.
- 5Close the modalClick ✕, the backdrop, or press Escape to dismiss the guide.
- 6Adapt 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
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.