How to Add a Size Chart to Shopify: Product-Specific Charts Without a Separate App

Last updated
•
Expert reviewed
•
5 min read
Jacques Blom
Jacques Blom
CTO at Fudge.

Key takeaways

  • Dawn can show a size chart with no app. Its Pop-up block opens any store page in a dialog, so one page plus one block covers a store-wide chart.1
  • Different charts per product need a metafield. Shopify’s own tutorial uses a product metafield of type Page, connected to the Pop-up block as a dynamic source.2
  • Metaobjects pay off once you have many charts. They hold measurements as structured data you can render as a table, switch between inches and cm, and translate.
  • Publish the chart as an HTML table, not only as an image. Screen readers and translation tools cannot read measurements inside a picture.

A Shopify size chart does not need a dedicated app: a page, a metafield and a block that ships with Dawn are enough for most apparel, footwear and jewellery stores. This guide shows how to add a size chart in Shopify three native ways, then covers what the basic tutorials skip: different charts for different products, accessible table markup, mobile layout and an inches/cm switch.

Whether you call it a size chart or a Shopify size guide, the setup is the same.

Why you can trust us

We have been in the Shopify space for over four years and have worked with hundreds of Shopify brands on their storefronts. Jacques has over 15 years of development experience. We build Fudge, an AI storefront editor with a 4.9 rating on the Shopify App Store and Built for Shopify status, and product page elements like a size guide are the kind of theme code it writes.


What are the ways to add a size chart in Shopify?

There are four native routes and one app route. Pick by how many different charts you need.

MethodPer-product charts?Structured data?EffortBest for
Page + Pop-up blockNo, one chart per templateNo, page contentLowest, no codeStores with one product category
Alternate product templatesOne chart per templateNoLow, no code2-4 chart types
Page metafield + dynamic sourceYesNo, each chart is a pageLow, no code in DawnSeveral charts on a Dawn-family theme
Metaobject + LiquidYesYesMedium, one Liquid snippetMany charts, unit switching, translation
Size chart appYesVaries by appLow setup, depends on the appFit quizzes, vendor-supplied chart feeds

The steps below use Dawn. Other themes name the block differently: Horizon’s Popup link block (blocks/popup-link.liquid) is filled with nested blocks instead of a page and can open as a drawer.

Method 1: One Shopify size chart for the whole store

  1. Go to Online Store → Pages → Add page. Title it “Size chart”, build the table with the Insert table button in the editor, set Visibility to Visible and save.
  2. Go to Online Store → Themes → Edit theme, then open your product template from the template dropdown.
  3. In Product information, click Add block and choose Pop-up.
  4. Set Link label to “Size chart”, pick your page in the Page setting, and save.

Those are the block’s only two settings.1 The link opens a dialog showing the page title and content. Drag the block directly under Variant picker so it sits with the size options.

Method 2: How do you show a different size chart per product?

Shopify’s documented answer is a product metafield of type Page, connected to the Pop-up block as a dynamic source.2 The block’s page setting accepts exactly that metafield type.3

  1. Go to Settings → Metafields and metaobjects → Products → Add definition. Name it “Size chart”, click Select type, choose Page, and save. Storefront access is on by default.
  2. Create one page per chart: tops, bottoms, shoes, ring sizes.
  3. In the theme editor, select the Pop-up block, click the dynamic source icon next to Page, and select your Size chart metafield.
  4. On each product, open Product metafields, click Size chart, and select the right page. A product can link to one page.

New to metafields? See how to add metafields to Shopify products.

Shopify’s tutorial puts the block on a separate product template, assigned only to products with a chart. The Dawn source shows why: the Pop-up button is rendered without checking whether a page is set, so a product with an empty metafield still gets the link, opening an empty dialog.1

To keep one template instead, duplicate your theme first, then wrap the existing opener markup in sections/main-product.liquid in a blank check:

{%- when 'popup' -%}
  {%- if block.settings.page != blank -%}
    <modal-opener ...>
      ...
    </modal-opener>
  {%- endif -%}

