JAVASCRIPTshopifybeginner

Shopify Size Chart Modal

Add a size chart popup to help customers choose the right size

#shopify#size-chart#modal#apparel#ux
Share this snippet:

Code

javascript
1// Size Chart Modal Class
2class SizeChartModal {
3 constructor(options = {}) {
4 this.trigger = options.trigger || '[data-size-chart-trigger]';
5 this.modalId = options.modalId || 'size-chart-modal';
6 this.modal = null;
7
8 this.init();
9 }
10
11 init() {
12 // Create modal
13 this.createModal();
14
15 // Bind trigger buttons
16 document.addEventListener('click', (e) => {
17 if (e.target.matches(this.trigger) || e.target.closest(this.trigger)) {
18 e.preventDefault();
19 this.open();
20 }
21 });
22 }
23
24 createModal() {
25 this.modal = document.createElement('div');
26 this.modal.id = this.modalId;
27 this.modal.className = 'size-chart-modal';
28
29 this.modal.innerHTML = `
30 <div class="size-chart-overlay" data-close-modal></div>
31 <div class="size-chart-content">
32 <button class="size-chart-close" data-close-modal aria-label="Close">×</button>
33
34 <div class="size-chart-header">
35 <h2>Size Chart</h2>
36 <p>Find your perfect fit</p>
37 </div>
38
39 <div class="size-chart-body">
40 <!-- Size tabs -->
41 <div class="size-tabs">
42 <button class="size-tab active" data-tab="women">Women's</button>
43 <button class="size-tab" data-tab="men">Men's</button>
44 <button class="size-tab" data-tab="kids">Kids</button>
45 </div>
46
47 <!-- Women's Size Chart -->
48 <div class="size-table-wrapper active" data-content="women">
49 <div class="size-table-scroll">
50 <table class="size-table">
51 <thead>
52 <tr>
53 <th>Size</th>
54 <th>US</th>
55 <th>Bust (in)</th>
56 <th>Waist (in)</th>
57 <th>Hips (in)</th>
58 </tr>
59 </thead>
60 <tbody>
61 <tr>
62 <td>XS</td>
63 <td>0-2</td>
64 <td>32-33</td>
65 <td>24-25</td>
66 <td>34-35</td>
67 </tr>
68 <tr>
69 <td>S</td>
70 <td>4-6</td>
71 <td>34-35</td>
72 <td>26-27</td>
73 <td>36-37</td>
74 </tr>
75 <tr>
76 <td>M</td>
77 <td>8-10</td>
78 <td>36-37</td>
79 <td>28-29</td>
80 <td>38-39</td>
81 </tr>
82 <tr>
83 <td>L</td>
84 <td>12-14</td>
85 <td>38-40</td>
86 <td>30-32</td>
87 <td>40-42</td>
88 </tr>
89 <tr>
90 <td>XL</td>
91 <td>16-18</td>
92 <td>42-44</td>
93 <td>34-36</td>
94 <td>44-46</td>
95 </tr>
96 </tbody>
97 </table>
98 </div>
99 </div>
100
101 <!-- Men's Size Chart -->
102 <div class="size-table-wrapper" data-content="men">
103 <div class="size-table-scroll">
104 <table class="size-table">
105 <thead>
106 <tr>
107 <th>Size</th>
108 <th>Chest (in)</th>
109 <th>Waist (in)</th>
110 <th>Sleeve (in)</th>
111 </tr>
112 </thead>
113 <tbody>
114 <tr>
115 <td>S</td>
116 <td>34-36</td>
117 <td>28-30</td>
118 <td>32-33</td>
119 </tr>
120 <tr>
121 <td>M</td>
122 <td>38-40</td>
123 <td>32-34</td>
124 <td>33-34</td>
125 </tr>
126 <tr>
127 <td>L</td>
128 <td>42-44</td>
129 <td>36-38</td>
130 <td>34-35</td>
131 </tr>
132 <tr>
133 <td>XL</td>
134 <td>46-48</td>
135 <td>40-42</td>
136 <td>35-36</td>
137 </tr>
138 <tr>
139 <td>XXL</td>
140 <td>50-52</td>
141 <td>44-46</td>
142 <td>36-37</td>
143 </tr>
144 </tbody>
145 </table>
146 </div>
147 </div>
148
149 <!-- Kids Size Chart -->
150 <div class="size-table-wrapper" data-content="kids">
151 <div class="size-table-scroll">
152 <table class="size-table">
153 <thead>
154 <tr>
155 <th>Size</th>
156 <th>Age</th>
157 <th>Height (in)</th>
158 <th>Weight (lbs)</th>
159 </tr>
160 </thead>
161 <tbody>
162 <tr>
163 <td>XS</td>
164 <td>4-5</td>
165 <td>41-44</td>
166 <td>34-41</td>
167 </tr>
168 <tr>
169 <td>S</td>
170 <td>6-7</td>
171 <td>45-49</td>
172 <td>42-52</td>
173 </tr>
174 <tr>
175 <td>M</td>
176 <td>8-10</td>
177 <td>50-54</td>
178 <td>53-70</td>
179 </tr>
180 <tr>
181 <td>L</td>
182 <td>12-14</td>
183 <td>55-61</td>
184 <td>71-100</td>
185 </tr>
186 </tbody>
187 </table>
188 </div>
189 </div>
190
191 <!-- Measurement Guide -->
192 <div class="measurement-guide">
193 <h3>How to Measure</h3>
194 <div class="measurement-tips">
195 <div class="measurement-tip">
196 <strong>Bust/Chest:</strong> Measure around the fullest part
197 </div>
198 <div class="measurement-tip">
199 <strong>Waist:</strong> Measure around the narrowest part
200 </div>
201 <div class="measurement-tip">
202 <strong>Hips:</strong> Measure around the fullest part
203 </div>
204 </div>
205 </div>
206 </div>
207 </div>
208 `;
209
210 document.body.appendChild(this.modal);
211
212 // Bind close events
213 this.modal.querySelectorAll('[data-close-modal]').forEach(el => {
214 el.addEventListener('click', () => this.close());
215 });
216
217 // Tab switching
218 this.initTabs();
219 }
220
221 initTabs() {
222 const tabs = this.modal.querySelectorAll('.size-tab');
223 const contents = this.modal.querySelectorAll('.size-table-wrapper');
224
225 tabs.forEach(tab => {
226 tab.addEventListener('click', () => {
227 const target = tab.dataset.tab;
228
229 // Update active tab
230 tabs.forEach(t => t.classList.remove('active'));
231 tab.classList.add('active');
232
233 // Update visible content
234 contents.forEach(content => {
235 if (content.dataset.content === target) {
236 content.classList.add('active');
237 } else {
238 content.classList.remove('active');
239 }
240 });
241 });
242 });
243 }
244
245 open() {
246 this.modal.classList.add('is-active');
247 document.body.style.overflow = 'hidden';
248
249 // Trigger analytics event
250 if (typeof window.dataLayer !== 'undefined') {
251 window.dataLayer.push({
252 'event': 'size_chart_opened'
253 });
254 }
255 }
256
257 close() {
258 this.modal.classList.remove('is-active');
259 document.body.style.overflow = '';
260 }
261}
262
263// Initialize
264document.addEventListener('DOMContentLoaded', () => {
265 new SizeChartModal();
266});

