Back to CSS Buttons Brutalist Glitch CSS + JS
Share
HTML
<button class="btn-glitch" data-text="SUBMIT">
  <span class="btn-glitch-fill" aria-hidden="true"></span>
  <span class="btn-glitch-label">SUBMIT</span>
</button>
CSS
.btn-glitch {
  position: relative;
  padding: 14px 36px;
  border: 2px solid #fff;
  background: transparent;
  color: #fff;
  font-family: "Arial Narrow", Arial, sans-serif;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
  cursor: pointer;
  overflow: hidden;
  user-select: none;
  transition: color 0.1s;
}
.btn-glitch-fill {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.15s cubic-bezier(.77,0,.18,1);
}
.btn-glitch-label { position: relative; z-index: 1; }
.btn-glitch:hover { color: #0c0c0f; }
.btn-glitch:hover .btn-glitch-fill { transform: scaleX(1); }
.btn-glitch.is-glitching { animation: btn-glitch-shake 0.4s cubic-bezier(.36,.07,.19,.97) both; }
.btn-glitch.is-glitching::before,
.btn-glitch.is-glitching::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "Arial Narrow", Arial, sans-serif;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 3px;
  overflow: hidden;
}
.btn-glitch.is-glitching::before {
  color: #ff0040;
  clip-path: polygon(0 0, 100% 0, 100% 45%, 0 45%);
  animation: btn-glitch-l1 0.4s steps(2) forwards;
}
.btn-glitch.is-glitching::after {
  color: #00fff9;
  clip-path: polygon(0 55%, 100% 55%, 100% 100%, 0 100%);
  animation: btn-glitch-l2 0.4s steps(2) forwards;
}
@keyframes btn-glitch-shake {
  0%,100% { transform: translate(0); }
  20% { transform: translate(-3px, 1px) skewX(-3deg); }
  40% { transform: translate(3px, -1px) skewX(3deg); }
  60% { transform: translate(-2px, 2px); }
  80% { transform: translate(2px, -2px); }
}
@keyframes btn-glitch-l1 {
  0% { transform: translate(-4px, -2px); opacity: 1; }
  50% { transform: translate(4px, 2px); opacity: 0.8; }
  100% { transform: translate(0); opacity: 0; }
}
@keyframes btn-glitch-l2 {
  0% { transform: translate(4px, 2px); opacity: 1; }
  50% { transform: translate(-4px, -2px); opacity: 0.8; }
  100% { transform: translate(0); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .btn-glitch.is-glitching { animation: none; }
  .btn-glitch.is-glitching::before,
  .btn-glitch.is-glitching::after { animation: none; opacity: 0; }
}
JS
document.querySelectorAll('.btn-glitch').forEach(function (btn) {
  btn.addEventListener('click', function () {
    btn.classList.add('is-glitching');
    setTimeout(function () { btn.classList.remove('is-glitching'); }, 420);
  });
});