Alternate templates for 2-4 chart types

With only a few categories, skip the metafield. Create one product template per category, each with a Pop-up block pointing at a fixed page, then assign it under Theme template on the product or through the bulk editor’s Template column. A theme can hold 1,000 templates in total.4 See adding a custom template in Shopify for the steps.

Shopify’s category metafields are a different thing: they describe product attributes such as clothing size, not a table of measurements.

Method 3: Structured size charts with metaobjects

A page stores a chart as formatted text. A metaobject stores it as data with named fields, which makes unit switching, consistent markup and translation practical.

It is worth the extra setup when you have many charts or reuse them across markets. A definition can have up to 40 fields and 1,000,000 entries.5

Set up the definition and the reference

  1. Go to Content → Metaobjects → Add definition and name it “Size chart”.
  2. Add fields: Title (single line text), Measurements (JSON) and Fit notes (multi-line text). Leave Storefronts selected, and turn on Translations if you sell in more than one language.
  3. Add one entry per chart and keep it Active. A draft entry returns nothing in Liquid.5
  4. Go to Settings → Metafields and metaobjects → Products → Add definition, choose the Metaobject type, pick your Size chart definition, and save.
  5. On each product, select the entry in the Metafields section.

Store both units in the Measurements field:

{
    "columns": ["Size", "Chest", "Waist"],
    "rows": [
        {"size": "S", "inches": ["34-36", "28-30"], "cm": ["86-91", "71-76"]},
        {"size": "M", "inches": ["38-40", "32-34"], "cm": ["97-102", "81-86"]}
    ]
}

Render it as a table

Dawn has no block that turns a metaobject into a table, so this route needs Liquid. Duplicate your theme first, then add a Custom Liquid block under the Variant picker and paste:

{%- assign chart = product.metafields.custom.size_chart.value -%}
{%- if chart != blank -%}
  {%- assign data = chart.measurements.value -%}
  <details class="size-chart" data-unit="in">
    <summary>Size guide</summary>
    <div class="size-chart__scroll" role="region" aria-labelledby="SizeChartCaption" tabindex="0">
      <table>
        <caption id="SizeChartCaption">{{ chart.title.value | escape }}</caption>
        <thead>
          <tr>
            {%- for column in data.columns -%}
              <th scope="col">{{ column | escape }}</th>
            {%- endfor -%}
          </tr>
        </thead>
        <tbody>
          {%- for row in data.rows -%}
            <tr>
              <th scope="row">{{ row.size | escape }}</th>
              {%- for inches in row.inches -%}
                <td>
                  <span class="u-in">{{ inches | escape }} in</span>
                  <span class="u-cm">{{ row.cm[forloop.index0] | escape }} cm</span>
                </td>
              {%- endfor -%}
            </tr>
          {%- endfor -%}
        </tbody>
      </table>
    </div>
    {%- if chart.fit_notes.value != blank -%}
      <p>{{ chart.fit_notes.value | escape | newline_to_br }}</p>
    {%- endif -%}
  </details>
{%- endif -%}

Adjust custom.size_chart to your metafield’s namespace and key. The details element is a disclosure that works without JavaScript; a drawer or modal takes more code. The Custom Liquid setting accepts HTML and Liquid up to 50kb, so the CSS and script further down can live in the same block.

The Fudge route. Fudge reads the metaobject and writes the display layer. Tell Fudge:

“Add a ‘Size guide’ link next to the size selector on product pages that opens a drawer. Show the size chart from the product’s size chart metaobject as an accessible table, with an inches/cm toggle that remembers the choice.”

You get native theme code as a draft to review before publishing. The measurements still come from you and stay in metaobjects in the Shopify admin; AI and Shopify metafields explains that split.

How do you assign size charts at scale?

The bulk editor. Select products in the Products list, open the bulk editor, click Columns and add your metafield from the Metafields section. Shopify’s page does not list which metafield types the grid can edit, so try your size chart column on a few products first.6

