前言
我們在 css 里可以直接使用 border
屬性指定元素的邊框鞭呕,但這樣的方法具有局限性,就是只能添加單色的邊框,如果需要給元素添加漸變的邊框杖爽,又該如何實現(xiàn)呢?
利用 border-image
我們可以使用 border-image 和 linear-gradient() 實現(xiàn)漸變的邊框紫皇。
<template>
<div :class="$style.btn">
<slot>button</slot>
</div>
</template>
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
user-select: none;
border: 4px solid transparent;
border-image: linear-gradient(#e66465, #9198e5);
padding: 8px 16px;
font-size: 32px;
}
效果如下圖所示:
這樣就完成了基本的漸變邊框慰安,但這種方法并不能支持圓角屬性,除非我們直接使用帶圓角的圖片聪铺。
利用 background
CSS SECRETS 中第二章第八節(jié)提到化焕,可以利用疊加的背景圖片去模擬邊框效果,利用這一思想铃剔,我們在漸變的背景之上疊加一個原有的背景撒桨,就能達到我們想要的效果查刻,而且因為利用的是 background
,所以圓角屬性也能得到支持凤类,一舉兩得穗泵。
.btn {
border-radius: 8px; /* 圓角屬性測試 */
background-image: linear-gradient(#eee, #eee), /* 底色,即原有的背景 */
linear-gradient(#e66465, #9198e5); /* 模擬漸變邊框 */
background-clip: padding-box, border-box;
background-origin: border-box;
}
說明:
- 因為我們需要將底色覆蓋在漸變背景之上踱蠢,層級最高火欧,所以底色背景是
background-image
的第一項,漸變背景為第二項茎截。- 由于是模擬邊框效果苇侵,所以底色的繪制區(qū)域為
padding-box
,漸變背景的繪制區(qū)域為border-box
企锌。- 上面所說的覆蓋背景榆浓,其實指的是覆蓋背景區(qū)域,而元素的背景區(qū)域是由
background-origin
屬性來決定的撕攒,默認值是padding-box
陡鹃,故默認情況下,漸變背景是填不滿整個元素的抖坪,需要改為border-box
萍鲸。
效果如下:
這樣我們就實現(xiàn)了漸變邊框的效果,且支持圓角屬性擦俐。
動態(tài)的漸變邊框
既然漸變邊框是背景模擬出來的脊阴,那我們也可以將線性漸變改為圓錐漸變(conic-gradient),這樣就有了彩虹色的邊框蚯瞧,當(dāng)然這需要瀏覽器的支持嘿期。
.btn {
background-image: linear-gradient(#eee, #eee),
conic-gradient(#ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
}
效果如下:
如果我們想讓邊框旋轉(zhuǎn)起來,我們可以先舍棄上面的解決方案埋合,而是用兩個元素备徐,一個元素充當(dāng)漸變背景,一個元素覆蓋到背景上面甚颂,然后兩者做反向的旋轉(zhuǎn)動畫即可蜜猾,但我們偏不這么做,就是要用一個元素做到旋轉(zhuǎn)效果振诬,該如何做呢瓣铣?
其實我們可以利用 CSS 自定義屬性及 @keyframe
去實現(xiàn),首先定義6個基本顏色構(gòu)成一個數(shù)組贷揽,然后在動畫的每一幀,進行顏色數(shù)組的左移操作梦碗,就能實現(xiàn)旋轉(zhuǎn)效果禽绪。
scss 代碼如下:
$colors: (#ff0000), (#ffff00), (#00ff00), (#00ffff), (#0000ff), (#ff00ff);
$colorSize: length($colors);
@function getIndex($len, $index) {
@if $index > $len {
@return $index - $len;
}
@return $index;
}
.btn {
@for $i from 1 through $colorSize {
#{--color + $i}: nth($colors, $i);
}
background-image: linear-gradient(#eee, #eee),
conic-gradient(var(--color1), var(--color2), var(--color3), var(--color4), var(--color5), var(--color6), var(--color1));
animation: rotate 5s linear infinite;
}
@keyframes rotate {
@for $i from 1 through $colorSize {
#{$i * 100% / $colorSize} {
@for $j from 1 through $colorSize {
#{--color + $j}: nth($colors, getIndex($colorSize, $i + $j));
}
}
}
}
效果如下:
可以看到動畫是一幀一幀的而不是平滑的蓖救,這是因為自定義屬性本身是不能動畫化的,不過現(xiàn)在有了css houdini印屁,這樣我們就能手動注冊自定義屬性循捺,使得自定義屬性可以動畫化。
增加 js:
const colors = [
'#ff0000',
'#ffff00',
'#00ff00',
'#00ffff',
'#0000ff',
'#ff00ff',
];
colors.forEach((color, index) => {
CSS.registerProperty({
name: `--color${index + 1}`,
syntax: '<color>',
initialValue: color,
inherits: true,
});
});
增加 scss:
.btn {
background-size: 200% 200%;
}
效果如下:
這樣就由一幀一幀的動畫變成了平滑的動畫雄人,把 background-size
設(shè)置成 200% 200%
从橘,可以使動畫看起來更舒服。
注:
conic-gradient
和css houdini
都需要瀏覽器支持础钠,本文代碼在 chrome 71 可完美運行恰力,代碼可至 github 查看。
技術(shù)總結(jié)
我們可以利用 background-clip
和 background-origin
去完成漸變邊框的需求旗吁,利用 CSS.registerProperty
使得自定義屬性也能夠和其他屬性一樣運行在動畫中踩萎。
其實我們還可以使用 clip-path
對漸變背景的顯示區(qū)域進行裁剪,從而也模擬出漸變邊框的效果很钓,但這種方案對圓角屬性的支持也不算太好香府,故本文暫不討論該方案。
本文如有紕漏之處码倦,還請各位大神指出企孩,有其他問題也可以在評論中提出,謝謝大家袁稽。