Shopify 商品页倒计时代码

By | 2025-09-15

功能:

  • 标题、副标题、倒计时、角标、优惠券代码复制
  • Translate & Adapt多语言翻译
  • 倒计时显示/隐藏
  • 字体大小、颜色、粗细等细节自定义

使用方式:

  1. shopify 主题 snippets 文件夹下新建文件 countdown-promo-block.liquid,粘贴以下代码
Liquid
<div id="countdown-promo-{{ block.id }}" class="countdown-promo" {{ block.shopify_attributes }}
  style="
    --cp-bg: {{ block.settings.wrap_bg | default: '#ffffff' }};
    --cp-border-color: {{ block.settings.wrap_border_color | default: '#000000' }};
    --cp-border-style: {{ block.settings.wrap_border_style }};
    --cp-border-width: {{ block.settings.wrap_border_width }}px;
    --cp-radius: {{ block.settings.wrap_radius }}px;
    --cp-padding-block: {{ block.settings.wrap_padding_y }}px;
    --cp-padding-inline: {{ block.settings.wrap_padding_x }}px;
    --cp-margin-block: {{ block.settings.wrap_margin_y }}px;
    --cp-margin-inline: {{ block.settings.wrap_margin_x }}px;

    --title-color: {{ block.settings.title_color | default: '#111111' }};
    --title-size: {{ block.settings.title_size }}px;
    --title-weight: {{ block.settings.title_weight | default: 700 }};

    --subtitle-color: {{ block.settings.subtitle_color | default: '#333333' }};
    --subtitle-size: {{ block.settings.subtitle_size }}px;
    --subtitle-weight: {{ block.settings.subtitle_weight | default: 500 }};

    --num-bg: {{ block.settings.num_bg | default: '#000000' }};
    --num-color: {{ block.settings.num_color | default: '#ffffff' }};
    --num-size: {{ block.settings.num_size }}px;

    --label-bg: {{ block.settings.label_bg | default: 'transparent' }};
    --label-color: {{ block.settings.label_color | default: '#333333' }};
    --label-size: {{ block.settings.label_size }}px;
    --label-weight: {{ block.settings.label_weight | default: 500 }};

    --coupon-bg: {{ block.settings.coupon_bg | default: '#ffffff' }};
    --coupon-color: {{ block.settings.coupon_color | default: '#111111' }};
    --coupon-border-color: {{ block.settings.coupon_border_color | default: '#111111' }};
    --coupon-border-style: {{ block.settings.coupon_border_style }};
    --coupon-border-width: {{ block.settings.coupon_border_width }}px;
    --coupon-radius: {{ block.settings.coupon_radius }}px;
    --coupon-size: {{ block.settings.coupon_size }}px;
    --coupon-weight: {{ block.settings.coupon_weight | default: 600 }};

    --ribbon-bg: {{ block.settings.ribbon_bg | default: '#111111' }};
    --ribbon-color: {{ block.settings.ribbon_color | default: '#ffffff' }};
  "
  data-ribbon-corner="{{ block.settings.ribbon_corner }}"