CSV import. The product CSV accepts metafield columns for a fixed list of types. list.metaobject_reference is on it; the Page type and the single metaobject reference are not.6 To assign charts by spreadsheet, define the metafield as a list of values and read the first entry in Liquid.

By product type in Liquid. If your product types are consistent, skip per-product assignment. Name each entry so its handle matches a product type, then replace the first line of the Method 3 snippet with:

{%- assign chart = product.metafields.custom.size_chart.value -%}
{%- if chart == blank -%}
  {%- assign type_handle = product.type | handleize -%}
  {%- assign chart = metaobjects.size_chart[type_handle] -%}
{%- endif -%}

Here size_chart is the metaobject definition’s type. A product of type “Tops” picks up the entry with the handle tops, and a per-product metafield still wins. The same pattern works with pages through pages[handle], or with a tag check such as product.tags contains 'chart-tops'.

The Fudge route. Describe the rule and Fudge writes the Liquid for it. Tell Fudge:

“Use a different size chart for tops, bottoms and shoes based on product type, and hide the size guide link on products that have no chart.”

Fudge writes the rule into your theme as a draft. You still create the three charts in the admin.

Got the measurements but not the drawer, table and toggle? Describe it to Fudge.
Try Fudge for Free

What makes a Shopify size chart accessible?

Use a real HTML table. A screen reader or translation app cannot read numbers inside a picture, so an image-only chart fails WCAG 1.1.1 Non-text Content unless the same information is repeated as text.7

The relationships between sizes and measurements also have to be in the markup, which is WCAG 1.3.1 Info and Relationships.7 In practice:

<div class="size-chart__scroll" role="region" aria-labelledby="chart-caption" tabindex="0">
    <table>
        <caption id="chart-caption">
            Women's tops - body measurements
        </caption>
        <thead>
            <tr>
                <th scope="col">Size</th>
                <th scope="col">Chest</th>
                <th scope="col">Waist</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th scope="row">S</th>
                <td>34-36 in</td>
                <td>28-30 in</td>
            </tr>
        </tbody>
    </table>
</div>

Shopify’s help page for the editor’s table tool covers rows and columns, not captions or header cells. Click Show HTML in the page editor to check the markup and adjust it by hand.

The pop-up has rules too. A dialog should trap focus, close on Escape and return focus to the link that opened it. Dawn’s Pop-up block does all three: its source sets role="dialog" and aria-modal="true", loops Tab inside the dialog, closes on Escape or a backdrop click, and hands focus back to the opener.8 One wrinkle: it renders the page title as a second h1 on the product page.

Our WCAG 2.2 AA checklist for Shopify covers the rest of the product page.

How should a size chart work on mobile?

A six-column chart will not fit a phone screen, and that is acceptable: WCAG 1.4.10 Reflow exempts data tables, because rows and columns only make sense in two dimensions.

Scroll horizontally, with a cue. Dawn already does this inside its pop-up: below 750px its stylesheet sets tables to overflow-x: auto.1 Let the last visible column appear cut off, or add a “Scroll for more sizes” line, so shoppers know there is more.

Pin the first column. Once the size labels scroll away, the numbers lose their meaning. Sticky row headers fix that, and are easier to compare across than a stacked one-card-per-size layout:

.size-chart__scroll {
    overflow-x: auto;
}
.size-chart__scroll th[scope='row'] {
    position: sticky;
    left: 0;
    background: #fff;
}

Mind tap targets. WCAG 2.5.8 sets a 24 by 24 CSS pixel minimum. Dawn gives its pop-up link a min-height of 4.4rem; give the unit buttons similar room.

Drawer or modal? On phones a bottom drawer keeps the product visible behind it; a centred modal gives a wide table more room on desktop. Both need the same keyboard behaviour.

The Fudge route. Fudge makes the layout change in your theme’s CSS and markup. Tell Fudge:

“On mobile, make the size chart table scroll horizontally with the first column pinned.”

