Shopify Liquid实现移动端与桌面端变体选择控件差异化显示问询
解决方案
方法1:渲染两套控件,用CSS媒体查询控制显示/隐藏
这是最直接的方案——让Liquid同时输出单选框和下拉菜单两套变体选择控件,再通过CSS根据屏幕尺寸控制哪套显示、哪套隐藏,最后用JS同步两套控件的选中状态避免操作混乱。
Liquid代码(生成两套控件)
<!-- 桌面端单选框组 --> <div class="variant-selector variant-radios"> {% for option in product.options %} <div class="option-group"> <h3>{{ option.name }}</h3> {% for value in option.values %} <input type="radio" name="options[{{ option.name }}]" id="opt-{{ option.name | handle }}-{{ value | handle }}" value="{{ value }}" {% if product.selected_options[forloop.parentloop.index0].value == value %}checked{% endif %} > <label for="opt-{{ option.name | handle }}-{{ value | handle }}">{{ value }}</label> {% endfor %} </div> {% endfor %} </div> <!-- 移动端下拉菜单组 --> <div class="variant-selector variant-dropdown"> {% for option in product.options %} <select name="options[{{ option.name }}]"> {% for value in option.values %} <option value="{{ value }}" {% if product.selected_options[forloop.parentloop.index0].value == value %}selected{% endif %} >{{ option.name }}: {{ value }}</option> {% endfor %} </select> {% endfor %} </div>
CSS代码(控制显示逻辑)
/* 默认显示单选框,隐藏下拉菜单 */ .variant-dropdown { display: none; } .variant-radios { display: flex; gap: 2rem; flex-wrap: wrap; } /* 移动端切换显示规则 */ @media (max-width: 767px) { .variant-radios { display: none; } .variant-dropdown { display: flex; flex-direction: column; gap: 1rem; } }
JS代码(同步选中状态)
// 单选框变化时同步下拉菜单 document.querySelectorAll('.variant-radios input[type="radio"]').forEach(radio => { radio.addEventListener('change', () => { const optionName = radio.name.match(/options\[(.*?)\]/)[1]; const targetSelect = document.querySelector(`.variant-dropdown select[name="options[${optionName}]"]`); targetSelect.value = radio.value; }); }); // 下拉菜单变化时同步单选框 document.querySelectorAll('.variant-dropdown select').forEach(select => { select.addEventListener('change', () => { const optionName = select.name.match(/options\[(.*?)\]/)[1]; const targetRadio = document.querySelector(`.variant-radios input[type="radio"][name="options[${optionName}]"][value="${select.value}"]`); if (targetRadio) targetRadio.checked = true; }); });
方法2:Liquid输出变体数据,JS动态生成对应控件
如果不想在页面中冗余渲染控件,可以让Liquid只输出产品变体的结构化数据,再用JS根据当前屏幕尺寸动态生成单选框或下拉菜单。
Liquid代码(输出变体JSON数据)
<script> // 把产品变体数据注入到全局变量 window.productData = {{ product | json }}; </script> <div id="variant-controls-container"></div>
JS代码(动态生成控件)
const controlsContainer = document.getElementById('variant-controls-container'); function renderVariantControls() { controlsContainer.innerHTML = ''; const isMobile = window.innerWidth <= 767; window.productData.options.forEach(option => { if (isMobile) { // 生成下拉菜单 const select = document.createElement('select'); select.name = `options[${option.name}]`; option.values.forEach(value => { const optEl = document.createElement('option'); optEl.value = value; optEl.textContent = `${option.name}: ${value}`; // 设置默认选中项 if (window.productData.selected_options.find(opt => opt.name === option.name).value === value) { optEl.selected = true; } select.appendChild(optEl); }); controlsContainer.appendChild(select); } else { // 生成单选框组 const group = document.createElement('div'); const title = document.createElement('h3'); title.textContent = option.name; group.appendChild(title); option.values.forEach(value => { const radio = document.createElement('input'); radio.type = 'radio'; radio.name = `options[${option.name}]`; radio.id = `radio-${option.name}-${value}`; radio.value = value; // 设置默认选中项 if (window.productData.selected_options.find(opt => opt.name === option.name).value === value) { radio.checked = true; } const label = document.createElement('label'); label.htmlFor = radio.id; label.textContent = value; group.appendChild(radio); group.appendChild(label); }); controlsContainer.appendChild(group); } }); } // 首次渲染 renderVariantControls(); // 窗口大小变化时重新渲染 window.addEventListener('resize', renderVariantControls);
方案对比
- 方法1:实现成本低,Liquid逻辑改动小,用户无加载延迟;缺点是多渲染一套控件,DOM体积略有增加(可忽略)。
- 方法2:DOM更简洁,仅渲染当前尺寸所需控件;缺点是需要编写更多JS逻辑,首次加载可能有轻微渲染延迟。
内容的提问来源于stack exchange,提问作者HW2022
相关产品推荐
相关产品推荐

