This article will use pure CSS to take you step by step to implement such a sci-fi character jumping background animation. A character rain animation similar to this:
Or something like this:
![CodePen Home
Matrix digital rain (animated version) By yuanchuan](https://user-images.githubusercontent.com/8554143/127498966-dd59fc85-49a6-4741-859d-2b9b65757563.gif)
It is very colorful when applied on the background of some similar scientific and technological themes.
Vertical text
The first step is to realize the vertical arrangement of the text:
This step is very simple, and there are many possible methods. Here I will briefly list it:
writing-mode
to control the text arrangement. You canwriting-mode: vertical-lr
etc., but for numbers and English, it will be rotated 90° to display:
<p>1234567890ABC</p>
<p>中文或其他字符ォヶ</p>
p {
writing-mode: vertical-lr;
}
Of course, in this case, the display of English characters does not meet our needs.
- Control the width of the container, and control that each line can only display 1 Chinese character.
This method is the easiest and most convenient method, but due to the particularity of English, to allow continuous long strings to wrap naturally, we also need to cooperate with word-break: break-all
:
p {
width: 12px;
font-size: 10px;
word-break: break-all;
}
The effect is as follows to meet the demand:
Use CSS to achieve random string selection
In order to make our effect more natural. The selection of characters in each line is preferably random.
But it is too difficult for CSS to randomly generate characters in each line. So here we invite the CSS preprocessor SASS/LESS.
And because less likely to use CSS to a single label, such as <p>
label insert characters, so we have to show character in the label on each <p>
pseudo-elements elements ::before
of content
them.
We can set up a set of strings in advance, and then use SASS function to randomly generate content
each element. The pseudo code is as follows:
<div>
<p></p>
<p></p>
<p></p>
</div>
$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);
@function randomChar() {
$r: random($length);
@return str-slice($str, $r, $r);
}
@function randomChars($number) {
$value: '';
@if $number > 0 {
@for $i from 1 through $number {
$value: $value + randomChar();
}
}
@return $value;
}
p:nth-child(1)::before {
content: randomChars(25);
}
p:nth-child(2)::before {
content: randomChars(25);
}
p:nth-child(3)::before {
content: randomChars(25);
}
Briefly explain the above code:
$str
defines a random string,$length
represents the length of the string- randomChar () is utilized in the SASS
random()
method, each time selecting a random 0 -$length
integers, denoted$r
, reuse of the SASSstr-slice
method, each from$str
select a subscript for$r
random character - randomChars() is to call the randomChar() method
$str
to randomly generate a string of strings from 061075fc18010e, the length of which is the passed parameter$number
In this way, the characters in each column are different each time:
Of course, I think the above method is not the best. Thecontent
of the CSS pseudo-element supports character encoding. For example,content: '\3066';
will be rendered into the characterて
. In this way, by setting the character interval and cooperating with the SASS function, the randomness can be better generated. Characters, but I tried for a long time, the final product generated by SASS function will\
and3066
, which cannot be converted into characters through character encoding, and finally give up...
Use CSS to achieve typing effects
OK, continue, next we are going to use CSS to achieve the typing effect, that is, let the characters appear one by one, like this:
This is achieved with the help of the steps
feature of animation, which is a frame-by-frame animation.
From left to right and from top to bottom, the principle is the same. Taking from left to right as an example, suppose we have 26 English characters, and we know the length of the string composed of 26 English characters, then we only need to set For an animation, let its width change from 0 - 100%
through 26 frames. With overflow: hidden
, each frame of steps can display a character.
Of course, some tricks are needed here. How do we know the length of the string through the number of characters?
Key points: adopts the feature of monospaced fonts and ch
unit CSS.
If you don’t know what a monospace font family is, you can read my article- "Fonts you should know font-family" .
In CSS, the ch
represents the width of the number "0". If the font happens to be a monospace font, that is, the width of each character is the same, then ch
can become the width of each English character, then 26ch
is actually the length of the entire string.
Using this feature, in conjunction with the animation steps
, we can easily use CSS to achieve typing animation effects:
<h1>Pure CSS Typing animation.</h1>
h1 {
font-family: monospace;
width: 26ch;
white-space: nowrap;
overflow: hidden;
animation: typing 3s steps(26, end);
}
@keyframes typing {
0{
width: 0;
}
100% {
width: 26ch;
}
}
You can get the following results:
You can click here for the complete code:
CodePen Demo - Pure CSS to achieve text input effect
Transform into vertical typing effect
Next, we will use the above techniques to transform it. Transform a horizontal typing effect into a vertical typing effect.
The core pseudo code is as follows:
<div>
<p></p>
<p></p>
<p></p>
</div>
$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);
@function randomChar() {
$r: random($length);
@return str-slice($str, $r, $r);
}
@function randomChars($number) {
$value: '';
@if $number > 0 {
@for $i from 1 through $number {
$value: $value + randomChar();
}
}
@return $value;
}
p {
width: 12px;
font-size: 10px;
word-break: break-all;
}
p::before {
content: randomChars(20);
color: #fff;
animation: typing 4s steps(20, end) infinite;
}
@keyframes typing {
0% {
height: 0;
}
25% {
height: 100%;
}
100% {
height: 100%;
}
}
In this way, we have achieved the vertical typing effect:
Of course, this looks more uniform, lacking a certain degree of randomness, and also lacking a certain sense of beauty.
Based on this, we carry out two transformations:
- Based on the animation duration
animation-time
and the animation delayanimation-delay
, increase the random within a certain range - At the end or in the process of each animation, replace the pseudo-element
content
, that is, regenerate a copy ofcontent
This can be achieved very easily with the help of SASS. The core SASS code is as follows:
$n: 3;
$animationTime: 3;
$perColumnNums: 20;
@for $i from 0 through $n {
$content: randomChars($perColumnNums);
$contentNext: randomChars($perColumnNums);
$delay: random($n);
$randomAnimationTine: #{$animationTime + random(20) / 10 - 1}s;
p:nth-child(#{$i})::before {
content: $content;
color: #fff;
animation: typing-#{$i} $randomAnimationTine steps(20, end) #{$delay * 0.1s * -1} infinite;
}
@keyframes typing-#{$i} {
0% {
height: 0;
}
25% {
height: 100%;
}
100% {
height: 100%;
content: $contentNext;
}
}
}
Looking at the effect, there has been a good improvement:
Of course, there are actually some differences in the above-mentioned transition from horizontal typing to vertical typing. Under the existing vertical arrangement rules, the actual vertical height cannot be obtained by ch matching the number of characters. So there are certain trade-offs here. Actually slowing down the animation, the appearance of no word is not necessarily complete.
Of course, it is almost imperceptible under the fast animation effect.
Increase light and shadow and transparency changes
The last step is to increase the changes in light, shadow and transparency.
The best effect is to keep the brightness of each newly-appearing character at its maximum, while the brightness of the characters that have already appeared slowly decreases.
But because we can't finely control every character here, we can only control every line of characters, so we must find another way to achieve it.
The final way is to borrow another pseudo-element to synchronize the mask to achieve the final effect. Let's take a step by step look at the process.
Add bright colors and highlights to text
The first step is to add bright colors and highlights to the text. This is very easy. It is to select a bright color under a black background and make the text glow text-shadow
p::before {
color: rgb(179, 255, 199);
text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 5px currentColor, 0 0 10px currentColor;
}
Take a look at the effect. On the left is a white character, in the middle is to change the character color, and on the right is the effect of changing the font color and adding a font shadow:
Add sync mask to text
Next, during the progress of the text animation, a black to transparent mask is added synchronously to try to restore the brightness of each newly-appearing character, while the brightness of the characters that have already appeared slowly decreases.
The schematic diagram of this effect is roughly like this, here I separate the text layer and the mask layer, and the background color is changed from black to white, which is easy to understand:
The pseudo code of the approximate mask layer is as follows, using another pseudo element of the element:
p::after {
content: '';
background: linear-gradient(rgba(0, 0, 0, .9), transparent 75%, transparent);
background-size: 100% 220%;
background-repeat: no-repeat;
animation: mask 4s infinite linear;
}
@keyframes mask {
0% {
background-position: 0 220%;
}
30% {
background-position: 0 0%;
}
100% {
background-position: 0 0%;
}
}
Well, the final result together is probably like this:
By adjusting @keyframes mask
, you can get a different character fade effect, which requires certain debugging.
Complete code and effect
OK, the main steps are disassembled, and finally the complete code is applied, using the Pug template engine and SASS grammar.
The complete code adds up to no more than 100 lines.
.g-container
-for(var i=0; i<50; i++)
p
@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@200&display=swap');
$str: 'ぁぃぅぇぉかきくけこんさしすせそた◁▣▤▥▦▧♂♀♥☻►◄▧▨♦ちつってとゐなにぬねのはひふへほゑまみむめもゃゅょゎをァィゥヴェォカヵキクケヶコサシスセソタチツッテトヰンナニヌネノハヒフヘホヱマミムメモャュョヮヲㄅㄉㄓㄚㄞㄢㄦㄆㄊㄍㄐㄔㄗㄧㄛㄟㄣㄇㄋㄎㄑㄕㄘㄨㄜㄠㄤㄈㄏㄒㄖㄙㄩㄝㄡㄥabcdefghigklmnopqrstuvwxyz123456789%@#$<>^&*_+';
$length: str-length($str);
$n: 50;
$animationTime: 4;
$perColumnNums: 25;
@function randomChar() {
$r: random($length);
@return str-slice($str, $r, $r);
}
@function randomChars($number) {
$value: '';
@if $number > 0 {
@for $i from 1 through $number {
$value: $value + randomChar();
}
}
@return $value;
}
body, html {
width: 100%;
height: 100%;
background: #000;
display: flex;
overflow: hidden;
}
.g-container {
width: 100vw;
display: flex;
justify-content: space-between;
flex-wrap: nowrap;
flex-direction: row;
font-family: 'Inconsolata', monospace, sans-serif;
}
p {
position: relative;
width: 5vh;
height: 100vh;
text-align: center;
font-size: 5vh;
word-break: break-all;
white-space: pre-wrap;
&::before,
&::after {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100%;
overflow: hidden;
}
}
@for $i from 0 through $n {
$content: randomChars($perColumnNums);
$contentNext: randomChars($perColumnNums);
$delay: random($n);
$randomAnimationTine: #{$animationTime + random(20) / 10 - 1}s;
p:nth-child(#{$i})::before {
content: $content;
color: rgb(179, 255, 199);
text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 5px currentColor, 0 0 10px currentColor;
animation: typing-#{$i} $randomAnimationTine steps(20, end) #{$delay * 0.1s * -1} infinite;
z-index: 1;
}
p:nth-child(#{$i})::after {
$alpha: random(40) / 100 + 0.6;
content: '';
background: linear-gradient(rgba(0, 0, 0, $alpha), rgba(0, 0, 0, $alpha), rgba(0, 0, 0, $alpha), transparent 75%, transparent);
background-size: 100% 220%;
background-repeat: no-repeat;
animation: mask $randomAnimationTine infinite #{($delay - 2) * 0.1s * -1} linear;
z-index: 2;
}
@keyframes typing-#{$i} {
0% {
height: 0;
}
25% {
height: 100%;
}
100% {
height: 100%;
content: $contentNext;
}
}
}
@keyframes mask{
0% {
background-position: 0 220%;
}
30% {
background-position: 0 0%;
}
100% {
background-position: 0 0%;
}
}
The final effect is as shown in the title picture:
You can click here for the complete code and demonstration effect:
CodePen Demo -- Digital Char Rain Animation
at last
Inspired by Yuan Chuan , this effect CodePen Demo - Matrix digital rain , the original effect is realized using JavaScript·, this article uses pure CSS to perform the interpretation.
For more exciting CSS effects, please pay attention to my CSS inspiration
Okay, this concludes this article, I hope it helps you :)
If you want to get the most interesting CSS information, don’t miss my account - 161075fc18095e iCSS front-end facts 161075fc18095f 😄
More wonderful CSS technical articles are summarized in my Github - iCSS , which will be updated continuously. Welcome to click a star to subscribe to the collection.
If you have any questions or suggestions, you can exchange more, original articles, limited writing style, and lack of knowledge. If there are any irregularities in the article, please let me know.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。