CSS DIV 上的动画渐变边框
CSS animated gradient border on a DIV
我正在尝试创建一个加载 DIV
,它的边框看起来像一个不确定的进度环微调器。
根据 https://css-tricks.com/gradient-borders-in-css/
上的示例之一,我非常接近
当边框不旋转时这很好。当您在 :before
元素中设置 border
以匹配 gradient-box
元素中的透明 border
时,静态渐变边框看起来很完美。
但是,添加动画后,由于整个 :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>
我试过 overflow: hidden;但是边框就消失了.. 有什么办法可以 'mask' :before 元素以某种方式使此加载 Div 后面的任何内容在其后面仍然可见,从而使边框保持其预期宽度?
基本上,我的目标是 border
中的颜色渐变旋转以产生 spinning/rotating 边缘的效果。
嗨,这是你要找的吗?
我所做的是我添加了一个新的 div 这将是“掩码”以及用于掩码和 loadingBox 的容器 div。
然后我将蒙版的大小设置为比您的可见区域大一点,使其成为透明背景,然后给它一个与背景颜色相同的大轮廓以有效地遮盖边框。然后我摆弄了蒙版、加载框和之前的 z-index。我还在 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>
我喜欢你最初使用 overflow: hidden
的想法,但为了让它发挥作用,我必须包含一个额外的包装器 div。
- 外包装定义了一个padding作为渐变边框的显示区域
- 里面的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 有一个更优雅的解决方案,但不幸的是它只适用于 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>
CanIUse for @property 表示这 仅适用于 Chrome 和 Edge post。
我正在尝试创建一个加载 DIV
,它的边框看起来像一个不确定的进度环微调器。
根据 https://css-tricks.com/gradient-borders-in-css/
上的示例之一,我非常接近当边框不旋转时这很好。当您在 :before
元素中设置 border
以匹配 gradient-box
元素中的透明 border
时,静态渐变边框看起来很完美。
但是,添加动画后,由于整个 :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>
我试过 overflow: hidden;但是边框就消失了.. 有什么办法可以 'mask' :before 元素以某种方式使此加载 Div 后面的任何内容在其后面仍然可见,从而使边框保持其预期宽度?
基本上,我的目标是 border
中的颜色渐变旋转以产生 spinning/rotating 边缘的效果。
嗨,这是你要找的吗?
我所做的是我添加了一个新的 div 这将是“掩码”以及用于掩码和 loadingBox 的容器 div。
然后我将蒙版的大小设置为比您的可见区域大一点,使其成为透明背景,然后给它一个与背景颜色相同的大轮廓以有效地遮盖边框。然后我摆弄了蒙版、加载框和之前的 z-index。我还在 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>
我喜欢你最初使用 overflow: hidden
的想法,但为了让它发挥作用,我必须包含一个额外的包装器 div。
- 外包装定义了一个padding作为渐变边框的显示区域
- 里面的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 有一个更优雅的解决方案,但不幸的是它只适用于 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>
CanIUse for @property 表示这 仅适用于 Chrome 和 Edge post。