diff --git a/content/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough.md b/content/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough.md new file mode 100644 index 0000000..ddca193 --- /dev/null +++ b/content/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough.md @@ -0,0 +1,1133 @@ +--- +title: Cyberpunk-Style Glitch Text Walkthrough +date: 2024-07-23T18:35:26.560Z +lastmod: 2024-07-24T20:43:47.560Z +image: /images/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough/Peek 2024-07-24 22-34.gif +description: Discover how to create a cyberpunk-style glitch text effect using pure CSS. This guide covers text layering, clip-paths, and animations for a dynamic, futuristic look. Dive in and start glitching! +tags: + - Web-Dev + - CSS + - Programming +draft: false +slug: cyberpunk-style-glitch-text-walkthrough +--- + + + +# The Effect + +{{< details "The Effect (What we are going to make)">}} +
+
+

近設計

+
+{{< /details >}} + +## Walkthrough + +This came out of a 24-hour work sprint to replicate some sophisticated video VFX in to make it more flexible. + +There's a lot of pieces that go into an effect like this. What follows is an outline of the animations and VFX concepts, all in pure css :) + +**Core principles:** + +* Keep the text legible most of the time +* Don't throw too many glitches in per second. Give it space to breathe +* Whitespace never hurt anyone +* Blurs & glows lend a feeling of realism in dark environments (queue neon) + +--- + +{{< toc >}} + +--- + +## Layers + +Create multiple layers to play with. For this example I'll use `::before` & `::after` elements, but this could just as easily be multiple div's overlapped, or whatever. + +

EXAMPLE

+ +{{< details "Example layers CSS:" >}} + +```css {linenos=true} +.layers { + position: relative; +} + +.layers::before, +.layers::after { + content: attr(data-text); + position: absolute; + width: 110%; + z-index: -1; +} + +.layers::before { + top: 10px; + left: 15px; + color: #e0287d; +} + +.layers::after { + top: 5px; + left: -10px; + color: #1bc7fb; +} +``` + +{{< /details >}} + +## Paths + +Build out a set of clip-paths (I wrote up a generator util for this project) + +**Example Path:** + +
+ +**Over Text:** + +

EXAMPLE

