Drifting Particles Field

Diffent background styles you can use. Without layering over HTML.

Code

<div class="particles-section">
  <div class="particles-field">
    <div class="particles-layer particles-layer--1"></div>
    <div class="particles-layer particles-layer--2"></div>
    <div class="particles-layer particles-layer--3"></div>
  </div>
</div>
.particles-section {
  position: relative;
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at top, #020617 0, #000 65%);
  overflow: hidden;
}

.particles-field {
  position: relative;
  width: 100%;
  max-width: 900px;
  aspect-ratio: 16 / 9;
  border-radius: 1.2rem;
  overflow: hidden;
  border: 1px solid rgba(148, 163, 184, 0.35);
  background: radial-gradient(circle at top, #020617 0, #000 70%);
}

/* Shared layer styles */
.particles-layer {
  position: absolute;
  inset: -10%;
  background-repeat: repeat;
  mix-blend-mode: screen;
  opacity: 0.7;
}

/* Fine grain */
.particles-layer--1 {
  background-image:
    radial-gradient(circle, rgba(148, 163, 184, 0.6) 1px, transparent 55%);
  background-size: 40px 40px;
  animation: particles-drift-1 42s linear infinite;
}

/* Medium blobs */
.particles-layer--2 {
  background-image:
    radial-gradient(circle, rgba(56, 189, 248, 0.55) 2px, transparent 60%);
  background-size: 80px 80px;
  animation: particles-drift-2 55s linear infinite;
}

/* Larger soft lights */
.particles-layer--3 {
  background-image:
    radial-gradient(circle, rgba(34, 197, 94, 0.35) 8px, transparent 70%);
  background-size: 180px 180px;
  animation: particles-drift-3 75s linear infinite;
}

@keyframes particles-drift-1 {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(60px, -80px, 0); }
}

@keyframes particles-drift-2 {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(-90px, 60px, 0); }
}

@keyframes particles-drift-3 {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(40px, 90px, 0); }
}
// JS-driven dots (example)
const container = document.querySelector('.particles-field');
const DOT_COUNT = 40;

for (let i = 0; i < DOT_COUNT; i++) {
  const dot = document.createElement('span');
  dot.className = 'particles-dot';
  container.appendChild(dot);
}

Moving Stripe Hero Section

Moving rainbow stripes that can be applied to a Hero Section with no JS.

An awesome title

Code

<section class="demo-stripes">
  <div class="demo-stripes__hero"></div>
  <div class="demo-stripes__content">
    <h3 class="demo-stripes__heading" data-text="An awesome title">
      An awesome title
    </h3>
    <input type="checkbox" id="demo-stripes-switch" class="demo-stripes__switch" />
    <label for="demo-stripes-switch" class="demo-stripes__toggle">
      <span>
        <span class="demo-stripes__icon">→</span>
        switch bg
      </span>
    </label>
  </div>
</section>
/* Scoped Houdini stripes hero */
@property --blink-opacity {
  syntax: "<number>";
  inherits: false;
  initial-value: 1;
}

@keyframes demo-stripes-blink {
  0%, 100% { opacity: var(--blink-opacity, 1); }
  50%      { opacity: 0; }
}

@keyframes demo-stripes-bg-pan {
  from { background-position: 50% 50%, 50% 50%; }
  to   { background-position: 350% 50%, 350% 50%; }
}

/* Root of the card demo */
.demo-stripes {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 240px;
  border-radius: 1rem;
  overflow: hidden;

  --stripe-color: #fff;
  --bg: var(--stripe-color);
}

/* Background rainbow + stripes */
.demo-stripes__hero {
  width: 100%;
  height: 100%;
  position: relative;
  display: flex;
  place-content: center;
  place-items: center;

  --stripes: repeating-linear-gradient(
    100deg,
    var(--stripe-color) 0%,
    var(--stripe-color) 7%,
    transparent 10%,
    transparent 12%,
    var(--stripe-color) 16%
  );

  --rainbow: repeating-linear-gradient(
    100deg,
    #60a5fa 10%,
    #e879f9 15%,
    #60a5fa 20%,
    #5eead4 25%,
    #60a5fa 30%
  );

  background-image: var(--stripes), var(--rainbow);
  background-size: 300%, 200%;
  background-position: 50% 50%, 50% 50%;

  filter: blur(10px) invert(100%);
  mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%);
  -webkit-mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%);
}

