在 CSS 过渡期间绘制边框颜色
Drawing border colors during a CSS transition
button {
background: none;
border: 0;
box-sizing: border-box;
margin: 1em;
padding: 1em 2em;
box-shadow: inset 0 0 0 2px #f45e61;
color: #f45e61;
font-size: inherit;
font-weight: 700;
position: relative;
vertical-align: middle;
}
button::before, button::after {
box-sizing: inherit;
content: " ";
position: absolute;
width: 100%;
height: 100%;
}
.draw {
transition: color 0.25s;
}
.draw::before, .draw::after {
border: 2px solid transparent;
width: 0;
height: 0;
transition: width 1.25s ease-out 1.25s, height 1.25s ease-out 1.25s;
}
.draw::before {
top: 0;
left: 0;
}
.draw::after {
bottom: 0;
right: 0;
}
.draw:hover {
color: #60daaa;
}
.draw:hover::before, .draw:hover::after {
width: 100%;
height: 100%;
}
.draw:hover::before {
border-top-color: #60daaa;
border-right-color: #60daaa;
transition: width 0.25s ease-out, height 0.25s ease-out 0.25s;
}
.draw:hover::after {
border-bottom-color: #60daaa;
border-left-color: #60daaa;
transition: border-color 0s ease-out 0.5s, width 0.25s ease-out 0.5s, height 0.25s ease-out 0.75s;
}
<section class="buttons">
<button class="draw">Draw</button>
</section>
我有一支工作笔 (https://codepen.io/anon/pen/vdgdxO),它可以在悬停时更改元素的边框颜色(右上左下),并进行一些过渡以使其平滑。
我希望能够 "reverse" 边框颜色在几秒后改变。基本上,我想在对方改变颜色时改变边框颜色:
- border-top 改变颜色
- 右边框改变颜色
- border-bottom 改变颜色 & border-top 变回原来的颜色
- border-left 改变颜色 & border-right 变回原来的颜色
- border-top 改变颜色 & border-bottom 变回原来的颜色
- border-right 改变颜色 & border-left 变回原来的颜色
等等
现在我只解决了颜色变化问题,但我不知道如何"reverse"。我也希望这种过渡永远循环,但我不知道从哪里开始。有什么建议吗?
我会使用多个 linear-gradient
和一个 复杂的 动画(通过对每个 size/position 进行动画处理)来获得最终结果。如果你掌握了诀窍,你可以轻松调整不同的值以获得你想要的任何动画。
.draw {
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa);
background-position: 0 0, 0 0, 0 100%, 0 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
animation: animate 1.4s linear infinite 0.2s;
}
@keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
}
<button class="draw">Draw</button>
它是如何工作的?
结构:我们有8个linear-gradient
。 4 将简单地创建初始边框并且不会移动(它们位于底层)并且 4 将用于绘制将在初始边框上方创建动画的线(它们位于顶层)。
顺序很重要,因为在背景属性中,每个渐变都有 8 个值。您会注意到 3px
值将简单地指定每个渐变的宽度或高度(类似于 border-width
)并且它在动画期间不会改变。
动画:我将调整每个渐变的position/size来创建动画。它分为两部分:一个小的过渡和一个大的动画。过渡仅用于创建动画的初始状态,这就是为什么用于过渡的持续时间与动画的延迟相同。
第一步是为顶部 边框从左到右设置动画。为此,渐变应位于 (0,0) [top,left]
,大小为 0% 3px [width height]
。然后我只需将大小更改为 100% 3px
,我将获得所需的动画(之前描述的 3px 不会改变)。
现在要为第二个边框设置动画,我们也这样做。我们需要一个位于 (100%,0) [top,right]
且大小为 3px 0% [width height]
的渐变,我们将其设置为 3px 100%
:
- 现在因为我们有两个边框,所以我们需要为第三个边框设置动画并隐藏第一个边框。我不会详细介绍第三个边框,因为它与上面的边框相似,所以让我们看看如何隐藏顶部的边框。第一个直观的想法是简单地将其大小设置回
0% 3px
但这只会创建反向动画,因此我们将有一个 从右到左 动画,这是不好的。这里的技巧是调整渐变的位置,使其成为 (100%,0) [top,right]
而不是 (0,0)
,因为当渐变为 100% 大小时,这两个位置是等效的(所以我们在上一步为第二个)。现在,我们可以将大小放回 0% 3px
,我们将有一个 从左到右 动画:
- 我们继续相同的逻辑,直到我们回到初始状态,通过在动画中指定
infinite
属性 我们将获得所需的效果。
所以主要的想法是有一个大小等于 0% 的渐变,我们在给定的方向上动画到全尺寸 (100%) 然后我们改变它的位置(这对全尺寸没有任何影响大小),然后将其大小设置为 0。我们将其与我们拥有的 4 个渐变混合。
更新
为了避免与所有这些渐变混淆,这里进行了更新,我在静态边框中使用了一个伪元素,因此我们只为动画保留了 4 个渐变:
.draw {
position:relative;
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61);
background-position: 0 0, 0 0, 0 100%, 0 100%;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:before {
content:"";
position:absolute;
z-index:-1;
top:0;
right:0;
left:0;
bottom:0;
border:3px solid #60daaa;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
animation: animate 1.4s linear infinite 0.2s;
}
@keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%
}
}
<button class="draw">Draw</button>
button {
background: none;
border: 0;
box-sizing: border-box;
margin: 1em;
padding: 1em 2em;
box-shadow: inset 0 0 0 2px #f45e61;
color: #f45e61;
font-size: inherit;
font-weight: 700;
position: relative;
vertical-align: middle;
}
button::before, button::after {
box-sizing: inherit;
content: " ";
position: absolute;
width: 100%;
height: 100%;
}
.draw {
transition: color 0.25s;
}
.draw::before, .draw::after {
border: 2px solid transparent;
width: 0;
height: 0;
transition: width 1.25s ease-out 1.25s, height 1.25s ease-out 1.25s;
}
.draw::before {
top: 0;
left: 0;
}
.draw::after {
bottom: 0;
right: 0;
}
.draw:hover {
color: #60daaa;
}
.draw:hover::before, .draw:hover::after {
width: 100%;
height: 100%;
}
.draw:hover::before {
border-top-color: #60daaa;
border-right-color: #60daaa;
transition: width 0.25s ease-out, height 0.25s ease-out 0.25s;
}
.draw:hover::after {
border-bottom-color: #60daaa;
border-left-color: #60daaa;
transition: border-color 0s ease-out 0.5s, width 0.25s ease-out 0.5s, height 0.25s ease-out 0.75s;
}
<section class="buttons">
<button class="draw">Draw</button>
</section>
我有一支工作笔 (https://codepen.io/anon/pen/vdgdxO),它可以在悬停时更改元素的边框颜色(右上左下),并进行一些过渡以使其平滑。
我希望能够 "reverse" 边框颜色在几秒后改变。基本上,我想在对方改变颜色时改变边框颜色:
- border-top 改变颜色
- 右边框改变颜色
- border-bottom 改变颜色 & border-top 变回原来的颜色
- border-left 改变颜色 & border-right 变回原来的颜色
- border-top 改变颜色 & border-bottom 变回原来的颜色
- border-right 改变颜色 & border-left 变回原来的颜色 等等
现在我只解决了颜色变化问题,但我不知道如何"reverse"。我也希望这种过渡永远循环,但我不知道从哪里开始。有什么建议吗?
我会使用多个 linear-gradient
和一个 复杂的 动画(通过对每个 size/position 进行动画处理)来获得最终结果。如果你掌握了诀窍,你可以轻松调整不同的值以获得你想要的任何动画。
.draw {
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa),
linear-gradient(#60daaa, #60daaa);
background-position: 0 0, 0 0, 0 100%, 0 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
animation: animate 1.4s linear infinite 0.2s;
}
@keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%,
0 0, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%,
3px 100%, 100% 3px, 100% 3px,3px 100%;
}
}
<button class="draw">Draw</button>
它是如何工作的?
结构:我们有8个linear-gradient
。 4 将简单地创建初始边框并且不会移动(它们位于底层)并且 4 将用于绘制将在初始边框上方创建动画的线(它们位于顶层)。
顺序很重要,因为在背景属性中,每个渐变都有 8 个值。您会注意到 3px
值将简单地指定每个渐变的宽度或高度(类似于 border-width
)并且它在动画期间不会改变。
动画:我将调整每个渐变的position/size来创建动画。它分为两部分:一个小的过渡和一个大的动画。过渡仅用于创建动画的初始状态,这就是为什么用于过渡的持续时间与动画的延迟相同。
第一步是为顶部 边框从左到右设置动画。为此,渐变应位于
(0,0) [top,left]
,大小为0% 3px [width height]
。然后我只需将大小更改为100% 3px
,我将获得所需的动画(之前描述的 3px 不会改变)。现在要为第二个边框设置动画,我们也这样做。我们需要一个位于
(100%,0) [top,right]
且大小为3px 0% [width height]
的渐变,我们将其设置为3px 100%
:
- 现在因为我们有两个边框,所以我们需要为第三个边框设置动画并隐藏第一个边框。我不会详细介绍第三个边框,因为它与上面的边框相似,所以让我们看看如何隐藏顶部的边框。第一个直观的想法是简单地将其大小设置回
0% 3px
但这只会创建反向动画,因此我们将有一个 从右到左 动画,这是不好的。这里的技巧是调整渐变的位置,使其成为(100%,0) [top,right]
而不是(0,0)
,因为当渐变为 100% 大小时,这两个位置是等效的(所以我们在上一步为第二个)。现在,我们可以将大小放回0% 3px
,我们将有一个 从左到右 动画:
- 我们继续相同的逻辑,直到我们回到初始状态,通过在动画中指定
infinite
属性 我们将获得所需的效果。
所以主要的想法是有一个大小等于 0% 的渐变,我们在给定的方向上动画到全尺寸 (100%) 然后我们改变它的位置(这对全尺寸没有任何影响大小),然后将其大小设置为 0。我们将其与我们拥有的 4 个渐变混合。
更新
为了避免与所有这些渐变混淆,这里进行了更新,我在静态边框中使用了一个伪元素,因此我们只为动画保留了 4 个渐变:
.draw {
position:relative;
padding: 20px 50px;
outline:none;
border: none;
box-shadow: none;
background-image:
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61),
linear-gradient(#f45e61, #f45e61);
background-position: 0 0, 0 0, 0 100%, 0 100%;
background-size: 3px 0%, 0% 3px, 0% 3px, 3px 0%;
background-color:transparent;
background-repeat:no-repeat;
transition:0.2s linear;
}
.draw:before {
content:"";
position:absolute;
z-index:-1;
top:0;
right:0;
left:0;
bottom:0;
border:3px solid #60daaa;
}
.draw:hover {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
animation: animate 1.4s linear infinite 0.2s;
}
@keyframes animate {
0% {
background-position: 0 100%, 0 0, 0 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%;
}
40% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 0;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 100%;
}
60% {
background-position: 0 100%, 100% 0, 100% 100%, 100% 100%;
background-size: 3px 0%, 0% 3px, 100% 3px,3px 100%
}
70% {
background-position: 0 100%, 100% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 100% 3px,3px 0%;
}
80% {
background-position: 0% 0%, 0% 0, 0% 100%, 100% 100%;
background-size: 3px 100%, 0% 3px, 0% 3px,3px 0%;
}
100% {
background-position: 0% 0%, 0 0, 0 100%, 100% 100%;
background-size: 3px 0%, 100% 3px, 0% 3px,3px 0%
}
}
<button class="draw">Draw</button>