【问题标题】:Multi color progress bar with border-radius and different border color具有边框半径和不同边框颜色的多色进度条
【发布时间】:2020-09-18 15:47:13
【问题描述】:

我正在尝试创建此进度条,但由于它具有边框半径和每个子进度元素的不同边框颜色而很困难。

有人知道如何实现吗?

这是我目前取得的成果,不包括边框: Codepen

body {
  display: flex;
  justify-content: center;
}

.progress-bar {
  height: 24px;
  width: 280px;
  background: #eaeaea;
  border-radius: 16px;
  display: flex;
  overflow: hidden;
}

.progress-bar-fill-1 {
  width: 30%;
  background: #F16172;
  box-sizing: border-box;
  border-right: 1px solid white;
}

.progress-bar-fill-2 {
  width: 20%;
  background: #31C4F3;
  box-sizing: border-box;
  border-right: 1px solid white;
}
<div class="progress-bar">
  <div class="progress-bar-fill-1"></div>
  <div class="progress-bar-fill-2"></div>
</div>

例如,如果我尝试为.progress-bar-fill-1 添加边框,它不会出现在角落上。

注意,我事先不知道百分比值,所以无法通过在第一个进度元素中添加border-radius 来解决问题。

谢谢

【问题讨论】:

  • 你能分享你的html代码吗?我没有道理。
  • @MaximJin 我添加了我卡在其中的代码...不知道如何为每个元素添加边框。
  • 您添加了隐藏在父元素中的溢出。如果只在第一个元素中添加边框, .progress-bar-fill-1 {border-radius: 16px; }
  • 是的,我在问题中提到它只会对这个例子有所帮助,但它不够通用......我需要为每个案例找到一个 css 解决方案。

标签: css less


【解决方案1】:
body {
  display: flex;
  justify-content: center;
}

.progress-bar {
  height: 24px;
  width: 280px;
  background: #eaeaea;
  border-radius: 16px;
  display: flex;
  overflow: hidden;
}


.progress-bar-fill-1 {
  position: relative;
  width: 30%;
  z-index: 1;
}

.progress-bar-fill-1:before {
  position: absolute;  
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  content: "";
  background: #F16172;
  box-sizing: border-box;
  border-right: 1px solid white;
  border: 1px solid black;
  border-radius: 16px;
}

.progress-bar-fill-2 {
  width: 20%;
  position:relative;  
}

.progress-bar-fill-2:before {
  position: absolute;
  left: -16px;
  right: 0;
  top: 0;
  bottom: 0;
  content: "";
  background: #31C4F3;
  box-sizing: border-box;
  border-right: 1px solid white;
  border-radius: 16px;
}

请检查结果。 您使用了 flex。所以我们不能将边距添加到第二个div。

【讨论】:

  • 谢谢,但它在每个子进度元素中都有圆角,我在设计中需要它。并且是通用的,因为我不确切知道它将包含多少子进度以及宽度。
【解决方案2】:

使用剪辑路径、伪元素和一些 CSS 变量,您可以使用一个元素轻松完成此操作。诀窍是在彼此顶部放置 3 个元素(主元素和 2 个伪元素),然后剪切伪元素以仅显示所需的部分:

.progress-bar {
  --b:2px; /* boder width */
  --s:2px; /* space between progress */

  height: 30px;
  width: 300px;
  margin:5px;
  background: #eaeaea;
  border-radius: 20px;
  position:relative;
  border:var(--b) solid grey;
  position:relative;
}
.progress-bar::before,
.progress-bar::after{
  content:"";
  border-radius:inherit;
  border:inherit;
  box-sizing: border-box;
  position:absolute;
  top:calc(-1*var(--b));
  left:calc(-1*var(--b));
  bottom:calc(-1*var(--b));
  right:calc(-1*var(--b));
}

.progress-bar::before {
  background: #F16172;
  border-color:red;
  clip-path:inset(0 calc(100% - var(--f1)) 0 0);
}