+ +{{< details "Example paths CSS:" >}} + +```css {linenos=true} +.single-path { + clip-path: polygon( + 0% 12%, + 53% 12%, + 53% 26%, + 25% 26%, + 25% 86%, + 31% 86%, + 31% 0%, + 53% 0%, + 53% 84%, + 92% 84%, + 92% 82%, + 70% 82%, + 70% 29%, + 78% 29%, + 78% 65%, + 69% 65%, + 69% 66%, + 77% 66%, + 77% 45%, + 85% 45%, + 85% 26%, + 97% 26%, + 97% 28%, + 84% 28%, + 84% 34%, + 54% 34%, + 54% 89%, + 30% 89%, + 30% 58%, + 83% 58%, + 83% 5%, + 68% 5%, + 68% 36%, + 62% 36%, + 62% 1%, + 12% 1%, + 12% 34%, + 60% 34%, + 60% 57%, + 98% 57%, + 98% 83%, + 1% 83%, + 1% 53%, + 91% 53%, + 91% 84%, + 8% 84%, + 8% 83%, + 4% 83% + ); +} + +.paths { + animation: paths 5s step-end infinite; +} + +@keyframes paths { + 0% { + clip-path: polygon( + 0% 43%, + 83% 43%, + 83% 22%, + 23% 22%, + 23% 24%, + 91% 24%, + 91% 26%, + 18% 26%, + 18% 83%, + 29% 83%, + 29% 17%, + 41% 17%, + 41% 39%, + 18% 39%, + 18% 82%, + 54% 82%, + 54% 88%, + 19% 88%, + 19% 4%, + 39% 4%, + 39% 14%, + 76% 14%, + 76% 52%, + 23% 52%, + 23% 35%, + 19% 35%, + 19% 8%, + 36% 8%, + 36% 31%, + 73% 31%, + 73% 16%, + 1% 16%, + 1% 56%, + 50% 56%, + 50% 8% + ); + } + + 5% { + clip-path: polygon( + 0% 29%, + 44% 29%, + 44% 83%, + 94% 83%, + 94% 56%, + 11% 56%, + 11% 64%, + 94% 64%, + 94% 70%, + 88% 70%, + 88% 32%, + 18% 32%, + 18% 96%, + 10% 96%, + 10% 62%, + 9% 62%, + 9% 84%, + 68% 84%, + 68% 50%, + 52% 50%, + 52% 55%, + 35% 55%, + 35% 87%, + 25% 87%, + 25% 39%, + 15% 39%, + 15% 88%, + 52% 88% + ); + } + + 30% { + clip-path: polygon( + 0% 53%, + 93% 53%, + 93% 62%, + 68% 62%, + 68% 37%, + 97% 37%, + 97% 89%, + 13% 89%, + 13% 45%, + 51% 45%, + 51% 88%, + 17% 88%, + 17% 54%, + 81% 54%, + 81% 75%, + 79% 75%, + 79% 76%, + 38% 76%, + 38% 28%, + 61% 28%, + 61% 12%, + 55% 12%, + 55% 62%, + 68% 62%, + 68% 51%, + 0% 51%, + 0% 92%, + 63% 92%, + 63% 4%, + 65% 4% + ); + } + + 45% { + clip-path: polygon( + 0% 33%, + 2% 33%, + 2% 69%, + 58% 69%, + 58% 94%, + 55% 94%, + 55% 25%, + 33% 25%, + 33% 85%, + 16% 85%, + 16% 19%, + 5% 19%, + 5% 20%, + 79% 20%, + 79% 96%, + 93% 96%, + 93% 50%, + 5% 50%, + 5% 74%, + 55% 74%, + 55% 57%, + 96% 57%, + 96% 59%, + 87% 59%, + 87% 65%, + 82% 65%, + 82% 39%, + 63% 39%, + 63% 92%, + 4% 92%, + 4% 36%, + 24% 36%, + 24% 70%, + 1% 70%, + 1% 43%, + 15% 43%, + 15% 28%, + 23% 28%, + 23% 71%, + 90% 71%, + 90% 86%, + 97% 86%, + 97% 1%, + 60% 1%, + 60% 67%, + 71% 67%, + 71% 91%, + 17% 91%, + 17% 14%, + 39% 14%, + 39% 30%, + 58% 30%, + 58% 11%, + 52% 11%, + 52% 83%, + 68% 83% + ); + } + + 76% { + clip-path: polygon( + 0% 26%, + 15% 26%, + 15% 73%, + 72% 73%, + 72% 70%, + 77% 70%, + 77% 75%, + 8% 75%, + 8% 42%, + 4% 42%, + 4% 61%, + 17% 61%, + 17% 12%, + 26% 12%, + 26% 63%, + 73% 63%, + 73% 43%, + 90% 43%, + 90% 67%, + 50% 67%, + 50% 41%, + 42% 41%, + 42% 46%, + 50% 46%, + 50% 84%, + 96% 84%, + 96% 78%, + 49% 78%, + 49% 25%, + 63% 25%, + 63% 14% + ); + } + + 90% { + clip-path: polygon( + 0% 41%, + 13% 41%, + 13% 6%, + 87% 6%, + 87% 93%, + 10% 93%, + 10% 13%, + 89% 13%, + 89% 6%, + 3% 6%, + 3% 8%, + 16% 8%, + 16% 79%, + 0% 79%, + 0% 99%, + 92% 99%, + 92% 90%, + 5% 90%, + 5% 60%, + 0% 60%, + 0% 48%, + 89% 48%, + 89% 13%, + 80% 13%, + 80% 43%, + 95% 43%, + 95% 19%, + 80% 19%, + 80% 85%, + 38% 85%, + 38% 62% + ); + } + + 1%, + 7%, + 33%, + 47%, + 78%, + 93% { + clip-path: none; + } +} +``` + +{{< /details >}} + +## Movement + +Create a stepping movement animation, so that the layers above can appear in different places as the other layers of the animation happen. + +It's best to make this timing somewhat erratic. + +
+ +{{< details "Example movement CSS:" >}} + +```css {linenos=true} +.movement { + /* Normally this position would be + absolute & on the layers, set to relative + here so we can see it on the div */ + position: relative; + animation: movement 8s step-end infinite; +} + +@keyframes movement { + 0% { + top: 0px; + left: -20px; + } + + 15% { + top: 10px; + left: 10px; + } + + 60% { + top: 5px; + left: -10px; + } + + 75% { + top: -5px; + left: 20px; + } + + 100% { + top: 10px; + left: 5px; + } +} +``` + +{{< /details >}} + +## Opacity + +Create a similar animation for opacity, so that the layers can appear/disappear. This will get layered with the movement to create the appearance of the layers popping in and out in different places. + +There's an art to getting this transition to work without making the user feel motion sickness. Take some time getting it right! + +
+ +{{< details "Example opacity CSS:" >}} + +```css {linenos=true} +.opacity { + animation: opacity 5s step-end infinite; +} + +@keyframes opacity { + 0% { + opacity: 0.1; + } + + 5% { + opacity: 0.7; + } + + 30% { + opacity: 0.4; + } + + 45% { + opacity: 0.6; + } + + 76% { + opacity: 0.4; + } + + 90% { + opacity: 0.8; + } + + 1%, + 7%, + 33%, + 47%, + 78%, + 93% { + opacity: 0; + } +} +``` + +{{< /details >}} + +## Font + +The next layer is changes to the font directly. These could be any properties, but we'll stick to font-weight and color. + +