.demo-stripes__hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--stripes), var(--rainbow);
  background-size: 200%, 100%;
  animation: demo-stripes-bg-pan 60s linear infinite;
  mix-blend-mode: difference;
}

/* Toggle theme when checked */
.demo-stripes:has(.demo-stripes__switch:checked) {
  --stripe-color: #000;
}

.demo-stripes:has(.demo-stripes__switch:checked) .demo-stripes__hero,
.demo-stripes:has(.demo-stripes__switch:checked) .demo-stripes__hero::after {
  filter: blur(10px) opacity(0.5) saturate(2);
}

/* Foreground content */
.demo-stripes__content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  align-items: center;
  justify-content: center;
  text-align: center;
  mix-blend-mode: difference;
  -webkit-mix-blend-mode: difference;
  filter: invert(1);
  padding: 1.5rem;
}

/* Heading glass effect */
.demo-stripes__heading {
  position: relative;
  margin: 0;
  font-size: clamp(1.4rem, 1rem + 3vw, 2.4rem);
}

.demo-stripes__heading::before {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  background: white;
  text-shadow: 0 0 1px #ffffff;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  -webkit-mask: linear-gradient(#000 0 0) luminance;
  mask: linear-gradient(#000 0 0) luminance, alpha;
  backdrop-filter: blur(19px) brightness(12.5);
  -webkit-text-stroke: 1px white;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

/* Switch */
.demo-stripes__switch {
  appearance: none;
  -webkit-appearance: none;
  opacity: 0;
  position: absolute;
}

.demo-stripes__toggle {
  cursor: pointer;
  padding: 0.5rem 0.75rem;
  border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.6);
  background: rgba(15, 23, 42, 0.9);
  color: #e5e7eb;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  transition: 0.3s ease;
}

.demo-stripes__toggle:hover,
.demo-stripes__toggle:active,
.demo-stripes__toggle:focus-within {
  animation: demo-stripes-switch 0.2s alternate;
}

@keyframes demo-stripes-switch {
  50% {
    transform: scale(1.2);
    font-weight: 900;
  }
}

/* Blinking icon */
.demo-stripes__icon {
  width: 1lh;
  height: 1lh;
  aspect-ratio: 1 / 1;
  padding: 0.25em 0.35rem;
  border-radius: 999px;
  border: 1px dashed currentColor;
  --blink-opacity: 1;
  animation: demo-stripes-blink 2s ease-in-out infinite running;
}
// No JS required for the demo:
// background switch is driven by :has() and a checkbox.
// (You can enhance it later if you want.)

Two-Card Spotlight Row

Perfect for comparing subscription tiers, and product differences.

Standard

$29/mo
  • Core features
  • Email support
  • Single workspace

Pro

$59/mo
  • Everything in Standard
  • Priority support
  • Team workspaces

Code

<section class="pricing-row">
  <article class="pricing-card pricing-card--standard">
    <h3 class="pricing-card__title">Standard</h3>
    <div class="pricing-card__price">
      $29<span class="pricing-card__price-suffix">/mo</span>
    </div>
    <ul class="pricing-card__features">
      <li>Core features</li>
      <li>Email support</li>
      <li>Single workspace</li>
    </ul>
  </article>

  <article class="pricing-card pricing-card--pro">
    <h3 class="pricing-card__title">Pro</h3>
    <div class="pricing-card__price">
      $59<span class="pricing-card__price-suffix">/mo</span>
    </div>
    <ul class="pricing-card__features">
      <li>Everything in Standard</li>
      <li>Priority support</li>
      <li>Team workspaces</li>
    </ul>
  </article>
</section>
.pricing-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.7rem;
}

.pricing-card {
  position: relative;
  width: min(260px, 100%);
  padding: 1.6rem 1.4rem;
  border-radius: 1.1rem;
  border: 1px solid rgba(148, 163, 184, 0.4);
  background: radial-gradient(circle at top, #020617 0, #020617 45%, #000 100%);
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.65);
  overflow: hidden;
  cursor: pointer;
  transition:
    transform 0.25s ease,
    box-shadow 0.25s ease,
    border-color 0.25s ease,
    filter 0.25s ease;
}

