<div class="glitch" data-text="GLITCH">GLITCH</div>
.glitch { position: relative; } .glitch::before, .glitch::after { content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
text-shadow
. .glitch::before { /* ... , , */ /* */ left: 2px; text-shadow: -1px 0 red; /* : */ background: black; } .glitch::after { /* ... , , */ /* */ left: -2px; text-shadow: -1px 0 blue; /* : */ background: black; }
::after
, unless you changed the z-index
. But this is not important, since we will alternately show parts of all three copies using the clip
property. At the moment, this property is already considered obsolete, it should be replaced by the clip-path
, but at the time of writing this article, the clip
property worked better. Of course, this will change over time, so sometimes you have to look at the situation. In which case, they will be easy to change, for example, using Autoprefixer .clip
rather strange syntax. It requires four values, it would be logical to assume that these are the coordinates of the upper left corner and the length with the width, or the coordinates of the upper left and lower right corners, but instead the numbers mean padding, as in the properties margin
or padding
( top/right/bottom/left
). .glitch::before { clip: rect(44px, 450px, 56px, 0); /* 0, 44px 450px, 56px */ }
clip
property, you can use CSS animations by changing the position of the cropping rectangle. Here is an example of such an animation: @keyframes glitch-anim { 0% { clip: rect(70px, 450px, 76px, 0); } 20% { clip: rect(29px, 450px, 16px, 0); } 40% { clip: rect(76px, 450px, 3px, 0); } 60% { clip: rect(42px, 450px, 78px, 0); } 80% { clip: rect(15px, 450px, 13px, 0); } 100% { clip: rect(53px, 450px, 5px, 0); } }
@keyframes glitch-anim { $steps: 10; @for $i from 0 through $steps { #{percentage($i*(1/$steps))} { clip: rect(random(100)+px, 9999px, random(100)+px, 0); } } }
.glitch::before { ... animation: glitch-anim-1 2s infinite linear alternate-reverse; } .glitch::after { ... animation: glitch-anim-2 2s infinite linear alternate-reverse; }
.example-one { font-size: 100px; @include textGlitch("example-one", 17, white, black, red, blue, 450, 115); }
/* (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 { #{percentage($i*(1/$steps))} { clip: rect( random($height)+px, $width+px, random($height)+px, 0 ); } } } } } &:before, &:after { content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%; background: $background; clip: rect(0, 0, 0, 0); } &: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; } }
Source: https://habr.com/ru/post/236263/
All Articles