Newsletter

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

.newsletter {
  align-items: center;
  background-color: color('surface-muted');
  border: config('border-width-base', $display) solid color('border');
  border-radius: radius('lg');
  display: grid;
  gap: spacer('m');
  padding: spacer-clamp('m', 'l');

  @include breakpoint('md') {
    grid-template-columns: 1fr 1fr;
  }

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

  &__title {
    font-size: font-size('h3');
  }

  &__text {
    color: color('muted');
  }

  &__form {
    display: flex;
    flex-wrap: wrap;
    gap: spacer('xs');

    .form-control {
      flex: 1 1 14rem;
    }

    .btn {
      flex: 0 0 auto;
    }
  }

  // The GDPR consent takes its own row under the field and the button.
  &__consent {
    flex-basis: 100%;
    font-size: config('font-size-sm', $typography);
  }
}
<section class="newsletter" aria-labelledby="newsletter-title">
    <div class="newsletter__content">
        <h2 class="newsletter__title" id="newsletter-title">Stay in the loop</h2>
        <p class="newsletter__text">Monthly notes about CSS, Sass and design systems. No spam, unsubscribe anytime.</p>
    </div>
    <form class="newsletter__form" onsubmit="return false;">
        <label class="sr-only" for="newsletter-email">Email address</label>
        <input class="form-control" id="newsletter-email" type="email" placeholder="you@example.com" autocomplete="email" required>
        <button class="btn btn--primary" type="submit">Subscribe</button>
        <label class="form-check newsletter__consent" for="newsletter-consent">
            <input class="form-check__control" id="newsletter-consent" name="consent" type="checkbox" required>
            <span class="form-label form-check__label">I agree to receive the newsletter and accept the <a href="#">privacy policy</a>. Unsubscribe anytime.</span>
        </label>
    </form>
</section>

Newsletter

On this page

A compact newsletter sign-up block with an email field and a submit button.

Technical Details

  • The email input has a visually hidden label (the placeholder is not a label) and autocomplete="email".
  • The input grows (flex: 1 1 14rem) and the button keeps its natural width; when there is not enough room, the button wraps below the input, without media queries.
  • Use type="email" and required for native validation; announce the result of the submission in a live region (see the Toast component).
  • The form has a required GDPR consent checkbox, unchecked by default (consent must be an active choice), with a link to the privacy policy. Keep the wording specific: what the person signs up for and how to unsubscribe. Store the consent with a timestamp on the server.

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.