creative tim
Today, we are going to do a lot of stuff with CSS animations. Indeed, we will talk about CSS loading animations. What do you say? Ready?
今天,我们将使用CSS动画做很多事情。 确实,我们将讨论CSS加载动画。 你说什么? 准备?
A few things before we start:
我们开始之前的几件事:
- You won’t see any vendor prefixes in the CSS snippets, but you will, of course, find them in the files. 您不会在CSS片段中看到任何供应商前缀,但是您当然会在文件中找到它们。
- The goal of the tutorial is to show the potential of CSS, particularly CSS3, that’s why the rendering could be altered on IE9-. If you plan to support these browsers, be sure to make fallbacks. 本教程的目的是展示CSS的潜力,尤其是CSS3,这就是为什么可以在IE9-上更改渲染的原因。 如果您打算支持这些浏览器,请确保进行回退。
- I personally use the box-model where [width] = [element-width] + [padding] + [borders]. I activate it with the following snippet: 我个人使用[[width] = [element-width] + [padding] + [borders]的盒子模型。 我使用以下代码段激活它:
*,
*:before,
*:after {
box-sizing: border-box;
}
CSS资料:优点和缺点(CSS Stuff: Pros and Cons)
What are the advantages and disadvantages of pure CSS loaders and preloaders (and more commonly CSS stuff)? Why not a JS solution, or even the good ol’ way: an animated GIF? There is no magic answer for this, it will depend on the situation. But let me give you some ideas.
纯CSS加载器和预加载器(以及更常见CSS东西)的优缺点是什么? 为什么不使用JS解决方案,甚至不采用好的方法:动画GIF? 对此没有神奇的答案,这取决于情况。 但是,让我给您一些想法。
优点 (Pros)
- CSS is easily editable: you can quickly change the duration, speed, color or whatever you want on your animationCSS易于编辑:您可以快速更改持续时间,速度,颜色或动画中所需的任何内容
- CSS is “vector-like”: you can scale it as you wish without any quality lossCSS类似于“矢量”:您可以按需缩放它,而不会造成质量损失
- CSS animations are faster than JS “animations” (which are not exactly animations) since they use the native browser engineCSS动画使用本地浏览器引擎,因此比JS“动画”(并非完全是动画)要快。
- CSS animations use GPU acceleration: if you have a good device, you’ll have very fast and smooth animations CSS动画使用GPU加速:如果您拥有好的设备,您将获得非常快速和流畅的动画
- CSS animations can be easily paused with the animation-play-state propertyCSS动画可以通过animation-play-state属性轻松地暂停
缺点(Cons)
CSS animations don’t have full browser support: IE9- and Opera Mini don’t understand them
CSS动画不完全支持浏览器:IE9和Opera Mini不了解它们
- CSS (pre)loaders can involve heavy markup, not necessarily worth the costCSS(预)加载器可能涉及大量标记,不一定值得
- CSS animations can’t be easily fired on pointer-events (except hover) with JavaScript使用JavaScript很难在指针事件(悬停除外)上触发CSS动画
One way to go would be to detect support with Modernizr, use CSS animations for browsers that support them and fall back to a regular GIF in other browsers. Win win.
一种方法是检测对Modernizr的支持,对支持CSS的浏览器使用CSS动画,并在其他浏览器中使用常规的GIF。 双赢。
例子1 (Example 1)
We will start with something pretty simple as always. Our little sphere is running infinitely from left to right in the bar. Movement is important to make the user understand the application/website is actually doing something.
我们将一如既往地以非常简单的方式开始。 我们的小球体在栏中从左到右无限延伸。 移动对于使用户了解应用程序/网站实际上正在做的事情很重要。
标记 (The Markup)
<div class="bar">
<i class="sphere"></i>
</div>
Pretty minimalist, right? We could even do this we a single element but it can easily make the CSS ugly. Note that we could have both, clean markup and nice CSS when we’ll be able to animate pseudo-elements. 😉
非常简约,对吧? 我们甚至可以只用一个元素就可以做到这一点,但它很容易使CSS变得丑陋。 请注意,当我们能够为伪元素制作动画时,可以同时拥有干净的标记和漂亮CSS。 😉
CSS (The CSS)
First, we create the container for the sphere: the bar. To preserve proportions and make the preloaders scalable, I used the em unit. Simply change the font-size value on the wrapper to scale the whole thing as you wish. Pretty cool, right?
首先,我们创建球体的容器:杆。 为了保留比例并使预加载器可伸缩,我使用了em单元。 只需更改包装器上的字体大小值即可按需缩放整个内容。 很酷吧?
.demo-1 .bar {
/* Size and position */
font-size: 20px; /* 1em */
width: 10em;
height: 1em;
position: relative;
margin: 100px auto;
/* Styles */
border-radius: .5em; /* Height/2 */
background: white; /* Fallback */
background: rgba(255,255,255,0.6);
box-shadow:
0 0 0 .05em rgba(100,100,100,0.075), /* Subtle border */
0 0 0 .25em rgba(0,0,0,0.1), /* Outter border */
inset 0 .1em .05em rgba(0,0,0,0.1), /* Inset shadow */
0 .05em rgba(255,255,255,0.7); /* Slight reflection */
}
Let’s immediately deal with the “Please wait.”. You’ve probably noticed it doesn’t appear in the markup: that’s because it’s generated content. Actually it should be in the markup in a real live case, since it’s important content, not just graphical stuff. But for the demo, I thought it could be enough to generate it.
让我们立即处理“请稍候”。 您可能已经注意到它没有出现在标记中:这是因为它是生成的内容。 实际上,它应该存在于实际情况下的标记中,因为它是重要的内容,而不仅仅是图形内容。 但是对于演示,我认为生成它就足够了。
.demo-1 .bar:after {
/* Content and position */
content: "Please wait.";
position: absolute;
left: 25%;
top: 150%;
/* Font styles */
font-family: 'Carrois Gothic', sans-serif;
font-size: 1em;
color: #555;
text-shadow: 0 .05em rgba(255,255,255,0.7);
}
So in case you want to make this a real element, just create a span or whatever, give it those styles and it’s done. Now, let’s take a look at the sphere.
因此,如果您想使其成为一个真正的元素,只需创建一个跨度或其他任何东西,然后给它们指定样式即可。 现在,让我们看一下这个领域。
.demo-1 .sphere {
/* Size */
display: block;
width: 1em;
height: 100%;
/* Styles */
border-radius: 50%;
background: linear-gradient(#eee, #ddd);
box-shadow:
inset 0 .15em .1em rgba(255,255,255,0.3), /* Top light */
inset 0 -.1em .15em rgba(0,0,0,0.15), /* Bottom shadow */
0 0 .25em rgba(0,0,0,0.3); /* Outter shadow */
/* Animation */
animation: move 1.75s ease-in-out infinite alternate;
}
Last but not least, the keyframes running the animation:
最后但并非最不重要的是,运行动画的关键帧:
@keyframes move {
to { margin-left: 90%; }
}
How could it be easier, right? So the sphere
element runs the move
animation in 1.75 seconds alternatively from start to end and end to start.
怎么会更容易,对吗? 因此, sphere
元素在1.75秒内(从头到尾,从头到尾)运行move
动画。
Note: an easy way to convert this preloader into a progress indicator would be to remove the alternate
parameter in the animation declaration, and set the according animation time based on the time you want the user to wait.
If you want to dynamically update the position of the element based on the progression of the loading, you’d have to couple this with a little bit of JavaScript of course.
注意:将这个预加载器转换为进度指示器的一种简单方法是删除动画声明中的alternate
参数,并根据您希望用户等待的时间设置相应的动画时间。 如果要根据加载的进度动态更新元素的位置,则必须将其与一些JavaScript结合使用。
例子2 (Example 2)
Now let’s continue with something a little bit more complicated. But not too much! A rotating … candy? Or something? Honestly, I don’t know. 😀
现在,让我们继续一些复杂的事情。 但是不要太多! 旋转……糖果? 或者其他的东西? 老实说,我不知道。 😀
标记 (The Markup)
Okay, so this one is entirely pseudo-element based. Completely. No need for extra markup.
好的,所以这个完全基于伪元素。 完全可以无需额外的标记。
<div class="spinner"></div>
CSS(The CSS)
This will be quick, trust me. First, the element itself. I used red and beige, but you could pick whatever color you like. Same for the number of colors, I picked two but you could go with four. Or just one. Or any other.
很快,相信我。 首先,元素本身。 我使用红色和米色,但您可以选择任何喜欢的颜色。 颜色数量相同,我选择了两种,但您可以选择四种。 或者只是一个。 或其他。
.demo-2 .spinner {
/* Size and position */
font-size: 100px; /* 1em */
width: 1em;
height: 1em;
position: relative;
margin: 100px auto;
/* Styles */
border-radius: 50%;
background: #FF4F72; /* Fallback */
background:
linear-gradient(#ea2d0e 50%, #fcd883 50%), /* First column */
linear-gradient(#fcd883 50%, #ea2d0e 50%); /* Second column */
background-position:
0 0, /* Position of 1st column */
100% 0; /* Position of 2nd column */
background-size: 50% 100%; /* Contraction of "50% 100%, 50% 100%" */
background-repeat: no-repeat;
box-shadow:
inset 0 0 0 .12em rgba(0,0,0,0.2), /* Inner border */
0 0 0 .12em rgba(255,255,255,0.1); /* Outter border */
opacity: 0.7;
animation: rota 3s infinite alternate;
}
Now, a pseudo-element for the inner transparent white circle.
现在,内部透明的白色圆圈为一个伪元素。
.demo-2 .spinner:after {
/* Size */
content: "";
width: 50%;
height: 50%;
/* Perfect centering */
position: absolute;
top: 25%;
left: 25%;
/* Styles */
border: .12em solid rgba(255,255,255,0.3);
border-radius: inherit;
}
And the animation.
还有动画。
@keyframes rota {
25% { transform: rotate(270deg); }
50% { transform: rotate( 90deg); }
75% { transform: rotate(360deg); }
100% { transform: rotate(180deg); }
}
例子3(Example 3)
Now let’s dig into something a little bit more tricky. But don’t worry, it’s really not that hard. Actually, I tried to simulate random behavior in CSS. Long story short: it’s impossible unless you set completely weird values, and it’s still not random, of course. Anyway, we’ll see that later.
现在,让我们深入研究一些棘手的问题。 但是不用担心,这实际上并不难。 实际上,我尝试在CSS中模拟随机行为。 长话短说:除非您设置完全怪异的值,否则这是不可能的,当然,它也不是随机的。 无论如何,我们稍后会看到。
标记 (The Markup)
The HTML for this one is not very pretty. Since we can’t animate pseudo-elements, we have to use multiple elements to do this. I went with a list (even if it’s not very semantic) but you could go with whatever you want.
这个HTML并不是很漂亮。 由于我们无法为伪元素设置动画,因此必须使用多个元素来执行此操作。 我列出了一个列表(即使不是很语义),但是您可以随便选择哪个列表。
<ul class="spinner">
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
CSS(The CSS)
First thing to do: style the list itself.
首先要做的是:对列表本身进行样式设置。
.demo-3 .spinner {
/* Size and position */
font-size: 100px; /* 1em */
width: 1em;
height: 1em;
margin: 100px auto;
position: relative;
/* Styles */
list-style: none;
border-radius: 50%;
border: .01em solid rgba(150,150,150,0.1); /* Subtle white line circling the dots */
}
And the shared properties for all list elements.
以及所有列表元素的共享属性。
.demo-3 .spinner li {
width: .2em;
height: .2em;
position: absolute;
border-radius: 50%;
}
And now, a few explanations about what’s coming. When the page loads, the four dots are not overlapping each other, they are positioned like cardinal points: north, south, east, west. But, their rotation centers are all in the same spot: the exact center of the spinner.
现在,对即将发生的事情进行一些解释。 当页面加载时,四个点彼此不重叠,它们的位置像基点:北,南,东,西。 但是,它们的旋转中心都在同一位置:旋转器的精确中心。
.demo-3 .spinner li:nth-child(1) {
background: #00C176; /* Blue */
top: 0;
left: 50%;
margin-left: -.1em; /* Width/2 */
transform-origin: 50% 250%;
animation:
rota 1.13s linear infinite,
opa 3.67s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(2) {
background: #FF003C; /* Red */
top: 50%;
right: 0;
margin-top: -.1em; /* Height/2 */
transform-origin: -150% 50%;
animation:
rota 1.86s linear infinite,
opa 4.29s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(3) {
background: #FABE28; /* Yellow */
bottom: 0;
left: 50%;
margin-left: -.1em; /* Width/2 */
transform-origin: 50% -150%;
animation:
rota 1.45s linear infinite,
opa 5.12s ease-in-out infinite alternate;
}
.demo-3 .spinner li:nth-child(4) {
background: #88C100; /* Green */
top: 50%;
left 0;
margin-top -.1em; /* Height/2 */
transform-origin: 250% 50%;
animation:
rota 1.72s linear infinite,
opa 5.25s ease-in-out infinite alternate;
}
Last, the two animations. One is for the rotation and one for the opacity. Yeah, the opacity is changing as well!
最后,两个动画。 一种用于旋转,一种用于不透明度。 是的,不透明度也在改变!
@keyframes rota {
to { transform: rotate(360deg); }
}
@keyframes opa {
12.0% { opacity: 0.80; }
19.5% { opacity: 0.88; }
37.2% { opacity: 0.64; }
40.5% { opacity: 0.52; }
52.7% { opacity: 0.69; }
60.2% { opacity: 0.60; }
66.6% { opacity: 0.52; }
70.0% { opacity: 0.63; }
79.9% { opacity: 0.60; }
84.2% { opacity: 0.75; }
91.0% { opacity: 0.87; }
}
Note: it occurred to me some people are uncomfortable with counter-clockwise rotation. Plus, clockwise reinforces the idea of the fast loading.
注意:我想到有些人对逆时针旋转感到不舒服。 另外,顺时针加强了快速加载的想法。
你和号码怎么了? (What’s wrong with you and numbers?)
As I told you I tried to make things appear the more “random” I could. I could have built up a little JS script running random numbers and inserting them in CSS, but I don’t like the idea.
就像我告诉你的那样,我试图使事情看起来更“随机”。 我本可以构建一个运行随机数并将其插入CSS的小JS脚本,但我不喜欢这个主意。
The best idea I had to do it was to generate random numbers from my head so it “looks like random”. That’s why you can see animation durations like 1.72s, 4.29s or 1.13s. Same things with keyframes from opa
and opacity values. Weird intervals, weird values, “pseudo random”.
我要做的最好的主意是从我的头上生成随机数,这样它“看起来像随机数”。 这就是为什么您可以看到动画持续时间为1.72s,4.29s或1.13s的原因。 与来自opa
和opacity值的关键帧相同。 奇怪的间隔,怪异的值,“伪随机”。
那么转换起源呢? (What about transform-origin?)
I take the opportunity to give you a little trick to find the appropriate transform-origin value when you want to do a rotation which is not performed around the default rotation center.
当您要执行围绕默认旋转中心不执行的旋转时,我借此机会给您一些技巧,以找到合适的变换原点值。
The main problem I faced with the transform-origin property is the lack of comprehension of the value. I didn’t understand well (and sometimes still don’t) the way it handles the transform origin.
我使用transform-origin属性遇到的主要问题是缺乏对值的理解。 我不太了解(有时还是不了解)它处理转换原点的方式。
Anyway, the idea is to show the transform origin with a pseudo-element. Have a look:
无论如何,这个想法是用伪元素显示变换原点。 看一看:
.my-element {
transform-origin: 12% 34%;
}
.my-element:after {
content: "";
width: 4px;
height: 4px;
position: absolute;
left: 12%; /* First value of transform-origin */
top: 34%; /* Second value of transform-origin */
margin: -2px 0 0 -2px;
border-radius: 50%;
background: red;
}
例子4(Example 4)
Let’s continue with a soft demo, a little bit steam punk: wheels, gears and such. I like this. Okay, let’s go.
让我们继续一个软演示,一点点蒸汽朋克:车轮,齿轮等。 我喜欢这个。 好吧走吧
标记(The Markup)
Pretty heavy on this one as well since we have to wrap each letter on a span. And we need a wrapper to cancel the main element rotation. We’ll talk about this later.
由于我们必须将每个字母都包裹在一个跨度上,因此在此方面也相当繁重。 我们需要一个包装器来取消主要元素的旋转。 我们稍后再讨论。
<div class="wrapper">
<div class="inner">
<span>L</span>
<span>o</span>
<span>a</span>
<span>d</span>
<span>i</span>
<span>n</span>
<span>g</span>
</div>
</div>
CSS(The CSS)
First, we have many things to apply to the main element, such as size, position, font-styles, animation, etc.
首先,我们有许多要应用于主元素的内容,例如大小,位置,字体样式,动画等。
.demo-4 .wrapper {
/* Size and position */
font-size: 25px; /* 1em */
width: 8em;
height: 8em;
margin: 100px auto;
position: relative;
/* Styles */
border-radius: 50%;
background: rgba(255,255,255,0.1);
border: 1em dashed rgba(138,189,195,0.5);
box-shadow:
inset 0 0 2em rgba(255,255,255,0.3),
0 0 0 0.7em rgba(255,255,255,0.3);
animation: rota 3.5s linear infinite;
/* Font styles */
font-family: 'Racing Sans One', sans-serif;
color: #444;
text-align: center;
text-transform: uppercase;
text-shadow: 0 .04em rgba(255,255,255,0.9);
line-height: 6em;
}
Wow, that was pretty heavy, wasn’t it? We still have to create the inner wheels with pseudo-elements.
哇,那太重了,不是吗? 我们仍然必须使用伪元素创建内轮。
.demo-4 .wrapper:before,
.demo-4 .wrapper:after {
content: "";
position: absolute;
z-index: -1;
border-radius: inherit;
box-shadow: inset 0 0 2em rgba(255,255,255,0.3);
border: 1em dashed;
}
.demo-4 .wrapper:before {
border-color: rgba(138,189,195,0.2);
top: 0; right: 0; bottom: 0; left: 0;
}
.demo-4 .wrapper:after {
border-color: rgba(138,189,195,0.4);
top: 1em; right: 1em; bottom: 1em; left: 1em;
}
Now the inner wrapper and the spans. Note how we use the reverse
parameter on the inner container to cancel the main element rotation.
现在是内部包装器和范围。 注意我们如何在内部容器上使用reverse
参数来取消主要元素的旋转。
.demo-4 .wrapper .inner {
width: 100%;
height: 100%;
animation: rota 3.5s linear reverse infinite;
}
.demo-4 .wrapper span {
display: inline-block;
animation: placeholder 1.5s ease-out infinite;
}
.demo-4 .wrapper span:nth-child(1) { animation-name: loading-1; }
.demo-4 .wrapper span:nth-child(2) { animation-name: loading-2; }
.demo-4 .wrapper span:nth-child(3) { animation-name: loading-3; }
.demo-4 .wrapper span:nth-child(4) { animation-name: loading-4; }
.demo-4 .wrapper span:nth-child(5) { animation-name: loading-5; }
.demo-4 .wrapper span:nth-child(6) { animation-name: loading-6; }
.demo-4 .wrapper span:nth-child(7) { animation-name: loading-7; }
Sadly, we need one animation for each letter since they need to be delayed. At first I thought about animation-delay, but this property only delays the first run, not each of them so it won’t work.
可悲的是,由于每个字母都需要延迟,因此我们需要为每个字母制作一个动画。 起初我考虑过动画延迟,但是此属性只会延迟首次运行,而不是每次都延迟,因此它将无法正常工作。
@keyframes rota {
to { transform: rotate(360deg); }
}
@keyframes loading-1 {
14.28% { opacity: 0.3; }
}
@keyframes loading-2 {
28.57% { opacity: 0.3; }
}
@keyframes loading-3 {
42.86% { opacity: 0.3; }
}
@keyframes loading-4 {
57.14% { opacity: 0.3; }
}
@keyframes loading-5 {
71.43% { opacity: 0.3; }
}
@keyframes loading-6 {
85.71% { opacity: 0.3; }
}
@keyframes loading-7 {
100% { opacity: 0.3; }
}
Those animations can be a little tricky to understand, so let me put it simple. Each letter needs to:
理解这些动画可能有些棘手,所以让我简单一点。 每个字母都需要:
- Lose a little bit of opacity 失去一点点的不透明
- Go back to full opacity回到完全不透明
- Wait until every other letter has done the same等到其他所有字母都一样
- Go back to step 1 and repeat返回步骤1并重复
How do we do that exactly?
我们到底该怎么做?
- You count the number of letters in your element. Our demo counts 7. 您可以计算元素中的字母数。 我们的演示计数为7。
- You divide 100 (the number of keyframes, expressed in %) by this number. In this example, it equals to ~14.28. 将100(关键帧数,以%表示)除以该数字。 在此示例中,它等于〜14.28。
- Every 14.28 keyframes, a letter runs its thing. 每隔14.28个关键帧,就会运行一个字母。
- Done. 做完了
例子5(Example 5)
Let’s end with something a little bit more conceptual. I know people won’t like it much, but depending on your website/application, you might consider this as an inspiration.
让我们以更具概念性的结尾。 我知道人们不太喜欢它,但是根据您的网站/应用程序,您可能会认为这是一个启发。
标记 (The Markup)
Despite what it looks like, we only need one single element to achieve this.
尽管看起来很像,但我们只需要一个元素即可实现这一目标。
<div class="pre-loader"></div>
CSS(The CSS)
Actually, our element is only one of our little spheres (the one at the top). The seven others are made of box-shadows.
实际上,我们的元素只是我们的小领域之一(顶部的领域)。 另外七个是由盒子阴影制成的。
.demo-5 .pre-loader {
/* Size and position */
font-size: 30px; /* 1em */
width: 1em;
height: 1em;
position: relative;
margin: 100px auto;
/* Styles */
border-radius: 50%;
background: #123456;
transform-origin: 50% 250%;
animation:
blink 1s steps(1, start) infinite, /* Blink */
counter-clock 8s linear infinite; /* Rotation */
/* Dots, clockwise */
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
The transparent square effect is made with a … well, a transparent square. It’s a rotated pseudo-element put on top of everything else. Pretty easy.
透明的正方形效果是由一个…透明正方形构成的。 这是一个旋转的伪元素,位于所有其他元素之上。 挺容易。
.demo-5 .pre-loader:after {
/* Size and position */
content: "";
width: 3em;
height: 3em;
position: absolute;
left: -1em;
top: 1em;
/* Styles */
transform: rotate(45deg);
background: white; /* Fallback */
background: rgba(255,255,255,0.6);
}
And now the animations. A few explanations about the second one (blink
):
现在是动画。 关于第二个的一些解释( blink
):
- We have 8 bullets, so we divide 100 keyframes into 8: 12.5. 我们有8个项目符号,因此我们将100个关键帧分为8:12.5。
Every 12.5 keyframes, a bullet loses a little bit of opacity.
rgb(18,52,86)
is the RGB code for #123456.每12.5个关键帧,子弹就会失去一点透明度。
rgb(18,52,86)
是#123456的RGB代码。- On the first frame (12.5%), it’s the element itself that decreases opacity. 在第一帧(12.5%)上,是元素本身降低了不透明度。
@keyframes counter-clock {
to { transform: rotate(-360deg); }
}
@keyframes blink {
12.5% {
background: rgba(18,52,86,0.6);
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
25% {
background: #123456;
box-shadow:
1em 1em rgba(18,52,86,0.6),
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
37.5% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em rgba(18,52,86,0.6),
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
50% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em rgba(18,52,86,0.6),
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
62.5% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em rgba(18,52,86,0.6),
-1em 3em #123456,
-2em 2em #123456,
-1em 1em #123456;
}
75% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em rgba(18,52,86,0.6),
-2em 2em #123456,
-1em 1em #123456;
}
87.5% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em rgba(18,52,86,0.6),
-1em 1em #123456;
}
100% {
background: #123456;
box-shadow:
1em 1em #123456,
2em 2em #123456,
1em 3em #123456,
0em 4em #123456,
-1em 3em #123456,
-2em 2em #123456,
-1em 1em rgba(18,52,86,0.6);
}
}
Note: I know I said counter-clockwise rotations are not that good, but since we couple it with a very fast clockwise animation, it’s a bit different this case.
注意:我知道我说的逆时针旋转不是很好,但是由于我们将其与非常快的顺时针动画结合在一起,所以这种情况有些不同。
使用外部工具简化流程 (Ease the process with external tools)
As you may have seen in some demos, sometimes we need to repeat the same snippets of code for different values or something and it can be very annoying to do.
正如您在某些演示中可能已经看到的那样,有时我们需要为不同的值或某些内容重复相同的代码片段,这样做可能非常烦人。
Thankfully, we can dramatically ease the process with appropriate tools. I think you’ve figured out this is the moment where I’m talking about CSS preprocessors. Indeed, but not only preprocessors.
幸运的是,我们可以使用适当的工具来大大简化这一过程。 我认为您已经知道这是我谈论CSS预处理程序的时刻。 确实,不仅限于预处理器。
Since the 4th demo was clearly the most repetitive, let’s try to ease the making of it for, let’s say, automatizing the process for changing the number of letters in the element.
由于第4个演示显然是最重复的,因此,让我们尝试简化它的制作过程,例如,使元素中字母数量的更改过程自动化。
Lettering.js (Lettering.js)
Lettering.js does a very simple thing: it wraps every letter in the targeted element with span
tags.
Lettering.js做的很简单:将每个字母用span
标签包裹在目标元素中。
So from now on, we don’t have to manually wrap our letters with spans, Lettering.js does it for us. Pretty neat, right? But we’re more concerned about the CSS part, I think.
因此,从现在开始,我们不必使用跨距手动包裹字母,而Lettering.js会为我们完成。 很整洁吧? 但是,我认为我们更关心CSS部分。
CSS预处理器 (CSS Preprocessors)
You may have already understood it: we need a loop. And I have some good news, CSS preprocessors provide loops support! At least some of them…
您可能已经了解了:我们需要一个循环。 而且我有一个好消息,CSS预处理器提供了循环支持! 至少其中一些...
Yeah, because you see, Sass does it the right way: the for loop. LESS however doesn’t provide a loop support. Instead, you have to make a recursive function decrementing a variable. It sucks, but it works.
是的,因为您看到了,所以Sass的做法正确:for循环。 但是, LESS不提供循环支持。 取而代之的是,您必须使一个递归函数递减一个变量。 它很烂,但是有效。
/* SCSS */
for $i from 1 through 10 {
/* Do stuff */
}
/* LESS */
.loop(@index) when (@index > 0) {
/* Do stuff */
.loop(@index - 1);
}
.loop(0) { }
.loop(10);
See? In what universe is a recursive function easier than a for loop? Anyway, let’s make our 4th demo with “loops”.
看到? 在哪个Universe中,递归函数比for循环更容易? 无论如何,让我们用“循环”制作第四个演示。
/* SCSS */
$iterations : 7; //Number of letters
@for $i from 1 through $iterations {
$val : 100%/$iterations*$i;
@keyframes loading-#{$i} {
#{$val} {
opacity: 0.3;
}
}
.wrapper span:nth-child(#{$i}) {
animation-name: loading-#{$i};
}
}
/* LESS */
@iterations: 7; //Number of letters
@newline: `"n"`; //Fix hack
.loop (@index) when (@index > 0) {
@val: 100/@iterations*@index;
(~"@keyframes loading-@{index} {@{newline}@{val}%") {
opacity: 0.3;
}
(~"} .wrapper span:nth-child(@{index}) @{newline}") {
animation-name: "loading-@{index}";
}
.loop(@index - 1);
}
.loop (0) {}
.loop (@iterations);
The output will be exactly the same as the one you read in the 4th demo. So it may be trivial when you have only 7 letters, but when you have 40 or 50, it can be a real time saver.
输出将与您在第4个演示中阅读的输出完全相同。 因此,当您只有7个字母时,这可能是微不足道的,但是当您有40个或50个字母时,它可以节省大量时间。
Note: adding prefixes to the SCSS version is pretty straightforward: duplicate the animation-name line, and the @keyframes block and add prefixes. However it’s completely painful with LESS and I’ll save you some time by showing you the end result.
注意:在SCSS版本中添加前缀非常简单:复制animation-name行,并@keyframes块并添加前缀。 但是,使用LESS会让您非常痛苦,我将通过显示最终结果为您节省一些时间。
If you want to understand how LESS concatenation works, and how you can handle things like @media or @keyframes in a mixin, please refer to the following discussions on Stack Overflow:
如果您想了解LESS串联的工作方式以及如何在mixin中处理@media或@keyframes之类的东西,请参考以下关于Stack Overflow的讨论:
最后的话(Final words)
And this is already the end of the tutorial, alas! Let’s finish with a few links as further readings and resources:
tutorial,这已经结束了教程! 让我们结束一些链接,作为进一步的阅读和资源:
A loading bar I made (based on a Dribble shot from Piotr Kwiatkowski)
A preloader I made (based on a Dribble shot from Filip Chudzinski)
My tutorial on how to make a pure CSS pie timer on CSS-tricks
Thanks for reading and be sure to share any related resource!
感谢您的阅读,并确保共享任何相关资源!
翻译自: https://tympanus.net/codrops/2012/11/14/creative-css-loading-animations/
creative tim