Some friends asked me how to use CSS to achieve the following Loading effects:

This is a very interesting question.

We know that using CSS, we can easily implement an animation like this:

<div></div>
Copy the code
div {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    border: 2px solid transparent;
    border-top: 2px solid # 000;
    border-left: 2px solid # 000;
    animation: rotate 3s infinite linear;
}
@keyframes rotate {
    100% {
        transform: rotate(360deg); }}Copy the code

The animation is as follows:

Compared with the required line loading animation, the above animation lacks a core point:

  • The length of a line will change as it rotates

Therefore, the difficulty here is also changed to how to dynamically realize the length change of arc line segment? If this problem is solved, the above line transformation Loading animation is basically solved.

This article introduces several interesting ways in which CSS can dynamically change the length of an arc:

Method 1: use a mask implementation

The first method, and the one that’s easy to think of, is to use masks.

We realize two semicircle lines, one is the actual color that can be seen, and the other is a thicker semicircle line that is the same as the background color. When the speed of the two lines is inconsistent, we can see the dynamic arc line from the vision.

Take a look at the schematic diagram to understand it:

We replace the above red lines with white background, and the overall animation effect is very similar. The pseudo-code is as follows:

<div></div>
Copy the code

div {
    width: 200px;
    height: 200px;
}
div::before {
    position: absolute;
    content: "";
    top: 0px; left: 0px; right: 0px; bottom: 0px;
    border-radius: 50%;
    border: 3px solid transparent;
    border-top: 3px solid # 000;
    border-left: 3px solid # 000;
    animation: rotate 3s infinite ease-out;
}
div::after {
    position: absolute;
    content: "";
    top: -2px; left: -2px; right: -2px; bottom: -2px;
    border-radius: 50%;
    border: 7px solid transparent;
    border-bottom: 7px solid #fff;
    border-right: 7px solid #fff;
    animation: rotate 4s infinite ease-in-out;
}
@keyframes rotate {
    100% {
        transform: rotate(0deg); }}Copy the code

The core is to achieve two semicircle lines, one black, one background color, the two lines move at different rates (through animation time and slow motion control), the effect is as follows:

Complete the code you can swipe — CodePen Demo-Linear Loading

The two biggest problems with the above scheme are:

  1. If the background color is not solid, it will give you away
  2. If you want to show a line segment larger than half a circle, it cannot be done

Based on this, we have to find another way.

Method two: Leverage SVG’s stroking -* capabilities

As mentioned in many previous articles, CSS with SVG allows us to implement a variety of simple and complex line animations, such as simple:

Or custom complex line animations for complex paths:

> < p style = “max-width: 100%; clear: both; min-height: 1em

Here, a simple SVG tag < Circle > with its CSS styles stroke-Dasharray and stroke-Dashoffset is enough to do the trick:

<svg class="circular" viewbox="25 25 to 50 50">
  <circle class="path" cx="50" cy="50" r="20" fill="none" />
</svg>
Copy the code
.circular {
  width: 100px;
  height: 100px;
  animation: rotate 2s linear infinite;
}
.path {
  stroke-dasharray: 1.200;
  stroke-dashoffset: 0;
  stroke: # 000;
  animation: dash 1.5 s ease-in-out infinite
}
@keyframes rotate {
  100% {
    transform: rotate(360deg); }}@keyframes dash {
  0% {
    stroke-dasharray: 1.200;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 89.200;
    stroke-dashoffset: -35px;
  }
  100% {
    stroke-dasharray: 89.200;
    stroke-dashoffset: -124px; }}Copy the code

A quick explanation:

  • stroke: Similar to CSS border-color, set the border color for SVG graphics.
  • stroke-dasharrayThe: value is an array of unlimited numbers, each number alternately representing the width of the dash and interval;
  • stroke-dashoffset: Distance from dash mode to the start of a path.

We use stroke-Dasharray to cut the previously complete line into multiple segments, assuming stroke-Dasharray: 10, where 10 represents such a figure:

The first 10 represents the length of the line segment, and the second 10 represents the space between the two visible line segments.

In the actual code, stroke-Dasharray: 1, 200 means that there is a 200px interval between two 1px line segments. Since the circumference of the circle with a diameter of 40px is 40 * π ≈ 125.6px, less than 200, there is only one point as shown below:

Similarly, stroke-Dasharray: 89, 200 means:

Through animation, the line segment is tween between these two states. The stroke-Dashoffset moves the line segment forward and combines with the parent’s transform: Rotate () animation to visually rotate the line segment in the same direction. The results are as follows:

The full code you can stamp here: CodePen Demo — Linear Loading

OK, I don’t want to introduce SVG tags, I just want to use pure CSS. There is also a pure CSS solution that utilizes CSs@property.

Method 3: Use CSS @Property to make Conic-gradient move

Here we need to use the ability of CSS @Property to animate angular gradients that would otherwise not work.

This method, which I mentioned in the article on CSS @ Property, makes the impossible possible

Normally, gradients cannot be animated, as shown below:

<div></div>
Copy the code
.normal {
    width: 200px;
    height: 200px;
    border-radius: 50%;
    background: conic-gradient(yellowgreen, yellowgreen 25%, transparent 25%, transparent 100%); 
    transition: background 300ms;
    
    &:hover {
        background: conic-gradient(yellowgreen, yellowgreen 60%, transparent 60.1%, transparent 100%); }}Copy the code

Since Conic-gradient does not support transition animation, what we get is a direct change from one frame to another:

Ok, use CSS @property to customize the variable:

@property --per {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 25%;
}

div {
    background: conic-gradient(yellowgreen, yellowgreen var(--per), transparent var(--per), transparent 100%); 
    transition: --per 300ms linear;
    
    &:hover {
        --per: 60%; }}Copy the code

Take a look at the results:

Here, we can animate the gradient dynamically, giving it animation power.

We only need to introduce the mask again and cut out the middle part to realize the above line Loading animation. The pseudo-code is as follows:

<div></div>
Copy the code

@property --per {
    syntax: "<percentage>";
    inherits: false;
    initial-value: 10%;
}

div {
    position: relative;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    animation: rotate 11s infinite ease-in-out;

    &::before {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border-radius: 50%;
        background: conic-gradient(transparent, transparent var(--per), #fa7 var(--per), #fa7);
        mask: radial-gradient(transparent, transparent 47.5 px..# 000 48px.# 000);
        animation: change 3s infinite cubic-bezier(0.57.0.29.0.49.0.76); }}@keyframes change {
    50% {
        transform: rotate(270deg);
        --per: 98%;
    }
    100% {
        transform: rotate(720deg); }}@keyframes rotate {
    100% {
        transform: rotate(360deg);
        filter: hue-rotate(360deg); }}Copy the code

I added filter: hue-rotate() to rotate the color of the line. The result is a pure CSS solution:

For the complete code you can click here: Linear Loading Animation

The only problem with this scenario is that the current compatibility of CSS @Property is slightly less optimistic. The future, of course.

The last

To sum up, this paper introduces three kinds of Loading animations to realize the change of dynamic arc line length. Of course, each of them has its own advantages and disadvantages. Sometimes, cutting images may also be a more time-saving way 🙂

Well, that’s the end of this article, I hope you found it helpful 🙂

Want to Get the most interesting CSS information, do not miss my public account – iCSS front-end interesting news 😄

More interesting CSS technology articles are summarized in my Github — iCSS, constantly updated, welcome to click on the star subscription favorites.

If there are any questions or suggestions, you can exchange more original articles, writing is limited, talent and learning is shallow, if there is something wrong in the article, hope to inform.