Glitch-Effekt auf Text / Bilder / SVG

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Lucas Bebbers Glitch ist ein super cooler Effekt. Es ist, als würde man Text auf einem Progressive-Scan-Monitor betrachten, der schon zu oft fallen gelassen wurde, und daher ist die Ausrichtung der Pixel in seltsam ungleichmäßigen Mengen in Zeit und Raum verschoben.

Es ist ein echter CSS-Trick, wenn es jemals einen gab! Es hat etwas gedauert, bis ich herausgefunden habe, wie er funktioniert, also dachte ich, ich erkläre ihn. Dann habe ich ihn auch für andere Arten von Inhalten funktionsfähig gemacht und ihn in eine Gruppe von Sass @mixins umgewandelt, um die Arbeit damit etwas zu erleichtern.

Siehe den Stift
CSS Glitched Text
von Chris Coyier (@chriscoyier)
auf CodePen.

Drei Kopien des Textes

Während der HTML ist nur

<div class="glitch" data-text="GLITCH">GLITCH</div> 

Drei Kopien davon werden über Pseudoelemente erstellt und liegen direkt übereinander.

.glitch {
  position: relative;
}
.glitch::before,
.glitch::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Erzeugung von drei eindeutigen Kopien, die einzeln gesteuert werden können

Ändern Sie die Kopien

Jede Kopie ist identisch, außer dass

  • Sie ist nach links oder rechts versetzt
  • Sie hat einen Lichteffekt in Form eines Textschattens

Zwischen der Verschiebung und dem Lichteffekt erhält sie dieses kaputte Gefühl.

.glitch::before {
  /* ... anything needed to make it identical */

  /* variation */
  left: 2px;
  text-shadow: -1px 0 red;
  
  /* important: opaque background masks the original */
  background: black;
}
.glitch::after {
  /* ... anything needed to make it identical */

  /* variation */
  left: -2px;
  text-shadow: -1px 0 blue;
  
  /* important: opaque background masks the original */
  background: black;
}

Jetzt sind die drei Kopien so

Beschneiden der Kopien

Man würde nur die oberste Kopie sehen, wenn sie so belassen wird. Wahrscheinlich die ::after-Version, es sei denn, man ändert sie mit z-index. Aber keine Angst, wir werden nur Teile der oberen, geänderten Kopien mit der clip Eigenschaft enthüllen. Diese Eigenschaft ist anscheinend veraltet zugunsten von clip-path, aber zum Zeitpunkt des Schreibens funktionierte nur clip für mich. Ich bin sicher, das wird sich mit der Zeit ändern, also müssen wir sie im Auge behalten, und vermutlich wird Autoprefixer das regeln.

Update! August 2019: Viel Zeit ist vergangen, und clip wird immer noch generell unterstützt, ist aber zugunsten des (besseren) clip-path veraltet. Die clip-Syntax kann das tun, was die inset()-Funktion für clip-path ist, also aktualisiere ich diesen Artikel, um diese zu verwenden. Es sieht nicht so aus, als ob Autoprefixer mit der Konversation umgeht.

Die Syntax für clip ist etwas seltsam. Für die vier Werte erwartet man vielleicht etwas wie oben/links/breite/höhe oder punkt-oben-links/punkt-unten-rechts. Aber stattdessen ist es wie Ränder und Polster: oben/rechts/unten/links

.glitch::before {
  clip: rect(44px, 450px, 56px, 0);
  /*
    Essentially a box from 0, 44px
    to 450px, 56px
  */

  /* clip-path: inset(); needs how far you want to push in from the edges instead */
}

Hier sind einige Beispiel-Clips auf diesen Ebenen, jetzt mit vollständig opaken Hintergründen (aber immer noch gedreht und mit zusätzlichen Farben, damit man sieht, was los ist)

Animieren Sie die Clips

Es stellt sich heraus, dass clip animiert werden kann, so dass sich diese ausgeschnittene Box mit der Zeit an eine neue Position bewegt, wenn sie dazu aufgefordert wird. Hier ist ein Beispiel für Keyframes