.pricing-card--standard { --pricing-accent: #38bdf8; }
.pricing-card--pro      { --pricing-accent: #22c55e; }

/* Radial spotlight glow */
.pricing-card::before {
  content: "";
  position: absolute;
  inset: -40%;
  background: radial-gradient(
    circle at var(--spot-x, 50%) var(--spot-y, 0%),
    color-mix(in oklab, var(--pricing-accent) 65%, transparent 35%) 0,
    transparent 65%
  );
  opacity: 0;
  transition: opacity 0.25s ease;
  z-index: 0;
}

.pricing-card::after {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: inherit;
  background: linear-gradient(to bottom,
    rgba(15, 23, 42, 0.9),
    rgba(15, 23, 42, 0.96)
  );
  z-index: 0;
}

.pricing-card__title,
.pricing-card__price,
.pricing-card__features {
  position: relative;
  z-index: 1;
}

/* ...other text styles omitted for brevity... */

/* Spotlight behaviour */
.pricing-row:hover .pricing-card {
  filter: brightness(0.45) saturate(0.9);
}

.pricing-card:hover,
.pricing-card:focus-within {
  transform: translateY(-8px);
  box-shadow: 0 22px 55px rgba(15, 23, 42, 0.85);
  border-color: color-mix(in oklab, var(--pricing-accent) 65%, #1e293b 35%);
  filter: none;
}

.pricing-card:hover::before,
.pricing-card:focus-within::before {
  opacity: 0.9;
}
// Mouse-follow spotlight (per card)
const cards = document.querySelectorAll('.pricing-card');

cards.forEach(card => {
  card.addEventListener('mousemove', e => {
    const r = card.getBoundingClientRect();
    const x = ((e.clientX - r.left) / r.width) * 100;
    const y = ((e.clientY - r.top) / r.height) * 100;
    card.style.setProperty('--spot-x', x.toFixed(1) + '%');
    card.style.setProperty('--spot-y', y.toFixed(1) + '%');
  });

  card.addEventListener('mouseleave', () => {
    card.style.removeProperty('--spot-x');
    card.style.removeProperty('--spot-y');
  });
});

Rotating 3D CTA Button

A call-to-action button that flips on hover.

Code

<div class="cta-wrapper">
  <a href="#" class="cta-button-3d">
    <span>Let's Begin</span>
    <span>Let's Begin</span>
    <span>Let's Begin</span>
    <span>Let's Begin</span>
  </a>
</div>
.cta-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
}

.cta-button-3d {
  position: relative;
  width: 170px;
  height: 54px;
  display: inline-block;
  transform-style: preserve-3d;
  transform: perspective(1000px) rotateX(0deg);
  transition: transform 4s;
  text-decoration: none;
}

.cta-button-3d:hover {
  transform: perspective(1000px) rotateX(360deg);
}

.cta-button-3d span {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.8rem;
  background: rgba(255, 255, 255, 0.92);
  color: #020617;
  border-radius: 999px;
  border: 2px solid #000;
  box-sizing: border-box;
  box-shadow:
    inset 0 18px 40px rgba(255, 255, 255, 0.9),
    0 10px 30px rgba(0, 0, 0, 0.7);
  transition:
    background-color 0.4s ease,
    color 0.4s ease,
    box-shadow 0.4s ease;
}

.cta-button-3d:hover span {
  background: linear-gradient(135deg, #0ea5e9, #22c55e);
  color: #f9fafb;
  box-shadow:
    inset 0 0 0 rgba(0, 0, 0, 0),
    0 14px 40px rgba(8, 47, 73, 0.9);
}

/* Each side of the "cube" */
.cta-button-3d span:nth-child(1) {
  transform: rotateX(0deg) translateZ(27px);
}
.cta-button-3d span:nth-child(2) {
  transform: rotateX(90deg) translateZ(27px);
}
.cta-button-3d span:nth-child(3) {
  transform: rotateX(180deg) translateZ(27px);
}
.cta-button-3d span:nth-child(4) {
  transform: rotateX(270deg) translateZ(27px);
}
// Optional enhancements:
// - Trigger rotation on click instead of hover
// - Tie animation to scroll or section visibility.