Loading
Copy-paste a theme-editor section for marketing - A real countdown to a fixed end date set in the theme editor - it does not reset per visitor. Adapted from a real storefront build.
The offer ends soon
{%- comment -%} Counts down to a fixed end date you set in the theme editor, so every visitor sees the same honest deadline.{%- endcomment -%}<gpl-countdown class="gpl-cd" data-end="{{ section.settings.end_date | escape }}" style="--gpl-accent: {{ section.settings.accent }};"> <div class="gpl-cd__card"> {%- if section.settings.badge != blank -%} <span class="gpl-cd__badge">{{ section.settings.badge | escape }}</span> {%- endif -%} {%- if section.settings.heading != blank -%} <p class="gpl-cd__heading">{{ section.settings.heading | escape }}</p> {%- endif -%} <div class="gpl-cd__clock" role="timer"> <span class="gpl-cd__slot"><b data-h>00</b><small>Hours</small></span> <span class="gpl-cd__colon" aria-hidden="true">:</span> <span class="gpl-cd__slot"><b data-m>00</b><small>Mins</small></span> <span class="gpl-cd__colon" aria-hidden="true">:</span> <span class="gpl-cd__slot gpl-cd__slot--accent"><b data-s>00</b><small>Secs</small></span> </div> <p class="gpl-cd__done" data-done hidden>{{ section.settings.finished_text | escape }}</p> </div></gpl-countdown> {% schema %}{ "name": "Countdown timer", "settings": [ { "type": "text", "id": "badge", "label": "Badge", "default": "Limited time" }, { "type": "text", "id": "heading", "label": "Heading", "default": "The offer ends soon" }, { "type": "text", "id": "end_date", "label": "End date (ISO 8601)", "info": "Example: 2030-12-31T23:59:59+05:30. One fixed deadline for all visitors.", "default": "2030-12-31T23:59:59+05:30" }, { "type": "text", "id": "finished_text", "label": "Text when finished", "default": "This offer has ended." }, { "type": "color", "id": "accent", "label": "Accent colour", "default": "#c8f542" } ], "presets": [{ "name": "Countdown timer" }]}{% endschema %} {% stylesheet %}.gpl-cd { display: block; }.gpl-cd__card { position: relative; width: 100%; max-width: clamp(18rem, 40vw, 28rem); margin: 0 auto; padding: clamp(1rem, 3.5vw, 1.4rem) clamp(0.8rem, 4vw, 1.5rem); border-radius: clamp(12px, 3vw, 16px); background: linear-gradient(145deg, rgba(16, 24, 40, 0.95), rgba(8, 12, 27, 0.98)); border: 1px solid color-mix(in srgb, var(--gpl-accent) 25%, transparent); box-shadow: 0 16px 40px -10px rgba(0, 0, 0, 0.7), 0 0 24px -6px color-mix(in srgb, var(--gpl-accent) 18%, transparent), inset 0 1px 0 rgb(255 255 255 / 0.08); color: #fff; text-align: center; overflow: hidden;}/* Neon edge + ambient sheen */.gpl-cd__card::before { content: ""; position: absolute; top: 0; left: 15%; right: 15%; height: 1px; background: linear-gradient(90deg, transparent, var(--gpl-accent), #38bdf8, transparent); opacity: 0.9;}.gpl-cd__card::after { content: ""; position: absolute; top: -50%; left: -80%; width: 40%; height: 200%; background: linear-gradient(120deg, transparent, rgb(255 255 255 / 0.05), transparent); transform: rotate(25deg); animation: gpl-cd-sheen 5.5s ease-in-out infinite; pointer-events: none;}@keyframes gpl-cd-sheen { 0% { left: -80%; } 30%, 100% { left: 180%; }}.gpl-cd__badge { display: inline-flex; align-items: center; gap: 0.3rem; border: 1px solid rgb(251 191 36 / 0.35); background: rgb(245 158 11 / 0.1); color: #fbbf24; border-radius: 999px; padding: 0.25rem 0.75rem; font-size: clamp(0.6rem, 2vw, 0.7rem); font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; text-shadow: 0 0 10px rgb(245 158 11 / 0.3);}.gpl-cd__heading { margin: 0.45rem 0 0; color: #94a3b8; font-size: clamp(0.7rem, 2.3vw, 0.82rem); }.gpl-cd__clock { display: flex; align-items: center; justify-content: center; gap: clamp(0.3rem, 1.8vw, 0.55rem); margin-top: clamp(0.75rem, 2.5vw, 1.1rem);}.gpl-cd__slot { display: grid; gap: 0.3rem; flex: 1; max-width: 5rem; }.gpl-cd__slot b { position: relative; display: grid; place-items: center; height: clamp(2.6rem, 12vw, 3.4rem); border: 1px solid rgb(140 170 210 / 0.18); border-radius: clamp(8px, 2vw, 10px); background: rgba(4, 9, 20, 0.85); box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.08), 0 4px 12px rgba(0, 0, 0, 0.4); font-family: ui-monospace, "Roboto Mono", Menlo, monospace; font-size: clamp(1.15rem, 5vw, 1.45rem); font-weight: 800; color: #fff; text-shadow: 0 0 12px rgb(255 255 255 / 0.25); overflow: hidden;}/* flip-style seam */.gpl-cd__slot b::before { content: ""; position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: rgb(255 255 255 / 0.06);}.gpl-cd__slot--accent b { border-color: color-mix(in srgb, var(--gpl-accent) 50%, transparent); background: rgba(8, 24, 28, 0.9); color: #5eead4; text-shadow: 0 0 14px color-mix(in srgb, var(--gpl-accent) 50%, transparent); box-shadow: 0 0 18px color-mix(in srgb, var(--gpl-accent) 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--gpl-accent) 35%, transparent);}.gpl-cd__slot small { color: rgb(var(--color-foreground, 100 116 139) / 0.75); font-size: clamp(0.55rem, 1.9vw, 0.65rem); font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;}.gpl-cd__slot--accent small { color: #5eead4; }.gpl-cd__colon { font-family: ui-monospace, monospace; font-weight: 700; color: rgb(var(--color-foreground, 148 163 184) / 0.55); animation: gpl-cd-blink 1s steps(2, start) infinite;}@keyframes gpl-cd-blink { 50% { opacity: 0.2; }}@media (prefers-reduced-motion: reduce) { .gpl-cd__card::after, .gpl-cd__colon { animation: none; }}.gpl-cd__done { margin: 0.9rem 0 0; color: #94a3b8; font-size: 0.9rem; }.gpl-cd__done[hidden] { display: none; }{% endstylesheet %} {% javascript %}class GplCountdown extends HTMLElement { connectedCallback() { const end = Date.parse(this.dataset.end || ''); const h = this.querySelector('[data-h]'); const m = this.querySelector('[data-m]'); const s = this.querySelector('[data-s]'); const done = this.querySelector('[data-done]'); const clock = this.querySelector('.gpl-cd__clock'); if (Number.isNaN(end)) return; const pad = (n) => String(n).padStart(2, '0'); const tick = () => { const left = Math.max(0, end - Date.now()); h.textContent = pad(Math.floor(left / 3600000)); m.textContent = pad(Math.floor((left % 3600000) / 60000)); s.textContent = pad(Math.floor((left % 60000) / 1000)); if (left <= 0) { clearInterval(this.timer); clock.hidden = true; done.hidden = false; } }; tick(); this.timer = setInterval(tick, 1000); } disconnectedCallback() { clearInterval(this.timer); }}if (!customElements.get('gpl-countdown')) customElements.define('gpl-countdown', GplCountdown);{% endjavascript %}