@keyframes noise-anim {
  0% {
    clip-path: inset(40% 0 61% 0);
  }
  20% {
    clip-path: inset(92% 0 1% 0);
  }
  40% {
    clip-path: inset(43% 0 1% 0);
  }
  60% {
    clip-path: inset(25% 0 58% 0);
  }
  80% {
    clip-path: inset(54% 0 7% 0);
  }
  100% {
    clip-path: inset(58% 0 43% 0);
  }
}

Beachten Sie, dass die linken und rechten Werte gleich bleiben, es sind nur die oberen und unteren Werte, die sich ändern. Und diese Werte sind ziemlich zufällig.

Das kann man mit Sass ziemlich einfach generieren, wie z.B.

@keyframes noise-anim {
  $steps: 20;
  @for $i from 0 through $steps {
    #{percentage($i*(1/$steps))} {
      $top: random(100);
      $bottom: random(101 - $top);
      clip-path: inset(#{$top}% 0 #{$bottom}% 0);
    }
  }
}

Da Sie zwei Sätze von zufälligen Clipping-Positionen haben möchten, würden Sie zwei Sätze dieser @keyframes erstellen und sie auf die Kopien anwenden

.glitch::before {
  ...

  animation: glitch-anim-1 2s infinite linear alternate-reverse;
}

.glitch::after {
  ...

  animation: glitch-anim-2 2s infinite linear alternate-reverse;
}

Dort legen wir die Geschwindigkeit fest (Anzahl der Keyframes beeinflusst auch die Geschwindigkeit) und lassen sie unendlich hin und her laufen.

Es macht ziemlich Spaß zuzusehen

Obwohl es wohl selbstverständlich sein sollte, dass ein wenig viel bewirkt.

Sass @mixins

Ich dachte, es wäre nett, wenn die Technik wiederverwendbarer wäre. Grundsätzlich ruft man einen @mixin mit Parametern auf, um den Effekt zu steuern und genau das zu bekommen, was man braucht.

.example-one {
  font-size: 100px;
  @include textGlitch("example-one", 17, white, black, red, blue, 450, 115);
}

Hier ist mein Ansatz dazu

/*
  (TEXT) PARAMS
  =================
  1. Namespace
  2. Intensity
  3. Text color
  4. Background color (flat)
  5. Highlight #1 color
  6. Highlight #2 color
  7. Width (px)
  8. Height (px)
*/

@mixin textGlitch($name, $intensity, $textColor, $background, $highlightColor1, $highlightColor2, $width, $height) {
  
  color: $textColor;
  position: relative;
  $steps: $intensity;
  
  // Ensure the @keyframes are generated at the root level
  @at-root {
    // We need two different ones
    @for $i from 1 through 2 {
      @keyframes #{$name}-anim-#{$i} {
        @for $i from 0 through $steps {
          $top: random(100);
          $bottom: random(101 - $top);
          #{percentage($i*(1/$steps))} {
            clip-path: inset(#{$top}% 0 #{$bottom}% 0);
          }
        }
      }
    }
  }
  &::before,
  &::after {
    content: attr(data-text);
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background: $background;
  }
  &::after {
    left: 2px;
    text-shadow: -1px 0 $highlightColor1;
    animation: #{$name}-anim-1 2s infinite linear alternate-reverse;
  }
  &::before {
    left: -2px;
    text-shadow: 2px 0 $highlightColor2; 
    animation: #{$name}-anim-2 3s infinite linear alternate-reverse;
  }
}

Es gibt tausend verschiedene Wege, dies anzugehen, dies ist nur einer. Es hängt ganz davon ab, wie viel der Mixin für Sie tun soll, wie viel Anpassbarkeit Sie wollen oder brauchen, was Sie im HTML belassen wollen, etc.

Ich habe auch zwei weitere Mixins erstellt, einen zum Anwenden dieses Effekts auf Bilder und einen für Inline-SVG. Sie sind unterschiedlich, weil sie keine Pseudoelemente zur Erstellung der Kopien verwenden, die Farbgebung anders erfolgt, die Positionierung anders ist, usw. Hier sind alle drei zusammen.

Und eine Demo

Siehe den Stift
CSS Glitched Text
von Chris Coyier (@chriscoyier)
auf CodePen.