EXAMPLE

+ +{{< details "Example font CSS:" >}} + +```css {linenos=true} +.font { + animation: font 7s step-end infinite; +} + +@keyframes font { + 0% { + font-weight: 100; + color: #e0287d; + filter: blur(3px); + } + + 20% { + font-weight: 500; + color: #fff; + filter: blur(0); + } + + 50% { + font-weight: 300; + color: #1bc7fb; + filter: blur(2px); + } + + 60% { + font-weight: 700; + color: #fff; + filter: blur(0); + } + + 90% { + font-weight: 500; + color: #e0287d; + filter: blur(6px); + } +} +``` + +{{< /details >}} + +## Combined Animation Layers + +Note that some of the animations have sync'd timing, and some don't. + +I try to sync the paths & opacity animations, so that it looks like the background layers are really a part of the main text that's glitching off. + +Then I try to separately sync the color/text/filter other effects, and keep the movement separate completely. This gives the whole thing the appearance of a lot more effects than are actually happening, because of the different combinations. + +

+ EXAMPLE +

+ +{{< details "Example CSS:" >}} + +```css {linenos=true} +.glitch span { + animation: paths 5s step-end infinite; +} + +.glitch::before { + animation: paths 5s step-end infinite, opacity 5s step-end infinite, + font 8s step-end infinite, movement 10s step-end infinite; +} + +.glitch::after { + animation: paths 5s step-end infinite, opacity 5s step-end infinite, + font 7s step-end infinite, movement 8s step-end infinite; +} +``` + +{{< /details >}} + +## Environment + +For good measure, it should live in the right language & context :) + +
+
+

近設計

+
+ +{{< figcaption >}} +background image from: [unsplash.com](https://images.unsplash.com/photo-1602136773736-34d445b989cb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1200&q=80) +{{< /figcaption >}} + +{{< details "Example environment CSS:" >}} + +```css {linenos=true} +.hero-container { + position: relative; + padding: 200px 0; + text-align: center; +} + +.environment { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + opacity: 0.5; + filter: blur(5px); + background: url(https://images.unsplash.com/photo-1602136773736-34d445b989cb?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1200&q=80) + center no-repeat; + background-size: cover; +} +``` + +{{< /details >}} + +{{< details "Example HTML layout:">}} + +```html {linenos=true} +
+
+

近設計

+
+``` + +{{< /details >}} + +## Conclusion + +With this walkthrough, you should now have a basic understanding of how to create glitch effects using pure CSS. By layering text, applying clip-paths, and animating movement, opacity, and font properties, you can achieve a striking cyberpunk-style effect. Experiment with these techniques to customize and enhance your web projects with a unique, futuristic flair. Dive in and start glitching! diff --git a/static/images/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough/Peek 2024-07-24 22-34.gif b/static/images/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough/Peek 2024-07-24 22-34.gif new file mode 100644 index 0000000..2ab2c12 Binary files /dev/null and b/static/images/blog/2024-07-23-cyberpunk-style-glitch-text-walkthrough/Peek 2024-07-24 22-34.gif differ