简体   繁体   English

DIV 上的 CSS 动画渐变边框

[英]CSS animated gradient border on a DIV

I'm trying to create a loading DIV that has a border that looks like an indeterminate progress ring spinner.我正在尝试创建一个加载DIV ,它的边框看起来像一个不确定的进度环形微调器。

I'm pretty close based on one of the examples on https://css-tricks.com/gradient-borders-in-css/基于https://css-tricks.com/gradient-borders-in-css/上的示例之一,我非常接近

This is great when the border doesn't rotate.当边框不旋转时,这很好。 When you set the border in the :before element to match the transparent border in the gradient-box element then the static gradient border looks perfect.当您在:before元素中设置border以匹配gradient-box元素中的透明border ,静态渐变边框看起来很完美。

However, once the animation is added, because the whole :before element rotates you get a pretty odd effect - as shown in the example below.然而,一旦添加了动画,因为整个: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>

I've tried playing about with overflow: hidden;我试过玩溢出:隐藏; but the border just disappears.. is there any way to 'mask' the :before element in a way that whatever is behind this loading Div is still visible behind it and so that the border stays as its intended width?但边框只是消失了.. 有什么方法可以“屏蔽” :before 元素,使加载 Div 后面的任何内容仍然可见,以便边框保持其预期宽度?

Basically, my goal is that the colour gradient in the border rotates to give the effect of a spinning/rotating edge.基本上,我的目标是border中的颜色渐变旋转以产生旋转/旋转边缘的效果。

Hi is this what you are looking for?您好,这是您要找的吗?

What I did was I added a new div which will be the "mask" as well as a container div for both the mask and the loadingBox.我所做的是添加了一个新的 div,它将是“掩码”以及用于掩码和加载框的容器 div。

I then sized the mask to be a little larger than your visible area, make it a transparent background, and then gave it a large outline the same color as your background to effectively mask out a border.然后我将遮罩的大小设置为比您的可见区域大一点,使其成为透明背景,然后给它一个与背景颜色相同的大轮廓,以有效地遮住边框。 I then fiddled with z-indexs of the mask, the loadingbox and the before.然后我摆弄了面具的 z-indexs、loadingbox 和之前的。 I also added some actual borders on mask to box it out into a nice shape.我还在mask上添加了一些实际的边框,将其框成一个漂亮的形状。

Take a look:看一看:

 .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>

I like your original idea with using overflow: hidden , but to make it work I had to include an extra wrapper div.我喜欢你使用overflow: hidden原始想法,但为了使它工作,我必须包含一个额外的包装 div。

  • The outer wrapper defines a padding which serves as the display area for the gradient border外部包装器定义了一个填充,用作渐变边框的显示区域
  • The inner div is just the content box with a black background内部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>

An alternative: Using @property另一种选择:使用@property

There's a much more elegant solution using @property , but unfortunately it only works on Chrome.使用@property有一个更优雅的解决方案,但不幸的是它只适用于 Chrome。 I'm including here in case one day it becomes more universally supported or support for other browsers isn't important for your use case.我将其包括在内,以防有一天它变得更加普遍,或者对其他浏览器的支持对您的用例来说并不重要。

The conic-gradient function has a parameter that allows you to specify at what angle the gradient starts. conic-gradient函数有一个参数,可让您指定渐变开始的角度。 If we can animate just that parameter , perhaps using a CSS variable, then we can animate the border with just a single div and without actually rotating anything.如果我们可以只为那个参数设置动画,也许使用 CSS 变量,那么我们可以只用一个 div 设置边框动画,而无需实际旋转任何东西。

Unfortunately, without some hinting the browser doesn't know how to transition a CSS variable.不幸的是,没有一些提示浏览器不知道如何转换 CSS 变量。 Therefore, we use @property to indicate the variable is an angle, telling the browser how to transition it.因此,我们使用@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 indicates this will only work in Chrome and Edge as of this post.用于@property 的 CanIUse表示这仅适用于本文中的 Chrome 和 Edge

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM