如何创建具有线性渐变的圆角动画进度条?

问题描述

我只想使用CSS创建类似的东西。

Rounded progress bar with gradient

更具体地说,我需要一个具有x%黄色背景且带有圆角边缘的div。黄色部分可以在开始,结束或中间的任何地方,如上图所示。 div的其余部分应染成黑色。

我知道我可以通过将div放在另一个内部并设置内部div的长度,位置和背景颜色来做到这一点。但是我想知道是否可以通过设置其背景颜色或背景图像或其他方式仅使用一个div来完成。使用线性渐变,除了黄色部分的圆形边缘,我可以实现所有想要的功能。这是CSS:

/* this will make the background-color 40% black,20% yellow,40% black */
div{
    background-image: linear-gradient(
        90deg,black 40%,yellow 20%,yellow 60,black 60%
    );
    background-size: 100% 100%;
    background-repeat: no-repeat;
}

这是代码段:

#mydiv{
  width: 400px;
  height: 50px;
  background-image: linear-gradient(
        90deg,rgb(20,20,20) 40%,rgb(255,174,0) 20%,0) 60%,20) 60%
   );
   background-size: 100% 100%;
   background-repeat: no-repeat;
   border-radius: 25px;
}
<div id="mydiv"></div>

是否可以仅使用一个div和CSS来实现这一目标?

我需要能够控制黄色部分的长度和位置,以便可以在CSS动画中更改其位置和长度。

动画将如下所示:

#outer{
  width: 400px;
  height: 20px;
  border-radius: 10px;
  position: relative;
  overflow: hidden;
  background-color: rgb(20,20);
}

#inner{
  width: 20%;
  height: 100%;
  border-radius: 10px;
  position: absolute;
  left: -20%;
  background-color: rgb(255,0);
  animation: loading 2s infinite;
}

@keyframes loading{
  0%{
    left: -20%;
  }
  100%{
    left: 100%;
  }
}
<div id="outer">
  <div id="inner"></div>
</div>

解决方法

要实现此目的,需要将yellow栏设为独立的选择器。

使用css,您可以在:before标签内使用#mydiv选择器,并在其中放置黄色条,如下所示。

#mydiv {
  width: 400px;
  height: 50px;
  background-color: black;
  border-radius: 25px;
  position: relative;
}

#mydiv:before {
  content: " ";
  position: absolute;
  top: 0;
  left: 20%;
  width: 40%;
  height: 100%;
  border-radius: 25px;
  background-color: yellow;
}
<div id="mydiv"></div>

,

这是仅梯度解决方案:

.mydiv{
  --w:100px; /* width of progress*/
  --h:50px; /* height of the element*/

  height: var(--h);
  box-sizing:border-box;
  margin:5px;
  background: 
    radial-gradient(farthest-side,orange 98%,transparent 100%) 0/var(--h) 100%,radial-gradient(farthest-side,linear-gradient(orange,orange) 0/ var(--w) 100%
    black;
  background-repeat: no-repeat;
  border-radius: var(--h);
  animation: a 2s linear infinite;
}
@keyframes a{
  from {
    background-position:
      left calc(-1*var(--w) - var(--h)) top 0,left calc(-1*var(--h)) top 0,left calc(-1*var(--h)/2 - var(--w)) top 0;
  }
  to {
    background-position:
      right calc(-1*var(--h)) top 0,right calc(-1*var(--w) - var(--h)) top 0,right calc(-1*var(--h)/2 - var(--w)) top 0;
  }
}
<div class="mydiv"></div>

<div class="mydiv" style="--w:200px;--h:40px;"></div>

<div class="mydiv" style="--w:250px;--h:20px;"></div>

或使用伪元素:

.mydiv {
  --w:100px; /* width of progress*/
  --h:50px; /* height of the element*/
  
  height: var(--h);
  background: black;
  border-radius: var(--h);
  overflow: hidden;
  margin:5px;
}

.mydiv::before {
  content: "";
  display: block;
  position: relative;
  width: var(--w);
  border-radius: inherit;
  height: 100%;
  background: orange;
  animation: a 2s linear infinite;
}

@keyframes a {
  from {
    left: 0;
    transform: translateX(-100%);
  }
  to {
    left: 100%;
    transform: translateX(0);
  }
}
<div class="mydiv"></div>

<div class="mydiv" style="--w:200px;--h:40px;"></div>

<div class="mydiv" style="--w:250px;--h:20px;"></div>

,

可能的梯度解

只需在radial-gradient的线性渐变的开头和结尾处添加圆帽

#mydiv{
  width: 400px;
  height: 50px;
  background-color: rgba(20,20,20);
  background-image: linear-gradient(
        90deg,transparent 25px,rgb(255,174,0) 25px,0) calc(100% - 25px),transparent calc(100% - 25px)
   ),radial-gradient(circle at 25px,transparent 25px),radial-gradient(circle at calc(100% - 25px),transparent 25px);
   background-size: 50% 100%;
   background-repeat: no-repeat;
   border-radius: 25px;
   
   animation: moving 3s infinite alternate linear;
}

@keyframes moving {
  100% { 
    background-position: 100% 0;
  }
}
<div id="mydiv"></div>