Shopify Size Chart Modal

Create a professional size chart modal that helps customers select the correct size, reducing returns and improving customer satisfaction.

// Size Chart Modal Class
class SizeChartModal {
    constructor(options = {}) {
        this.trigger = options.trigger || '[data-size-chart-trigger]';
        this.modalId = options.modalId || 'size-chart-modal';
        this.modal = null;

        this.init();
    }

    init() {
        // Create modal
        this.createModal();

        // Bind trigger buttons
        document.addEventListener('click', (e) => {
            if (e.target.matches(this.trigger) || e.target.closest(this.trigger)) {
                e.preventDefault();
                this.open();
            }
        });
    }

    createModal() {
        this.modal = document.createElement('div');
        this.modal.id = this.modalId;
        this.modal.className = 'size-chart-modal';

        this.modal.innerHTML = `
            <div class="size-chart-overlay" data-close-modal></div>
            <div class="size-chart-content">
                <button class="size-chart-close" data-close-modal aria-label="Close">×</button>

                <div class="size-chart-header">
                    <h2>Size Chart</h2>
                    <p>Find your perfect fit</p>
                </div>

                <div class="size-chart-body">
                    <!-- Size tabs -->
                    <div class="size-tabs">
                        <button class="size-tab active" data-tab="women">Women's</button>
                        <button class="size-tab" data-tab="men">Men's</button>
                        <button class="size-tab" data-tab="kids">Kids</button>
                    </div>

                    <!-- Women's Size Chart -->
                    <div class="size-table-wrapper active" data-content="women">
                        <div class="size-table-scroll">
                            <table class="size-table">
                                <thead>
                                    <tr>
                                        <th>Size</th>
                                        <th>US</th>
                                        <th>Bust (in)</th>
                                        <th>Waist (in)</th>
                                        <th>Hips (in)</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>XS</td>
                                        <td>0-2</td>
                                        <td>32-33</td>
                                        <td>24-25</td>
                                        <td>34-35</td>
                                    </tr>
                                    <tr>
                                        <td>S</td>
                                        <td>4-6</td>
                                        <td>34-35</td>
                                        <td>26-27</td>
                                        <td>36-37</td>
                                    </tr>
                                    <tr>
                                        <td>M</td>
                                        <td>8-10</td>
                                        <td>36-37</td>
                                        <td>28-29</td>
                                        <td>38-39</td>
                                    </tr>
                                    <tr>
                                        <td>L</td>
                                        <td>12-14</td>
                                        <td>38-40</td>
                                        <td>30-32</td>
                                        <td>40-42</td>
                                    </tr>
                                    <tr>
                                        <td>XL</td>
                                        <td>16-18</td>
                                        <td>42-44</td>
                                        <td>34-36</td>
                                        <td>44-46</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>

                    <!-- Men's Size Chart -->
                    <div class="size-table-wrapper" data-content="men">
                        <div class="size-table-scroll">
                            <table class="size-table">
                                <thead>
                                    <tr>
                                        <th>Size</th>
                                        <th>Chest (in)</th>
                                        <th>Waist (in)</th>
                                        <th>Sleeve (in)</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>S</td>
                                        <td>34-36</td>
                                        <td>28-30</td>
                                        <td>32-33</td>
                                    </tr>
                                    <tr>
                                        <td>M</td>
                                        <td>38-40</td>
                                        <td>32-34</td>
                                        <td>33-34</td>
                                    </tr>
                                    <tr>
                                        <td>L</td>
                                        <td>42-44</td>
                                        <td>36-38</td>
                                        <td>34-35</td>
                                    </tr>
                                    <tr>
                                        <td>XL</td>
                                        <td>46-48</td>
                                        <td>40-42</td>
                                        <td>35-36</td>
                                    </tr>
                                    <tr>
                                        <td>XXL</td>
                                        <td>50-52</td>
                                        <td>44-46</td>
                                        <td>36-37</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>

                    <!-- Kids Size Chart -->
                    <div class="size-table-wrapper" data-content="kids">
                        <div class="size-table-scroll">
                            <table class="size-table">
                                <thead>
                                    <tr>
                                        <th>Size</th>
                                        <th>Age</th>
                                        <th>Height (in)</th>
                                        <th>Weight (lbs)</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td>XS</td>
                                        <td>4-5</td>
                                        <td>41-44</td>
                                        <td>34-41</td>
                                    </tr>
                                    <tr>
                                        <td>S</td>
                                        <td>6-7</td>
                                        <td>45-49</td>
                                        <td>42-52</td>
                                    </tr>
                                    <tr>
                                        <td>M</td>
                                        <td>8-10</td>
                                        <td>50-54</td>
                                        <td>53-70</td>
                                    </tr>
                                    <tr>
                                        <td>L</td>
                                        <td>12-14</td>
                                        <td>55-61</td>
                                        <td>71-100</td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>

                    <!-- Measurement Guide -->
                    <div class="measurement-guide">
                        <h3>How to Measure</h3>
                        <div class="measurement-tips">
                            <div class="measurement-tip">
                                <strong>Bust/Chest:</strong> Measure around the fullest part
                            </div>
                            <div class="measurement-tip">
                                <strong>Waist:</strong> Measure around the narrowest part
                            </div>
                            <div class="measurement-tip">
                                <strong>Hips:</strong> Measure around the fullest part
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        `;

        document.body.appendChild(this.modal);

        // Bind close events
        this.modal.querySelectorAll('[data-close-modal]').forEach(el => {
            el.addEventListener('click', () => this.close());
        });

        // Tab switching
        this.initTabs();
    }

