You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 21:45:36