.progress-bar::after {
  background: #31C4F3;
  border-color:blue;
  clip-path:inset(0 calc(100% - var(--f1) - var(--f2)) 0 calc(var(--f1) + var(--s)));
}
<div class="progress-bar" style="--f1:30%;--f2:20%;"></div>

<div class="progress-bar" style="--f1:50%;--f2:20%;--b:3px;"></div>

<div class="progress-bar" style="--f1:60%;--f2:10%;--s:5px"></div>

<div class="progress-bar" style="--f1:20%;--f2:70%;--b:1px"></div>

<div class="progress-bar" style="--f1:20%;--f2:80%;--s:10px"></div>

【讨论】:

  • 不错!我只担心浏览器支持。而且,这可以通过滑入以某种方式动画吗?
  • @AnatEliahu 什么样的动画?
  • @AnatEliahu 像这样:jsfiddle.net/suc4b1jz ?悬停查看效果
【解决方案3】:

为什么会出现这个问题:

父元素使用overflow: hidden;border-radius: 16px;。什么会导致带有圆角的父元素以及其中的所有内容都被父元素屏蔽。

因为子元素(又名.progress-bar-fill-1)原本是一个正方形,所以也会产生正方形的边框。但是子元素的前面/开头将被其父元素掩盖并溢出。

对此的解决方案是,将被屏蔽的父元素中的第一个子元素也舍入,如下所述。

解决方案:

您还必须为第一个子元素添加边框半径。又名 border-radius: 0 0 16px 16px 0;.progress-bar-fill-1,如下例所示。

固定代码示例:

body {
  display: flex;
  justify-content: center;
}

.progress-bar {
  height: 24px;
  width: 280px;
  background: #eaeaea;
  border-radius: 16px;
  display: flex;
  overflow: hidden;
}

.progress-bar-fill-1 {
  width: 30%;
  background: #F16172;
  box-sizing: border-box;
  border-right: 1px solid white;
  border-radius: 0 0 16px 16px 0;
}

.progress-bar-fill-2 {
  width: 20%;
  background: #31C4F3;
  box-sizing: border-box;
  border-right: 1px solid white;
}
<div class="progress-bar">
  <div class="progress-bar-fill-1"></div>
  <div class="progress-bar-fill-2"></div>
</div>

【讨论】:

  • 谢谢,但如果我想要更通用的解决方案,仍然存在问题,请参阅我对帖子的新评论并附上示例。
  • 您能解释一下为什么要为子元素添加边框吗?而不是父元素?
  • 只是因为每个子元素都有不同的颜色,如果您知道如何为边框设置多种颜色,那也很好。我还想过让 2 个进度条彼此重叠(绝对位置)并以某种方式将其用作技巧。
【解决方案4】:

如果我将此添加到.progress-bar-fill-1:

border-top-left-radius: 16px;
border-bottom-left-radius: 16px;

它仍然不能解决问题,例如在这种情况下,当.progress-bar-fill-1 非常小时,.progress-bar-fill-2 的边框也会有同样的问题.. 所以我需要一个更通用的解决方案,因为我需要用它创建一个 React 组件。

问题来了:

body {
  display: flex;
  justify-content: center;
}

.progress-bar {
  height: 24px;
  width: 500px;
  background: #eaeaea;
  border-radius: 16px;
  display: flex;
  overflow: hidden;
}

.progress-bar-fill-1 {
  width: 1%;
  background: #F16172;
  box-sizing: border-box;
  border-right: 1px solid white;
  border: 1px solid black;
  border-top-left-radius: 16px;
  border-bottom-left-radius: 16px;
}

.progress-bar-fill-2 {
  width: 20%;
  background: #31C4F3;
  box-sizing: border-box;
  border-right: 1px solid white;
  border: 1px solid blue;
  border-left: none;
}
<div class="progress-bar">
  <div class="progress-bar-fill-1"></div>
  <div class="progress-bar-fill-2"></div>
</div>