    initTabs() {
        const tabs = this.modal.querySelectorAll('.size-tab');
        const contents = this.modal.querySelectorAll('.size-table-wrapper');

        tabs.forEach(tab => {
            tab.addEventListener('click', () => {
                const target = tab.dataset.tab;

                // Update active tab
                tabs.forEach(t => t.classList.remove('active'));
                tab.classList.add('active');

                // Update visible content
                contents.forEach(content => {
                    if (content.dataset.content === target) {
                        content.classList.add('active');
                    } else {
                        content.classList.remove('active');
                    }
                });
            });
        });
    }

    open() {
        this.modal.classList.add('is-active');
        document.body.style.overflow = 'hidden';

        // Trigger analytics event
        if (typeof window.dataLayer !== 'undefined') {
            window.dataLayer.push({
                'event': 'size_chart_opened'
            });
        }
    }

    close() {
        this.modal.classList.remove('is-active');
        document.body.style.overflow = '';
    }
}

// Initialize
document.addEventListener('DOMContentLoaded', () => {
    new SizeChartModal();
});

Liquid Template

<!-- Size Chart Trigger Link -->
<div class="product-size-selector">
    <label>Size:</label>

    <select name="Size" class="product-size-select">
        {% for option in product.options_with_values %}
            {% if option.name == 'Size' %}
                {% for value in option.values %}
                    <option value="{{ value }}">{{ value }}</option>
                {% endfor %}
            {% endif %}
        {% endfor %}
    </select>

    <a href="#" class="size-chart-link" data-size-chart-trigger>
        <svg width="16" height="16" viewBox="0 0 16 16">
            <path d="M0 0h6v6H0V0zm0 10h6v6H0v-6zM10 0h6v6h-6V0zm0 10h6v6h-6v-6z"/>
        </svg>
        Size Chart
    </a>
