AI CSS Animations

Liquid Wave Fill Button

Liquid rises and settles just under the brim, where two wavy surfaces keep rolling past each other while you hover. The waves are tiled radial gradients, so there is no SVG.

Also known as: liquid button hover, wave fill button, water fill button.

HTML

<button class="hfx-liquid-wave-fill">Try it free</button>

CSS

.hfx-liquid-wave-fill {
  --c: var(--hfx-color, #3b82f6);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.75em 1.75em;
  border-radius: 0.5em;
  font: 600 var(--hfx-size, 16px)/1.2 system-ui, sans-serif;
  white-space: nowrap;
  cursor: pointer;
  border: 2px solid var(--c);
  background: transparent;
  color: var(--c);
  transition: color 0.3s ease 0.25s;
}
/* one wave = a crest arc above the midline, a trough cut below it, solid under both */
.hfx-liquid-wave-fill::before,
.hfx-liquid-wave-fill::after {
  content: "";
  position: absolute;
  inset: 0.16em -2px -2px;
  z-index: -1;
  background:
    radial-gradient(0.65em at 0.45em 0.65em, var(--tint) 97%, transparent) 0 0 / 1.8em 0.18em repeat-x,
    radial-gradient(0.65em at 1.35em -0.47em, transparent 97%, var(--tint)) 0 0.18em / 1.8em 0.18em repeat-x,
    linear-gradient(var(--tint) 0 0) 0 0.36em / 100% 100% no-repeat;
  transform: translateY(104%);
  transition: transform 0.7s cubic-bezier(0.3, 0.6, 0.3, 1);
}
.hfx-liquid-wave-fill::before { --tint: var(--c); }
.hfx-liquid-wave-fill::after {
  --tint: color-mix(in srgb, var(--c) 40%, transparent);
  top: 0;
  z-index: -2;
  background-position: 0.9em 0, 0.9em 0.18em, 0 0.36em;
}
.hfx-liquid-wave-fill:is(:hover, :focus-visible) { color: #fff; }
.hfx-liquid-wave-fill:is(:hover, :focus-visible)::before,
.hfx-liquid-wave-fill:is(:hover, :focus-visible)::after {
  transform: translateY(0);
  animation: hfx-liquid-wave-fill-flow 1.1s linear infinite;
}
.hfx-liquid-wave-fill:is(:hover, :focus-visible)::after {
  transition-delay: 0.05s;
  animation-name: hfx-liquid-wave-fill-back;
  animation-duration: 1.6s;
}
@keyframes hfx-liquid-wave-fill-flow {
  to { background-position: 1.8em 0, 1.8em 0.18em, 0 0.36em; }
}
@keyframes hfx-liquid-wave-fill-back {
  to { background-position: -0.9em 0, -0.9em 0.18em, 0 0.36em; }
}

@media (prefers-reduced-motion: reduce) {
  .hfx-liquid-wave-fill, .hfx-liquid-wave-fill *, .hfx-liquid-wave-fill::before, .hfx-liquid-wave-fill::after, .hfx-liquid-wave-fill *::before, .hfx-liquid-wave-fill *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --hfx-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --hfx-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 16px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar hover effects