Sale Countdown

Autumn sale

Up to 40% off the bestsellers

Our biggest sale of the year, on the pieces you love most. While stocks last.

Ends in

03Days 00Hours 00Min 00Sec

Shop the sale
  • -30%

    Everyday Backpack

    Sale price: $62 Original price: $89

  • -40%

    Smart Watch

    Sale price: $179 Original price: $299

  • -30%

    Desk Lamp

    Sale price: $55 Original price: $79

@use 'sprucecss/scss/spruce' as *;

.sale-countdown-block {
  padding-block: spacer-clamp('xl', 'xxl');

  &__inner {
    display: flex;
    flex-direction: column;
    gap: spacer('l');
  }

  // The countdown component on the brand background.
  &__banner {
    @include set-css-variable((
      --base-color-heading: color('primary-foreground', 'btn'),
      --base-color-muted: color-alpha('primary-foreground', 0.8, 'btn'),
      --base-color-text: color('primary-foreground', 'btn'),
    ));
    @include selection(color('secondary-background', 'btn'), color('secondary-foreground', 'btn'));
    align-items: center;
    background-color: color('primary-background', 'btn');
    background-image: radial-gradient(circle at 0% 100%, #{color-alpha('secondary-background', 0.6, 'btn')}, transparent 55%);
    border: 0;
    color: color('primary-foreground', 'btn');
    display: grid;
    gap: spacer('l');
    text-align: start;

    @include breakpoint('lg') {
      grid-template-columns: minmax(0, 1fr) auto;
    }

    // The banner is a grid, so the stack margins of the component don't apply.
    > * {
      margin: 0 !important;
    }

    .countdown__unit {
      background-color: hsl(0deg 0% 100% / 14%);
      min-inline-size: 4.5rem;
    }
  }

  &__copy {
    @include layout-stack('xs');
  }

  &__eyebrow {
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }

  &__title {
    font-size: responsive-font-size(2.75rem, 35, '3vw + 1rem');
  }

  &__text {
    font-size: config('font-size-lead', $typography);
    max-inline-size: 34rem;
    opacity: 0.9;
  }

  &__timer {
    align-items: center;
    display: flex;
    flex-direction: column;
    gap: spacer('s');

    .countdown__title {
      font-size: config('font-size-base', $typography);
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }
  }

  &__action {
    background-color: color('primary-foreground', 'btn');
    border-color: color('primary-foreground', 'btn');
    color: color('primary-background', 'btn');

    &:hover {
      background-color: color-alpha('primary-foreground', 0.9, 'btn');
      color: color('primary-background', 'btn');
    }
  }

  &__grid {
    display: grid;
    gap: spacer('m');
    grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr));
    list-style: none;
    margin: 0;
    padding: 0;

    > li {
      display: flex;
      margin: 0 !important;
      margin-block: 0;
      padding-block: 0;
    }

    .product-card {
      inline-size: 100%;
    }

    del {
      color: color('muted');
      font-size: config('font-size-sm', $typography);
      font-weight: 400;
    }
  }
}
<section class="sale-countdown-block" aria-labelledby="sale-countdown-title">
    <div class="container">
        <div class="sale-countdown-block__inner">
            <div class="countdown sale-countdown-block__banner" data-countdown data-countdown-days="3">
                <div class="sale-countdown-block__copy">
                    <p class="sale-countdown-block__eyebrow">Autumn sale</p>
                    <h2 class="sale-countdown-block__title" id="sale-countdown-title">Up to 40% off the bestsellers</h2>
                    <p class="sale-countdown-block__text">Our biggest sale of the year, on the pieces you love most. While stocks last.</p>
                </div>
                <div class="sale-countdown-block__timer">
                    <p class="countdown__title" id="sale-countdown-label">Ends in</p>
                    <p class="countdown__timer" role="timer" aria-live="off" aria-labelledby="sale-countdown-label" data-countdown-timer>
                        <span class="countdown__unit"><span class="countdown__value" data-unit="days">03</span><span class="countdown__label">Days</span></span>
                        <span class="countdown__unit"><span class="countdown__value" data-unit="hours">00</span><span class="countdown__label">Hours</span></span>
                        <span class="countdown__unit"><span class="countdown__value" data-unit="minutes">00</span><span class="countdown__label">Min</span></span>
                        <span class="countdown__unit"><span class="countdown__value" data-unit="seconds">00</span><span class="countdown__label">Sec</span></span>
                    </p>
                    <p class="sr-only" data-countdown-text></p>
                    <a class="btn btn--lg sale-countdown-block__action" href="#">Shop the sale</a>
                </div>
            </div>
            <ul class="sale-countdown-block__grid" role="list">
                <li>
                    <article class="product-card">
                        <div class="product-card__media">
                            <img src="https://images.unsplash.com/photo-1553062407-98eeb64c6a62?auto=format&amp;fit=crop&amp;w=600&amp;q=70" alt="" loading="lazy" width="600" height="600">
                            <span class="product-card__tag">-30%</span>
                        </div>
                        <div class="product-card__body">
                            <h3 class="product-card__title"><a class="product-card__link" href="#">Everyday Backpack</a></h3>
                            <p class="product-card__price"><span class="sr-only">Sale price: </span>$62 <del><span class="sr-only">Original price: </span>$89</del></p>
                        </div>
                        <button class="btn btn--primary btn--sm product-card__action" type="button">Add to cart<span class="sr-only">: Everyday Backpack</span></button>
                    </article>
                </li>
                <li>
                    <article class="product-card">
                        <div class="product-card__media">
                            <img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?auto=format&amp;fit=crop&amp;w=600&amp;q=70" alt="" loading="lazy" width="600" height="600">
                            <span class="product-card__tag">-30%</span>
                        </div>
                        <div class="product-card__body">
                            <h3 class="product-card__title"><a class="product-card__link" href="#">Wireless Headphones</a></h3>
                            <p class="product-card__price"><span class="sr-only">Sale price: </span>$139 <del><span class="sr-only">Original price: </span>$199</del></p>
                        </div>
                        <button class="btn btn--primary btn--sm product-card__action" type="button">Add to cart<span class="sr-only">: Wireless Headphones</span></button>
                    </article>
                </li>
                <li>
                    <article class="product-card">
                        <div class="product-card__media">
                            <img src="https://images.unsplash.com/photo-1523275335684-37898b6baf30?auto=format&amp;fit=crop&amp;w=600&amp;q=70" alt="" loading="lazy" width="600" height="600">
                            <span class="product-card__tag">-40%</span>
                        </div>
                        <div class="product-card__body">
                            <h3 class="product-card__title"><a class="product-card__link" href="#">Smart Watch</a></h3>
                            <p class="product-card__price"><span class="sr-only">Sale price: </span>$179 <del><span class="sr-only">Original price: </span>$299</del></p>
                        </div>
                        <button class="btn btn--primary btn--sm product-card__action" type="button">Add to cart<span class="sr-only">: Smart Watch</span></button>
                    </article>
                </li>
                <li>
                    <article class="product-card">
                        <div class="product-card__media">
                            <img src="https://images.unsplash.com/photo-1507473885765-e6ed057f782c?auto=format&amp;fit=crop&amp;w=600&amp;q=70" alt="" loading="lazy" width="600" height="600">
                            <span class="product-card__tag">-30%</span>
                        </div>
                        <div class="product-card__body">
                            <h3 class="product-card__title"><a class="product-card__link" href="#">Desk Lamp</a></h3>
                            <p class="product-card__price"><span class="sr-only">Sale price: </span>$55 <del><span class="sr-only">Original price: </span>$79</del></p>
                        </div>
                        <button class="btn btn--primary btn--sm product-card__action" type="button">Add to cart<span class="sr-only">: Desk Lamp</span></button>
                    </article>
                </li>
            </ul>
        </div>
    </div>
</section>

Sale Countdown

On this page

A limited-time sale: a banner with a live countdown and a call to action, followed by the discounted products.

Technical Details

  • It combines the Countdown (styled on the brand background) and Product Cards. Load the countdown script too.
  • The countdown runs to data-countdown-days from now; set a fixed data-countdown-end date (like 2026-10-31T23:59:00) for a real sale. The timer is aria-live="off", and the script updates a hidden summary once a minute, so screen readers aren't flooded with seconds.
  • The sale prices have hidden "Sale price" and "Original price" labels, because a strikethrough isn't announced.
  • The banner overrides the heading, text and muted color tokens, and the text selection uses the secondary button colors, so everything stays readable on the brand color in every style.
  • Only show a countdown for a deadline that's real.
  • Override the content with saleCountdownBlock.

Documentation

Learn about Spruce CSS through our extensive documentation.

Components

Explore our UI library of accessible components built with Spruce CSS.

Blocks and Pages

Full-width page blocks and complete page templates, ready to copy.

Find us on GitHub

Did you find a bug? Have an idea or a question? Please open an issue to help us develop the project.