>
  <style>
    #countdown-promo-{{ block.id }}{
      position: relative;
      background: var(--cp-bg);
      border: var(--cp-border-width) var(--cp-border-style) var(--cp-border-color);
      border-radius: var(--cp-radius);
      padding: var(--cp-padding-block) var(--cp-padding-inline);
      margin: var(--cp-margin-block) var(--cp-margin-inline);
      max-width: 560px;
    }
    #countdown-promo-{{ block.id }} .cp-inner{ text-align:center }

    #countdown-promo-{{ block.id }} .cp-ribbon{
      position: absolute;
      top: 10px;
      padding: 6px 14px;
      background: var(--ribbon-bg);
      color: var(--ribbon-color);
      font-size: 12px;
      font-weight: 700;
      letter-spacing: .02em;
      border-radius: 999px;
      line-height: 1;
      white-space: nowrap;
      pointer-events: none;
      z-index: 2;
    }
    #countdown-promo-{{ block.id }}[data-ribbon-corner="right"] .cp-ribbon{ right: 10px; }
    #countdown-promo-{{ block.id }}[data-ribbon-corner="left"]  .cp-ribbon{ left: 10px; }

    #countdown-promo-{{ block.id }} .cp-title{
      margin:0 0 8px;color:var(--title-color);font-size:var(--title-size);line-height:1.2;font-weight:var(--title-weight);
      {% if block.settings.title_font != blank %}font-family: {{ block.settings.title_font.family }}, {{ block.settings.title_font.fallback_families }};{% endif %}
      display:inline-flex;align-items:center;gap:.4em;
    }
    #countdown-promo-{{ block.id }} .cp-subtitle{
      margin:0 0 16px;color:var(--subtitle-color);font-size:var(--subtitle-size);line-height:1.4;font-weight:var(--subtitle-weight);
      {% if block.settings.subtitle_font != blank %}font-family: {{ block.settings.subtitle_font.family }}, {{ block.settings.subtitle_font.fallback_families }};{% endif %}
    }

    #countdown-promo-{{ block.id }} .cp-timer{
      display:flex;width:100%;justify-content:center;gap:14px;align-items:flex-end;margin-bottom:12px
    }
    #countdown-promo-{{ block.id }} .cp-unit{display:grid;grid-template-rows:auto auto;gap:6px;justify-items:center;min-width:68px}
    #countdown-promo-{{ block.id }} .cp-num{
      background:var(--num-bg);color:var(--num-color);font-size:var(--num-size);line-height:1;
      padding:10px 12px;border-radius:8px;box-shadow:0 2px 0 rgba(0,0,0,.15), inset 0 -2px 0 rgba(255,255,255,.15);
      {% if block.settings.num_font != blank %}font-family: {{ block.settings.num_font.family }}, {{ block.settings.num_font.fallback_families }};{% endif %}
      font-weight:700;letter-spacing:.02em;
    }
    #countdown-promo-{{ block.id }} .cp-label{
      background:var(--label-bg);color:var(--label-color);font-size:var(--label-size);line-height:1.1;padding:2px 6px;border-radius:6px;
      {% if block.settings.label_font != blank %}font-family: {{ block.settings.label_font.family }}, {{ block.settings.label_font.fallback_families }};{% endif %}
      font-weight: var(--label-weight);
    }

    #countdown-promo-{{ block.id }} .cp-coupon{
      display:inline-flex;align-items:center;gap:10px;margin-top:10px;padding:10px 14px;background:var(--coupon-bg);color:var(--coupon-color);
      border:var(--coupon-border-width) var(--coupon-border-style) var(--coupon-border-color);border-radius:var(--coupon-radius);
      font-size:var(--coupon-size);cursor:pointer;user-select:none;position:relative;
      font-weight: var(--coupon-weight);
      {% if block.settings.coupon_font != blank %}font-family: {{ block.settings.coupon_font.family }}, {{ block.settings.coupon_font.fallback_families }};{% endif %}
    }
    #countdown-promo-{{ block.id }} .cp-scissors{ display:inline-flex; width:16px; height:16px; }
    #countdown-promo-{{ block.id }} .cp-scissors svg{ width:16px; height:16px; display:block; }
    #countdown-promo-{{ block.id }} .cp-coupon .cp-copy-tip{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none;opacity:0;transition:opacity .2s}
    #countdown-promo-{{ block.id }} .cp-coupon.copied .cp-copy-tip{opacity:1;background-color: #D3FFE0;}
    #countdown-promo-{{ block.id }} .cp-coupon.copied .cp-text{opacity:0}

    @media (max-width:480px){
      #countdown-promo-{{ block.id }} .cp-timer{gap:8px}
      #countdown-promo-{{ block.id }} .cp-unit{min-width:58px}
    }
  </style>

  {%- if block.settings.ribbon_enable and block.settings.ribbon_text != blank -%}
    <div class="cp-ribbon">{{ block.settings.ribbon_text }}</div>
  {%- endif -%}

  <div class="cp-inner">
    {% if block.settings.title != blank %}
      <h3 class="cp-title">
        <span>{{ block.settings.title }}</span>
      </h3>
    {% endif %}

    {% if block.settings.subtitle != blank %}
      <p class="cp-subtitle">{{ block.settings.subtitle }}</p>
    {% endif %}

    {%- if block.settings.enable_timer -%}
      <div class="cp-timer" role="timer" aria-live="polite"
           data-days="{{ block.settings.init_days | default: 0 }}"
           data-hours="{{ block.settings.init_hours | default: 0 }}"
           data-mins="{{ block.settings.init_minutes | default: 0 }}"
           data-secs="{{ block.settings.init_seconds | default: 0 }}">
        <div class="cp-unit"><div class="cp-num" data-num="days">00</div><div class="cp-label">{{ block.settings.label_days | default: 'Days' }}</div></div>
        <div class="cp-unit"><div class="cp-num" data-num="hours">00</div><div class="cp-label">{{ block.settings.label_hours | default: 'Hrs' }}</div></div>
        <div class="cp-unit"><div class="cp-num" data-num="mins">00</div><div class="cp-label">{{ block.settings.label_minutes | default: 'Min.' }}</div></div>
        <div class="cp-unit"><div class="cp-num" data-num="secs">00</div><div class="cp-label">{{ block.settings.label_seconds | default: 'Sec.' }}</div></div>
      </div>
    {%- endif -%}

    {% if block.settings.coupon_text != blank %}
      <div class="cp-coupon"
           data-code="{{ block.settings.coupon_code | escape }}"
           data-copied="{{ block.settings.coupon_copied | escape }}">
        <span class="cp-text">{{ block.settings.coupon_text }}</span>

        <span class="cp-scissors" aria-hidden="true">
          <svg width="800px" height="800px" viewBox="0 0 24 24" id="scissors-2" data-name="Flat Line" xmlns="http://www.w3.org/2000/svg" class="icon flat-line"><path id="primary" d="M16.91,4.32c1.55-.68,3.29-.25,3.89,1S20.63,8,19.09,8.68s-3.29.25-3.89-1S15.37,5,16.91,4.32ZM3,16,19.09,8.68m-2.18,11c1.55.68,3.29.25,3.89-1s-.17-2.73-1.71-3.4-3.29-.25-3.89,1S15.37,19,16.91,19.68Zm2.18-4.36L3,8" style="fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></path></svg>
        </span>

        <span class="cp-copy-tip">{{ block.settings.coupon_copied }}</span>
      </div>
    {% endif %}
  </div>

  <script>
  (function(){
    const root = document.getElementById('countdown-promo-{{ block.id }}');
    if(!root) return;

    {% if block.settings.enable_timer %}
    const t = root.querySelector('.cp-timer');
    if (t){
      const d = parseInt(t.dataset.days || '0',10),
            h = parseInt(t.dataset.hours||'0',10),
            m = parseInt(t.dataset.mins ||'0',10),
            s = parseInt(t.dataset.secs ||'0',10);
      const target = new Date(Date.now() + (((d*24 + h)*60 + m)*60 + s) * 1000);
      const pad = n => (n<10?'0':'') + n;

      function tick(){
        let diff = Math.max(0, Math.floor((target - new Date())/1000));
        const dd = Math.floor(diff/86400); diff -= dd*86400;
        const hh = Math.floor(diff/3600);  diff -= hh*3600;
        const mm = Math.floor(diff/60);    diff -= mm*60;
        const ss = diff;
        t.querySelector('[data-num="days"]').textContent  = pad(dd);
        t.querySelector('[data-num="hours"]').textContent = pad(hh);
        t.querySelector('[data-num="mins"]').textContent  = pad(mm);
        t.querySelector('[data-num="secs"]').textContent  = pad(ss);
      }
      tick();
      const iv = setInterval(()=>{ tick();
        if(t.querySelector('[data-num="days"]').textContent==='00' &&
           t.querySelector('[data-num="hours"]').textContent==='00' &&
           t.querySelector('[data-num="mins"]').textContent==='00' &&
           t.querySelector('[data-num="secs"]').textContent==='00'){ clearInterval(iv); }
      },1000);
    }
    {% endif %}

    const coupon = root.querySelector('.cp-coupon');
    if(coupon){
      coupon.addEventListener('click', async ()=>{
        const code = coupon.dataset.code || '';
        try{ await navigator.clipboard.writeText(code); }catch(e){
          const ta=document.createElement('textarea'); ta.value=code; document.body.appendChild(ta);
          ta.select(); try{ document.execCommand('copy'); }catch(_){}
          ta.remove();
        }
        coupon.classList.add('copied'); setTimeout(()=>coupon.classList.remove('copied'),2000);
      }, {passive:true});
    }
  })();
  </script>