The change arrives as a draft you can preview on a phone before publishing.

How do you add an inches/cm toggle?

Store both units instead of converting on the fly. A converted value such as 87.63 cm has to be rounded, and rounded conversions will not always match your manufacturer’s metric spec. That is why the Measurements field above carries inches and cm.

The Liquid in Method 3 already prints both values in each cell. Add two buttons inside the size-chart element, above the table:

<div role="group" aria-label="Measurement units">
    <button type="button" data-set-unit="in" aria-pressed="true">Inches</button>
    <button type="button" data-set-unit="cm" aria-pressed="false">Centimetres</button>
</div>
.size-chart[data-unit='in'] .u-cm,
.size-chart[data-unit='cm'] .u-in {
    display: none;
}
document.querySelectorAll('.size-chart').forEach(function (chart) {
    var buttons = chart.querySelectorAll('[data-set-unit]')

    function setUnit(unit) {
        chart.dataset.unit = unit
        buttons.forEach(function (button) {
            button.setAttribute('aria-pressed', String(button.dataset.setUnit === unit))
        })
        try {
            localStorage.setItem('sizeChartUnit', unit)
        } catch (e) {}
    }

    var saved = null
    try {
        saved = localStorage.getItem('sizeChartUnit')
    } catch (e) {}
    if (saved === 'in' || saved === 'cm') setUnit(saved)

    buttons.forEach(function (button) {
        button.addEventListener('click', function () {
            setUnit(button.dataset.setUnit)
        })
    })
})

aria-pressed tells assistive technology which unit is active, and the labels stay the same in both states, as the W3C toggle button pattern requires. The choice is saved in localStorage, so it carries to the next product.

International sizes are a related need. US, UK and EU sizes are labels, not conversions, so add them as extra columns from your manufacturer’s spec.

Put the link next to the size selector, because that is where the question comes up. For the wider layout, see how to customize a Shopify product page.

A table of numbers is only part of a useful guide. Add:

Fashion stores will find more layout ideas in Shopify store design for fashion.

When is a size chart app the right call?

Native methods cover displaying a chart. An app earns its place when you need something beyond display:

Check the live App Store listing for current pricing. For display alone, a native table in your theme, written by hand or with the Shopify store editor, is enough.

FAQ

Does Shopify have a built-in size chart feature?

Dawn has no dedicated size chart setting, but the pieces are native. Its product template includes a Pop-up block that opens a store page in a dialog, and Shopify's own tutorial pairs it with a product metafield of type Page to show a chart per product. No app is required for either.

How do I add different size charts for different products in Shopify?

Create a product metafield of type Page under Settings, Metafields and metaobjects, then connect it to the Pop-up block as a dynamic source and select the right page on each product. For two to four chart types, separate product templates are simpler. For many charts, use a metaobject and assign it by product type in Liquid.

Should a size chart be an image or a table?

A table. Screen readers and translation apps cannot read measurements inside an image, and an image-only chart fails WCAG 1.1.1 Non-text Content unless the same information is repeated as text. Use an HTML table with a caption and header cells marked with scope.

Why does the size chart link appear on products that have no chart?

In Dawn, the Pop-up block renders its link without checking whether a page is set, so an empty metafield still produces a link that opens an empty dialog. Either put the block on a separate product template, as Shopify's tutorial does, or wrap the block markup in a check that the page is not blank.

How do I show a size chart in both inches and cm?

Store both sets of measurements instead of converting in the browser, because rounded conversions may not match the metric spec from your manufacturer. Print both values in each table cell, hide one with CSS, and switch with two buttons that use aria-pressed. Save the choice in localStorage so it carries across products.

Where should the size chart go on a product page?

Next to the size selector, as a link that opens a pop-up or drawer. In Dawn you can drag the Pop-up block directly under the Variant picker block in the theme editor. Include how-to-measure instructions and fit notes inside the chart, and show model height and size worn near the images.

Can I bulk assign size charts to products?

