漸變邊框的實現(xiàn)方式

前言

我們在 css 里可以直接使用 border 屬性指定元素的邊框鞭呕,但這樣的方法具有局限性,就是只能添加單色的邊框,如果需要給元素添加漸變的邊框杖爽,又該如何實現(xiàn)呢?

利用 border-image

我們可以使用 border-imagelinear-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;
}

效果如下圖所示:

border-image

這樣就完成了基本的漸變邊框慰安,但這種方法并不能支持圓角屬性,除非我們直接使用帶圓角的圖片聪铺。

利用 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萍鲸。

效果如下:

background-image

這樣我們就實現(xiàn)了漸變邊框的效果,且支持圓角屬性擦俐。

動態(tài)的漸變邊框

既然漸變邊框是背景模擬出來的脊阴,那我們也可以將線性漸變改為圓錐漸變(conic-gradient),這樣就有了彩虹色的邊框蚯瞧,當(dāng)然這需要瀏覽器的支持嘿期。

.btn {
  background-image: linear-gradient(#eee, #eee),
  conic-gradient(#ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
}

效果如下:

conic-gradient

如果我們想讓邊框旋轉(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));
      }
    }
  }
}

效果如下:

animation

可以看到動畫是一幀一幀的而不是平滑的蓖救,這是因為自定義屬性本身是不能動畫化的,不過現(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%;
}

效果如下:

animation

這樣就由一幀一幀的動畫變成了平滑的動畫雄人,把 background-size 設(shè)置成 200% 200%从橘,可以使動畫看起來更舒服。

注:conic-gradientcss houdini 都需要瀏覽器支持础钠,本文代碼在 chrome 71 可完美運行恰力,代碼可至 github 查看。

技術(shù)總結(jié)

我們可以利用 background-clipbackground-origin 去完成漸變邊框的需求旗吁,利用 CSS.registerProperty 使得自定義屬性也能夠和其他屬性一樣運行在動畫中踩萎。

其實我們還可以使用 clip-path 對漸變背景的顯示區(qū)域進行裁剪,從而也模擬出漸變邊框的效果很钓,但這種方案對圓角屬性的支持也不算太好香府,故本文暫不討論該方案。

本文如有紕漏之處码倦,還請各位大神指出企孩,有其他問題也可以在評論中提出,謝謝大家袁稽。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勿璃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子运提,更是在濱河造成了極大的恐慌蝗柔,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件民泵,死亡現(xiàn)場離奇詭異癣丧,居然都是意外死亡,警方通過查閱死者的電腦和手機栈妆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門胁编,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鳞尔,你說我怎么就攤上這事嬉橙。” “怎么了寥假?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵市框,是天一觀的道長。 經(jīng)常有香客問我糕韧,道長枫振,這世上最難降的妖魔是什么喻圃? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮粪滤,結(jié)果婚禮上斧拍,老公的妹妹穿的比我還像新娘。我一直安慰自己杖小,他們只是感情好肆汹,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著予权,像睡著了一般昂勉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上伟件,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天硼啤,我揣著相機與錄音,去河邊找鬼斧账。 笑死谴返,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咧织。 我是一名探鬼主播嗓袱,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼习绢!你這毒婦竟也來了渠抹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤闪萄,失蹤者是張志新(化名)和其女友劉穎梧却,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體败去,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡放航,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了圆裕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片广鳍。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吓妆,靈堂內(nèi)的尸體忽然破棺而出赊时,到底是詐尸還是另有隱情,我是刑警寧澤行拢,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布祖秒,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏竭缝。R本人自食惡果不足惜狐胎,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望歌馍。 院中可真熱鬧,春花似錦晕鹊、人聲如沸松却。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晓锻。三九已至,卻和暖如春飞几,著一層夾襖步出監(jiān)牢的瞬間砚哆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工屑墨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留躁锁,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓卵史,卻偏偏與公主長得像战转,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子以躯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容