</div>

shopify 主题 sections目录下,找到main-product.liquid文件,在 main-product.liquid 中有一段类似:

Liquid
{% for block in section.blocks %}
  {% case block.type %}
    ...
  {% endcase %}
{% endfor %}

在 case 里加入一条分支:

Liquid
{% when 'countdown_promo' %}
  {% render 'countdown-promo-block', block: block %}

然后在同文件底部的 {% schema %} → “blocks”: [ … ] 数组中,新增一个 block 定义(可放在合适位置)。下面是完整可用的 block schema

Liquid
{
  "type": "countdown_promo",
  "name": "Countdown Promo",
  "limit": 1,
  "settings": [
    { "type": "checkbox", "id": "enable_timer", "label": "显示倒计时", "default": true },

    { "type": "header", "content": "Wrapper (背景/边框/间距)" },
    { "type": "color", "id": "wrap_bg", "label": "模块背景色", "default": "#ffffff" },
    { "type": "color", "id": "wrap_border_color", "label": "边框颜色", "default": "#111111" },
    { "type": "select", "id": "wrap_border_style", "label": "边框样式", "options": [
      { "value": "solid", "label": "solid" }, { "value": "dashed", "label": "dashed" }, { "value": "dotted", "label": "dotted" }
    ], "default": "solid" },
    { "type": "range", "id": "wrap_border_width", "min": 0, "max": 8, "step": 1, "unit": "px", "label": "边框宽度", "default": 1 },
    { "type": "range", "id": "wrap_radius", "min": 0, "max": 24, "step": 1, "unit": "px", "label": "圆角", "default": 10 },
    { "type": "range", "id": "wrap_padding_y", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "上下内边距", "default": 20 },
    { "type": "range", "id": "wrap_padding_x", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "左右内边距", "default": 20 },
    { "type": "range", "id": "wrap_margin_y", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "上下外边距", "default": 10 },
    { "type": "range", "id": "wrap_margin_x", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "左右外边距", "default": 0 },

    { "type": "header", "content": "标题/副标题" },
    { "type": "text", "id": "title", "label": "标题", "default": "🔥 Autumn Collection on Sale 🔥" },
    { "type": "font_picker", "id": "title_font", "label": "标题字体", "default": "roboto_n4" },
    { "type": "range", "id": "title_size", "min": 14, "max": 56, "step": 1, "unit": "px", "label": "标题字号", "default": 28 },
    { "type": "range", "id": "title_weight", "min": 100, "max": 900, "step": 50, "label": "标题粗细", "default": 700 },
    { "type": "color", "id": "title_color", "label": "标题颜色", "default": "#111111" },

    { "type": "text", "id": "subtitle", "label": "副标题", "default": "Innovative Comfort Technology ⏳" },
    { "type": "font_picker", "id": "subtitle_font", "label": "副标题字体", "default": "roboto_n4" },
    { "type": "range", "id": "subtitle_size", "min": 12, "max": 32, "step": 1, "unit": "px", "label": "副标题字号", "default": 16 },
    { "type": "range", "id": "subtitle_weight", "min": 100, "max": 900, "step": 50, "label": "副标题粗细", "default": 500 },
    { "type": "color", "id": "subtitle_color", "label": "副标题颜色", "default": "#333333" },

    { "type": "header", "content": "倒计时" },
    { "type": "range", "id": "init_days", "min": 0, "max": 30, "step": 1, "label": "天", "default": 0 },
    { "type": "range", "id": "init_hours", "min": 0, "max": 72, "step": 1, "label": "小时", "default": 7 },
    { "type": "range", "id": "init_minutes", "min": 0, "max": 59, "step": 1, "label": "分钟", "default": 2 },
    { "type": "range", "id": "init_seconds", "min": 0, "max": 59, "step": 1, "label": "秒钟", "default": 30 },

    { "type": "header", "content": "倒计时数字样式" },
    { "type": "font_picker", "id": "num_font", "label": "数字字体", "default": "roboto_n4" },
    { "type": "range", "id": "num_size", "min": 16, "max": 64, "step": 1, "unit": "px", "label": "数字字号", "default": 32 },
    { "type": "color", "id": "num_color", "label": "数字颜色", "default": "#ffffff" },
    { "type": "color", "id": "num_bg", "label": "数字背景色", "default": "#000000" },

    { "type": "header", "content": "时间单位标签" },
    { "type": "text", "id": "label_days", "label": "“天”标签文本", "default": "Days" },
    { "type": "text", "id": "label_hours", "label": "“小时”标签文本", "default": "Hrs" },
    { "type": "text", "id": "label_minutes", "label": "“分钟”标签文本", "default": "Min." },
    { "type": "text", "id": "label_seconds", "label": "“秒钟”标签文本", "default": "Sec." },
    { "type": "font_picker", "id": "label_font", "label": "标签字体", "default": "roboto_n4" },
    { "type": "range", "id": "label_size", "min": 10, "max": 24, "step": 1, "unit": "px", "label": "标签字号", "default": 12 },
    { "type": "range", "id": "label_weight", "min": 100, "max": 900, "step": 50, "label": "标签粗细", "default": 500 },
    { "type": "color", "id": "label_color", "label": "标签颜色", "default": "#333333" },
    { "type": "color", "id": "label_bg", "label": "标签背景色", "default": "#00000000" },

    { "type": "header", "content": "优惠券" },
    { "type": "text", "id": "coupon_text", "label": "优惠券展示文本", "default": "10% Off New Arrivals" },
    { "type": "text", "id": "coupon_code", "label": "点击复制的优惠码", "default": "FALL10" },
    { "type": "text", "id": "coupon_copied", "label": "复制成功提示", "default": "Code Copied!" },
    { "type": "font_picker", "id": "coupon_font", "label": "优惠券字体", "default": "roboto_n4" },
    { "type": "range", "id": "coupon_size", "min": 12, "max": 24, "step": 1, "unit": "px", "label": "优惠券字号", "default": 14 },
    { "type": "range", "id": "coupon_weight", "min": 100, "max": 900, "step": 50, "label": "优惠券粗细", "default": 600 },
    { "type": "color", "id": "coupon_bg", "label": "优惠券背景色", "default": "#ffffff" },
    { "type": "color", "id": "coupon_color", "label": "优惠券文字颜色", "default": "#111111" },
    { "type": "color", "id": "coupon_border_color", "label": "优惠券边框颜色", "default": "#111111" },
    { "type": "select", "id": "coupon_border_style", "label": "优惠券边框样式", "options": [
      { "value": "dashed", "label": "dashed" }, { "value": "solid", "label": "solid" }, { "value": "dotted", "label": "dotted" }
    ], "default": "dashed" },
    { "type": "range", "id": "coupon_border_width", "min": 0, "max": 6, "step": 1, "unit": "px", "label": "优惠券边框宽度", "default": 1 },
    { "type": "range", "id": "coupon_radius", "min": 0, "max": 20, "step": 1, "unit": "px", "label": "优惠券圆角", "default": 8 },

    { "type": "header", "content": "角标" },
    { "type": "checkbox", "id": "ribbon_enable", "label": "显示角标", "default": true },
    { "type": "text", "id": "ribbon_text", "label": "角标文字", "default": "SALE" },
    { "type": "select", "id": "ribbon_corner", "label": "角标位置", "options": [
      { "value": "right", "label": "右上角" }, { "value": "left", "label": "左上角" }
    ], "default": "right" },
    { "type": "color", "id": "ribbon_bg", "label": "角标背景色", "default": "#111111" },
    { "type": "color", "id": "ribbon_color", "label": "角标文字颜色", "default": "#ffffff" }
  ]
},
Product Information Section配置界面添加Blocks
Countdown Promo设置
多语言翻译

Leave a Reply

Your email address will not be published. Required fields are marked *