All posts

Tutorial

How to add a size chart to a Shopify product page (with metafields)

Add a per-product size chart to your Shopify product page the right way: a metafield the merchant fills in per product, rendered in a collapsible details element. Covers the metafield setup, the Liquid, and why this beats hardcoding a table. No app required.

Bas Lefeber

Founder, learnshopify.dev · June 12, 2026 · 3 min read

A size chart is the difference between a confident purchase and a return. The wrong way to add one is to hardcode a table into the theme, because every product needs different sizes and the merchant cannot edit code. The right way is a metafield: the merchant fills in a size chart per product in the admin, and the theme renders whatever they entered. No app, fully merchant-controlled.

This guide covers the one-time metafield setup, the Liquid to render it in a tidy collapsible panel, and why this pattern is the professional default for any "extra field on a product".

A Shopify product page with an expanded Size chart panel showing a table of sizes and measurements
The size chart is a per-product metafield, rendered in a collapsible panel.

Step 1: define the metafield (one-time)

In your Shopify admin, go to Settings → Custom data → Products and add a definition:

  • Namespace and key: custom.size_chart.
  • Type: Rich text (so the merchant can paste a formatted table), or Metaobject reference if you want one reusable chart shared across many products.
  • Save. Now every product has a Size chart field in its admin page.

Rich text vs a shared metaobject

Rich text is the fastest start: the merchant pastes a table per product. If many products share the same chart (all your t-shirts, say), a metaobject lets them edit one chart that updates everywhere. Start with rich text; graduate to a metaobject when duplication becomes a chore.

Step 2: render it

Create snippets/size-chart.liquid and render it near your variant picker. The whole snippet is a guarded read of the metafield inside a native <details> element, so it is collapsible with zero JavaScript:

snippets/size-chart.liquid
{% assign size_chart = product.metafields.custom.size_chart %} {% if size_chart != blank %}  <details class="size-chart">    <summary class="size-chart__toggle">Size chart</summary>    <div class="size-chart__content">      {{ size_chart }}    </div>  </details>{% endif %}
  • product.metafields.custom.size_chart reads the field you defined. The metafield object returns the rich-text content ready to output.
  • {% if size_chart != blank %} is the part most snippets forget: products without a chart render nothing at all, instead of an empty "Size chart" panel.
  • <details>/<summary> gives you an accessible, keyboard-friendly collapsible with no JavaScript. MDN documents the details element and browsers handle the open/close for free.

Output rich text directly, don't escape it

A rich-text metafield already returns safe HTML, so {{ size_chart }} renders the table correctly. Do not run it through escape or strip_html, that would print the raw tags or flatten the table. (For plain-text metafields the rules differ; rich text is the case here.)

Light styling

assets/size-chart.css
.size-chart { border-top: 1px solid rgba(0, 0, 0, 0.08); padding: 0.75rem 0; }.size-chart__toggle {  cursor: pointer;  font-weight: 600;  list-style: none;  display: flex;  justify-content: space-between;  align-items: center;}.size-chart__toggle::after { content: "+"; opacity: 0.5; }.size-chart[open] .size-chart__toggle::after { content: "–"; }.size-chart__content { padding-top: 0.75rem; }.size-chart__content table { width: 100%; border-collapse: collapse; }.size-chart__content th,.size-chart__content td { border: 1px solid rgba(0, 0, 0, 0.1); padding: 0.5rem 0.75rem; text-align: left; font-size: 0.9rem; }

Why this is the professional pattern

Reading product.metafields.custom.size_chart instead of hardcoding a table is the same principle behind almost every "custom field on a product" in Shopify: structured data belongs in a metafield the merchant owns, not baked into the theme or parsed out of the product description. It is covered in depth in displaying product metafields, and it is exactly the judgment that separates a maintainable store from one that needs a developer for every copy change.

Learn this properly · free lesson

Read your metafield: roast date on the PDP

Read and render a product metafield step by step in our interactive editor, against a live store, with a reviewer checking your work. It is the building block behind size charts, ingredient lists, care instructions, and more.

Try this lesson — free

Wrapping up

One metafield definition, one guarded read, and a native <details> panel. The merchant controls the content per product, the theme stays clean, and you never touch code when a size changes. That is a size chart built the way a professional Shopify developer would ship it.

Frequently asked questions

How do I add a size chart to a Shopify product page?

Define a product metafield (for example custom.size_chart as rich text) in Settings → Custom data, fill it in per product, then render it in a snippet with {{ product.metafields.custom.size_chart }} inside a collapsible details element. No app is required.

Should the size chart be a metafield or hardcoded in the theme?

A metafield. Different products need different size charts and the merchant should be able to edit them without touching code. Hardcoding a table forces a developer change for every update and cannot vary per product.

How do I show one shared size chart across many products?

Use a metaobject instead of a rich-text metafield. Create a size-chart metaobject, then reference it from a product metafield. Editing the metaobject updates every product that references it, which avoids duplicating the same chart.

How do I make the size chart collapsible without JavaScript?

Wrap it in a native <details> element with a <summary> toggle. Browsers handle the open and close behavior and keyboard accessibility for free, so you need no JavaScript at all.

On the launch list

Get updates on the platform.

Same waitlist as the homepage. New posts plus a heads-up when v1 launches. No drip, no spam.

One email when a new module ships, one when v1 launches. No drip sequence, no spam. Unsubscribe anytime.

LiquidMetafieldsProduct page

Keep going in the curriculum