0

我正在尝试创建一个加载DIV,其边框看起来像一个不确定的进度环微调器。

根据https://css-tricks.com/gradient-borders-in-css/上的示例之一,我非常接近

当边框不旋转时,这很棒。当您border:before元素中设置 以匹配元素中的透明border时,gradient-box静态渐变边框看起来很完美。

但是,一旦添加了动画,因为整个:before元素会旋转,您会得到一个非常奇怪的效果 - 如下例所示。

.gradient-box {
  
  display: flex;
  align-items: center;
  width: 90%;
  margin: auto;
  max-width: 22em;

  position: relative;
  padding: 30% 2em;
  box-sizing: border-box;

  border: 5px solid blue;
  color: #FFF;
  background: #000;
  background-clip: padding-box; /* !importanté */
  border: solid 5px transparent; /* !importanté */
  border-radius: 1em;

}

.gradient-box:before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -1;
    margin: -35px; /* !importanté */
    border-radius: inherit; /* !importanté */
    background: conic-gradient(#0000ff00, #ff0000ff);
    -webkit-animation: rotate-border 5s linear infinite;
    -moz-animation: rotate-border 5s linear infinite;
    -o-animation: rotate-border 5s linear infinite;
    animation: rotate-border 3s linear infinite;
}

@keyframes rotate-border {
    to {
        transform: rotate(360deg);
    }
}

html { height: 100%; background: #000; display: flex; }
body { margin: auto; }
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Loading DIV Test</title>
</head>
<body>

<div id="loadingBox" class="gradient-box">
<p>Loading.</p>
</div>

</body>

我试过玩溢出:隐藏;但是边框只是消失了..有什么方法可以“屏蔽” :before 元素,以使该加载 Div 后面的任何内容在其后面仍然可见,从而使边框保持其预期宽度?

基本上,我的目标是旋转中的颜色渐变border以产生旋转/旋转边缘的效果。

4

2 回答 2

1

我喜欢你最初的想法 using overflow: hidden,但为了让它工作,我必须包含一个额外的包装器 div。

  • 外包装定义了一个填充,用作渐变边框的显示区域
  • 内部 div 只是带有黑色背景的内容框

.loading-box-container {
  --size: 200px;
  --radius: 10px;
  position: relative;
  width: var(--size);
  height: var(--size);
  padding: var(--radius);
  border-radius: var(--radius);
  overflow: hidden;
}

.loading-box {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: #000;
  border-radius: var(--radius);
}

.loading-box-container::before {
  content: '';
  width: 150%; /* The upscaling allows the box to fill its container even when rotated */
  height: 150%;
  position: absolute;
  top: -25%; left: -25%;
  background: conic-gradient(#0000ff00, #ff0000ff);
  animation: rotate-border 5s linear infinite;
}

@keyframes rotate-border {
    to {
        transform: rotate(360deg);
    }
}
<div class="loading-box-container">
  <div class="loading-box">
    <p>Loading</p>
  </div>
</div>

另一种选择:使用@property

使用@property有一个更优雅的解决方案,但不幸的是它只适用于 Chrome。我将这里包括在内,以防有一天它会得到更普遍的支持,或者对其他浏览器的支持对您的用例并不重要。

conic-gradient函数有一个参数,允许您指定渐变开始的角度。如果我们可以只为那个参数设置动画,也许使用 CSS 变量,那么我们可以只用一个 div 为边框设置动画,而无需实际旋转任何东西。

不幸的是,没有一些提示,浏览器不知道如何转换 CSS 变量。因此,我们用@property一个角度来表示变量,告诉浏览器如何过渡它。

@property --rotation {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

.loading-box {
  --size: 200px;
  --radius: 10px;
  position: relative;
  width: var(--size);
  height: var(--size);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: #000;
  border-radius: var(--radius);
  margin: var(--radius);
}

.loading-box::before {
  --rotation: 0deg;
  content: '';
  width: calc(100% + 2 * var(--radius));
  height: calc(100% + 2 * var(--radius));
  border-radius: var(--radius);
  position: absolute;
  top: calc(-1 * var(--radius)); left: calc(-1 * var(--radius));
  background: conic-gradient(from var(--rotation), #0000ff00, #ff0000ff);
  animation: rotate-border 5s linear infinite;
  z-index: -1;
}

@keyframes rotate-border {
    to {
        --rotation: 360deg;
    }
}
<div class="loading-box">
  <p>Loading</p>
</div>

@property 的 CanIUse表明这在本文中仅适用于 Chrome 和 Edge

于 2021-07-23T13:41:08.213 回答
0

嗨,这是你要找的吗?

我所做的是添加了一个新的 div,它将作为“掩码”以及用于掩码和加载框的容器 div。

然后,我将蒙版的大小设置为比您的可见区域大一点,使其成为透明背景,然后给它一个与背景颜色相同的大轮廓,以有效地掩盖边框。然后我摆弄了掩码、加载框和之前的 z-indexs。我还添加了一些实际的边框以mask将其框出一个漂亮的形状。

看一看:

.gradient-box {
  
  display: flex;
  align-items: center;
  width: 90%;
  margin: auto;
  max-width: 22em;

  position: relative;
  padding: 30% 2em;
  box-sizing: border-box;

  border: 5px solid blue;
  color: #FFF;
  background: #000;
  background-clip: padding-box; /* !importanté */
  border: solid 5px transparent; /* !importanté */
  border-radius: 1em;

}

.gradient-box:before {
    content: '';
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -3;
    margin: -35px; /* !importanté */
    border-radius: inherit; /* !importanté */
    background: conic-gradient(#0000ff00, #ff0000ff);
    -webkit-animation: rotate-border 5s linear infinite;
    -moz-animation: rotate-border 5s linear infinite;
    -o-animation: rotate-border 5s linear infinite;
    animation: rotate-border 3s linear infinite;
}

@keyframes rotate-border {
    to {
        transform: rotate(360deg);
    }
}

html { height: 100%; background: #000; display: flex; }
body { margin: auto; }

.mask {
  position: absolute;
   box-sizing: border-box;
background-color: transparent; 
 outline: 65px solid black;
height: 100%;
  width: 100%;
  border: 2px solid black;
  border-left: 7px solid black;
  border-right: 7px solid black;
  z-index: -1;
}

.container {
  position: relative;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Loading DIV Test</title>
</head>
<body>
<div class="container">
<div class="mask"></div>
<div id="loadingBox" class="gradient-box">
<p>Loading.</p>
</div>
  </div>
</body>

于 2021-07-23T12:50:12.053 回答