【讨论】:

    【解决方案5】:

    我稍微修改了您的代码。 在 1% 上看起来不太好,但 2% 等看起来就像设计一样。

    body {
      display: flex;
      justify-content: center;
    }
    
    .progress-bar {
      height: 24px;
      width: 500px;
      background: #eaeaea;
      border-radius: 16px;
      display: flex;
      overflow: hidden;
    }
    
    .progress-bar-fill-1 {
      width: 2%;
      background: #F16172;
      box-sizing: border-box;
      border-right: 1px solid white;
      border-top: 1px solid red;
      border-bottom: 1px solid red;
      border-left: 1px solid red;
      border-top-left-radius: 16px;
      border-bottom-left-radius: 16px;
    }
    
    .progress-bar-fill-2 {
      width: 20%;
      background: #31C4F3;
      box-sizing: border-box;
      border-top: 1px solid blue;
      border-bottom: 1px solid blue;
      border-right: 1px solid white;
      border-left: none;
    }
    <div class="progress-bar">
      <div class="progress-bar-fill-1"></div>
      <div class="progress-bar-fill-2"></div>
    </div>

    【讨论】:

      【解决方案6】:

      我设法找到了一个也支持 IE11(某种)并在动画中包含幻灯片的解决方案: https://jsfiddle.net/5kphcLqg/

      @keyframes slideInFill {
        0% {
          width: 0;
          border-top-right-radius: 0;
          border-bottom-right-radius: 0;
        } 
      
        99% {
          border-top-right-radius: 0px;
          border-bottom-right-radius: 0px;
        }
      
        100% {
              border-top-right-radius: 16px;
          border-bottom-right-radius: 16px;
        }
      }
      
      @keyframes slideInBorder {
        from {
          width: 0;
        }
      }
       
      .container { 
        position: relative;
      }
      
      .borders {
        height: 24px;
        width: 280px;
        background: #DCDFDF;
        display: flex;
        border-radius: 16px;
        overflow: hidden;
        position: absolute;
        top: 0;
        box-sizing: border-box;
      }
      
      .borders-fill-1 {  
        position: relative;
        width: 20%;
        background: #06A2D4;
      }
      
      .animate {
        height: 24px;
        top: 0;   
        animation: slideInBorder 1s ease-in forwards;  
      }
      
      .borders-fill-1:after {
        content: '';
        position: absolute;
        height: 100%;
        width: 1px;
        background: white;
        right: 0;
        z-index: 9
      }
      
      .borders-fill-2:after {
        content: '';
        position: absolute;
        height: 100%;
        width: 1px;
        background: white; 
        right: 0;
        z-index: 9
      }
      
      .borders-fill-2 {
        width: 78%;
        background: #D31A47;  
        position: relative;
      }
      
      .fill-bg {
        background: #eaeaea;
        width: 280px;
        height: 24px;
        position: absolute;
        border-radius: 16px;
        background-clip: content-box;
        padding: 1px;
        box-sizing: border-box; 
      }
      
      .filling-wrapper {
        border-radius: 16px;
        width: 280px;
        height: 24px;
        position: absolute;
        overflow: hidden;
        border-right: 1px solid #D31A47;
      }
      
      .filling {
        width: 280px;
        height: 24px;
        position: absolute;
        background: linear-gradient(to right,      
          #31C4F3 20%,
          #F16172 20%,
          #F16172 98%,
          transparent 98%
        );
        animation: slideInFill 1s ease-in forwards; 
        border-top-left-radius: 16px;
        border-bottom-left-radius: 16px;
        padding: 1px;
        background-clip: content-box;
        box-sizing: border-box;
      }
      <div class="container">
          <div class="borders">
              <div class="borders-fill-1 animate"></div>
              <div class="borders-fill-2 animate"></div>
          </div>
          <div class="fill-bg"></div>
          <div class="filling">
          </div>
      </div>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-08-14
        • 2011-09-12
        • 1970-01-01
        • 2017-09-19
        • 1970-01-01
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多