loading...
Cover image for Front-End Journal #02 — CSS Glitch Effects

Front-End Journal #02 — CSS Glitch Effects

pcosvaz profile image Paula Vaz ・3 min read

This time, after a chat with a friend about a website that uses beautiful glitch effects, I decided to try to play with it aiming to explore how to create similar results utilizing only HTML and CSS. It’s a pleasure to share my journey with you.

Fist of all, our HTML couldn’t be more simple, it’s just an h1:

<body>
  <h1>we are not equally present in all parts of ourselves</h1>
</body>

The key point

These days, I discovered how to play with pseudo-elements and this idea is particularly helpful to create our effect.

@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@900&display=swap');
$width: 800px;
$height: 280px;

body {
  background-color: black;
  color: white;
  font-family: 'Noto Sans JP', sans-serif;
  font-size: 30px;
  letter-spacing: 1px;
}

h1 {
  position: absolute;
  top: 50%;
  left: 50%;
  text-align: center;
  transform: translate(-50%, -50%);
  width: $width;
  height: $height;

  &::before,
  &::after {
    content: 'we are not equally present in all parts of ourselves';
    display: block;
    position: absolute;
    top: 0;
  }

  &::before {
    color: rgba(122, 180, 255, 1);
    z-index: -1;
  }

  &::after {
    color: rgba(123, 91, 217, 1);
    z-index: -2;
  }
}

In lines 1 to 20, I just did the base style of our body and our h1 (positioning, font style, background color, etc).

The logic between lines 22 and 39 is our essential point. I created two pseudo-elements: :before and :after. These two elements are two copies of the h1, and the rules display: block, position: absolute and top: 0 guarantees the correct positioning perfectly behind the principal h1. Finally, I modified the text color of each pseudo-element.

Glitch Effect

I produced the glitch effect using the idea of clip.
The clip CSS property defines a visible portion of an element.

Formal syntax:

clip: rect(<top> <right> <bottom> <left>);

The and values are offsets from the inside top border edge of the box, while and are offsets from the inside left border edge of the box — that is, the extent of the padding box.

It’s important to say here that I used clip property because I just needed a simple rect, but if you want to do more complex clips, you can check the newer clip-path property instead.

To obtain the glitch effect, I simply created an animation, which is a for loop (this is why I used SCSS). In each interaction, I randomly selected two values and used them to create the clip. If you want to understand a little bit more about CSS animations, click here.

@keyframes glitch {
  $steps: 40;
  @for $step from 0 through $steps {
    #{percentage($step / $steps)} {
      $top: random($height);
      $bottom: random($height);
      @while $bottom < $top {
        $bottom: random($height);
      }
      clip: rect(#{$top}px $width #{$bottom}px 0);
    }
  }
}

Lastly, I attached the animation to the hover state of my pseudo-elements and added de left property so my pseudo-elements are displayed just when they’re on the hover state.

h1 {
  &:hover {
    &::before {
      animation: glitch 3s ease reverse infinite;
      left: 5px;
    }

    &::after {
      animation: glitch 3s ease infinite;
      left: -5px;
    }
  }
}

The result

You can see the complete code here. I hope you enjoyed it! ;)

Discussion

pic
Editor guide