Yes. The bulk editor can show metafield columns and a Template column, so you can set charts or templates for many products in one grid. The product CSV also accepts some metafield types, including lists of metaobject references. If your product types are consistent, a Liquid rule that maps product type to a chart avoids per-product assignment altogether.

Jacques's signature
Describe the size guide. Get theme code, not an app.

Footnotes

  1. Shopify, Dawn theme source, sections/main-product.liquid and assets/section-main-product.css - the popup block has two settings, a Link label text field and a page picker; the opener button is rendered with no check for an empty page; below 750px, tables inside the pop-up are set to display: block; overflow-x: auto; white-space: nowrap, and the pop-up link has a min-height of 4.4rem. https://github.com/Shopify/dawn/blob/main/sections/main-product.liquid and https://github.com/Shopify/dawn/blob/main/assets/section-main-product.css ↩ ↩2 ↩3 ↩4

  2. Shopify Help Center, “Adding a pop-up size chart to your product pages” - create a product metafield definition named Size chart with the Page type, add a Pop-up block to a product template, connect the block’s Page setting to the metafield with the dynamic source icon, and select a page on each product; “You can link only one page in the product metafield.” https://help.shopify.com/en/manual/custom-data/metafields/pop-up-tutorial ↩ ↩2

  3. Shopify.dev, dynamic sources reference - the page setting type accepts metafields of type page_reference, and metaobject fields can be connected to compatible settings. https://shopify.dev/docs/storefronts/themes/architecture/settings/dynamic-sources ↩

  4. Shopify Help Center, theme templates page - new templates are created from the template dropdown in the theme editor, assigned per product under Theme template or in the bulk editor’s Template column, and “you can have only 1,000 templates in total.” https://help.shopify.com/en/manual/online-store/themes/theme-structure/templates ↩

  5. Shopify.dev, metaobject limits reference - each definition can have up to 40 fields and up to 1,000,000 entries, with 128 merchant-created definitions per store (256 on Plus). The Liquid metaobject reference adds that an entry with draft status returns nil. https://shopify.dev/docs/apps/build/custom-data/metaobjects/metaobject-limits and https://shopify.dev/docs/api/liquid/objects/metaobject ↩ ↩2

  6. Shopify Help Center, bulk editing metafields page - “You can edit metafields in bulk for products, variants, collections, and customers” by adding them under Columns. The product CSV page lists the metafield types supported for import and export, which include list.metaobject_reference but not page_reference or a single metaobject_reference. https://help.shopify.com/en/manual/custom-data/metafields/bulk-edit-metafields and https://help.shopify.com/en/manual/products/import-export/using-csv ↩ ↩2

  7. W3C, Understanding WCAG 2.2 - SC 1.1.1 Non-text Content (Level A): “All non-text content that is presented to the user has a text alternative that serves the equivalent purpose”; SC 1.3.1 Info and Relationships (Level A), whose techniques include table markup, captions and the scope attribute. https://www.w3.org/WAI/WCAG22/Understanding/non-text-content.html and https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html ↩ ↩2

  8. Shopify, Dawn theme source, assets/global.js - the ModalDialog class closes on Escape and on a click on the backdrop, calls trapFocus when opened, and calls removeTrapFocus(this.openedBy) on close, which returns focus to the button that opened it. https://github.com/Shopify/dawn/blob/main/assets/global.js ↩

You might also be interested in

How to Build a Shopify Quiz Landing Page (Step-by-Step)
A Shopify quiz landing page hosts the quiz and nothing else. Build the page and template, strip the header, speed it up, and track the right events.
How to Design a Shopify Store for Pet Brands
Design a Shopify store for pet brands: shop-by-pet navigation, subscribe-and-save placement, matching quizzes, and starter packs for repeat orders.
Mobile-First Shopify Landing Page Patterns That Convert
Mobile Shopify landing page patterns that convert: single-column layout, sticky CTA, thumb-friendly targets, fast hero, and message match with your ad.