AI CSS Animations

Liquid Button

A button half full of liquid, with two waves rolling through it in opposite directions while the surface bobs. Each wave is an inline SVG path twice the button width, sliding by half.

Also known as: css liquid button animation, water wave button, wave button css.

HTML

<button class="btn-liquid" type="button">
  <svg class="btn-liquid-wave" viewBox="0 0 240 40" preserveAspectRatio="none" aria-hidden="true"><path d="M0 20 Q15 6 30 20 T60 20 T90 20 T120 20 T150 20 T180 20 T210 20 T240 20 V40 H0z"/></svg>
  <svg class="btn-liquid-wave" viewBox="0 0 240 40" preserveAspectRatio="none" aria-hidden="true"><path d="M0 20 Q15 6 30 20 T60 20 T90 20 T120 20 T150 20 T180 20 T210 20 T240 20 V40 H0z"/></svg>
  Stay hydrated
</button>

CSS

.btn-liquid {
  --c: var(--btn-color, #3b82f6);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0.75em 1.6em;
  border: 0;
  border-radius: 0.6em;
  font: 600 var(--btn-size, 18px)/1.1 system-ui, sans-serif;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 11.5em;
  height: 3.2em;
  padding: 0;
  border: 2px solid var(--c);
  border-radius: 2em;
  background: color-mix(in srgb, var(--c) 22%, #0a0f1d);
  color: #fff;
  text-shadow: 0 0.05em 0.25em color-mix(in srgb, var(--c) 40%, #000);
  transition: transform 0.2s ease;}
.btn-liquid-wave {
  position: absolute;
  bottom: -0.3em;
  left: 0;
  z-index: -1;
  width: 200%;
  height: calc(80% + 0.3em);
  fill: var(--c);
  animation:
    btn-liquid-roll 2.8s linear infinite,
    btn-liquid-bob 2.2s ease-in-out infinite alternate;
}
.btn-liquid-wave:first-child {
  height: calc(96% + 0.3em);
  fill: color-mix(in srgb, var(--c) 45%, transparent);
  animation-duration: 4.2s, 2.8s;
  animation-direction: reverse, alternate;
}
.btn-liquid:active { transform: scale(0.97); }
@keyframes btn-liquid-roll {
  to { transform: translateX(-50%); }
}
@keyframes btn-liquid-bob {
  from { translate: 0 0.12em; }
  to   { translate: 0 -0.12em; }
}

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

Customizing this snippet

  • Color: set --btn-color on the element or a parent. Currently previewing #3b82f6.
  • Base size: set --btn-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 18px.
  • 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 buttons