</div>

CSS Styling

/* Size Chart Link */
.size-chart-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: #0066cc;
    text-decoration: none;
    font-size: 14px;
    margin-left: 10px;
}

.size-chart-link:hover {
    text-decoration: underline;
}

/* Modal */
.size-chart-modal {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 9999;
    display: none;
}

.size-chart-modal.is-active {
    display: block;
}

.size-chart-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0,0,0,0.7);
    cursor: pointer;
}

.size-chart-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    border-radius: 8px;
    max-width: 800px;
    width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}

.size-chart-close {
    position: absolute;
    top: 15px;
    right: 15px;
    background: none;
    border: none;
    font-size: 30px;
    cursor: pointer;
    line-height: 1;
    z-index: 1;
}

.size-chart-header {
    padding: 30px 30px 20px;
    border-bottom: 1px solid #eee;
}

.size-chart-header h2 {
    margin: 0 0 5px;
    font-size: 24px;
}

.size-chart-header p {
    margin: 0;
    color: #666;
}

.size-chart-body {
    padding: 30px;
}

/* Tabs */
.size-tabs {
    display: flex;
    gap: 10px;
    margin-bottom: 25px;
    border-bottom: 2px solid #eee;
}

.size-tab {
    padding: 10px 20px;
    background: none;
    border: none;
    border-bottom: 2px solid transparent;
    cursor: pointer;
    font-size: 15px;
    font-weight: 500;
    color: #666;
    margin-bottom: -2px;
    transition: all 0.3s;
}

.size-tab:hover {
    color: #000;
}

.size-tab.active {
    color: #000;
    border-bottom-color: #000;
}

/* Size Table */
.size-table-wrapper {
    display: none;
}

.size-table-wrapper.active {
    display: block;
}

.size-table-scroll {
    overflow-x: auto;
}

.size-table {
    width: 100%;
    border-collapse: collapse;
}

.size-table th,
.size-table td {
    padding: 12px;
    text-align: left;
    border-bottom: 1px solid #eee;
}

.size-table th {
    background: #f9f9f9;
    font-weight: 600;
    font-size: 14px;
}

.size-table td {
    font-size: 14px;
}

.size-table tbody tr:hover {
    background: #f5f5f5;
}

/* Measurement Guide */
.measurement-guide {
    margin-top: 30px;
    padding: 20px;
    background: #f9f9f9;
    border-radius: 6px;
}

.measurement-guide h3 {
    margin: 0 0 15px;
    font-size: 16px;
}

.measurement-tips {
    display: grid;
    gap: 10px;
}

.measurement-tip {
    font-size: 14px;
}

.measurement-tip strong {
    display: inline-block;
    min-width: 100px;
    color: #000;
}

/* Responsive */
@media (max-width: 768px) {
    .size-chart-content {
        width: 95%;
        max-height: 95vh;
    }

    .size-chart-header,
    .size-chart-body {
        padding: 20px;
    }

    .size-tabs {
        flex-wrap: wrap;
    }

    .size-tab {
        padding: 8px 15px;
        font-size: 14px;
    }

    .size-table th,
    .size-table td {
        padding: 8px;
        font-size: 13px;
    }
}

Dynamic Size Chart from Metafields

<!-- Load size chart data from product metafields -->
{% if product.metafields.custom.size_chart %}
    <script>
    window.productSizeChart = {{ product.metafields.custom.size_chart }};
    </script>
{% endif %}
// Render custom size chart from metafield
if (window.productSizeChart) {
    const sizeChartData = JSON.parse(window.productSizeChart);
    // Render dynamic table from data
}

Features

  • Tabbed Interface: Easy navigation between categories
  • Responsive Tables: Horizontal scroll on mobile
  • Measurement Guide: Helps customers measure correctly
  • Professional Design: Clean, modern appearance
  • Keyboard Accessible: ESC to close
  • Mobile Optimized: Perfect on all devices
  • Analytics Ready: Track usage for insights
  • Customizable: Easy to modify for your sizes

Related Snippets