CSS 變量由淺入深,提高效率必備知識!

做者: Ahmad Shadeed
譯者:前端小智
來源:ishadeedcss

有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。html

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。前端

CSS變量(又名自定義屬性)已在Web瀏覽器中支持了近四年。 我通常也會根據項目狀況使用它們。 它們很是有用且易於使用,可是前端開發人員一般可能會誤用或誤解它們。git

簡介

CSS變量是在CSS文檔中定義的值,其目的是可重用性並減小CSS值中的冗餘。 下面是一個基本示例。github

clipboard.png

.section {
  border: 2px solid #235ad1;
}

.section-title {
  color: #235ad1;
}

.section-title::before {
  content: "";
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: #235ad1;
}

在此代碼段中,#235ad1使用了3次。 想象一下,對於一個大型項目,不一樣的CSS文件,若是哪天被要求更改顏色。 咱們能夠作的最好快的方式就是「查找並替換」。面試

使用CSS變量,能夠更快解決這個問題。 定義變量名須要用--開頭。 首先,咱們如今將在:root<html>元素中定義變量。編程

:root {
  --color-primary: #235ad1;
}

.section {
  border: 2px solid var(--color-primary);
}

.section-title {
  color: var(--color-primary);
}

.section-title::before {
  /* Other styles */
  background-color: var(--color-primary);
}

是否是比前面的乾淨得多? --color-primary變量是全局變量,由於咱們在:root元素中定義了它。 可是,咱們還能夠將變量範圍限定到整個文檔中的某些元素。瀏覽器

命名變量

與編程語言命名變量類似,CSS 變量的有效命名應包含字母數字字符,下劃線和破折號。 另外,值得一提的是 CSS 變量區分大小寫。微信

/* 合法命名 */
:root {
    --primary-color: #222;
    --_primary-color: #222;
    --12-primary-color: #222;
    --primay-color-12: #222;
}

/* 非法命名 */
:root {
    --primary color: #222; /* Spacings are not allowed */
    --primary$%#%$#
}

做用域

CSS 變量也有本身的做用域,這個概念相似於其餘編程語言。 以 JS 爲例:app

:root {
  --primary-color: #235ad1;
}

.section-title {
  --primary-color: d12374;
  color: var(--primary-color);
}

變量element是全局的,所以能夠在cool()函數內部訪問。 可是,只能在cool()函數中訪問變量otherElement

:root {
  --primary-color: #235ad1;
}

.section-title {
  --primary-color: d12374;
  color: var(--primary-color);
}

變量--primary-color是全局變量,能夠從文檔中的任何地方訪問。 變量 --primary-color因爲是在.section-title定義的,因此只能在.section-title中訪問。

下面是一個比較直觀的示例圖片,能夠增強咱們的理解:

clipboard.png

變量--primary-color用於標題顏色。 咱們想爲做者名最新文章標題自定義顏色,所以咱們須要將--primary-color覆蓋。 這一樣適用於--unit變量。

/* 全局變量 */
:root {
  --primary-color: #235ad1;
  --unit: 1rem;
}

/* section-title 默認的顏色和間距 */
.section-title {
  color: var(--primary-color);
  margin-bottom: var(--unit);
}

/* 覆蓋 section-title 樣式 */
.featured-authors .section-title {
  --primary-color: #d16823;
}

.latest-articles .section-title {
  --primary-color: #d12374;
  --unit: 2rem;
}

回退方案

這裏的回退不是不支持 CSS 變量的回退,而是 CSS 變量能夠支持回退方案。考慮如下示例:

.section-title {
  color: var(--primary-color, #222);
}

注意,var()有多個值。第二個#221只在變量--primary-color因爲某種緣由沒有定義的狀況下有效。不只如此,咱們還能夠將var()嵌套到另外一個var()中。

.section-title {
  color: var(--primary-color, var(--black, #222));
}

在變量值依賴於某個動做的狀況下,該特性很是有用。當變量沒有值時,爲它提供一個回退很重要。

用例一:控制組件的大小

clipboard.png

在設計系統中,按鈕一般有多種尺寸。 一般,按鈕能夠具備三種尺寸(Small, normal, large)。 使用 CSS 變量來實現它並不容易:

.button {
  --unit: 1rem;
  padding: var(--unit);
}

.button--small {
  --unit: 0.5rem;
}

.button--large {
  --unit: 1.5rem;
}

經過在按鈕組件做用域內更改變量--unit,咱們建立了按鈕的不一樣變體。

用例二:CSS 變量和 HSL 顏色

HSL表明色調,飽和度,亮度。色相的值決定了顏色,飽和度和亮度值能夠控制顏色的深淺。

clipboard.png

:root {
  --primary-h: 221;
  --primary-s: 71%;
  --primary-b: 48%;
}

.button {
  background-color: hsl(var(--primary-h), var(--primary-s), var(--primary-b));
  transition: background-color 0.3s ease-out;
}

/* 使背景更暗 */
.button:hover {
  --primary-b: 33%;
}

這裏何經過減少變量--primary-b使按鈕變暗。

用例三:比例調整

若是您使用過PhotoshopSketchFigmaAdobe XD之類的設計程序,那麼咱們會想在調整元素大小的同時按住Shift鍵以免扭曲它。

在CSS中,沒有直接的方法來作到這一點,可是咱們有一個簡單的解決方法,使用CSS變量。

clipboard.png

假設有一個圖標,而且其寬度和高度應該相等。 我定義了變量--size,用於寬度和高度。

.icon {
  --size: 22px;
  width: var(--size);
  height: var(--size);
}

如今,您只需更改--size變量的值便可模擬Shift調整大小的效果。

用例四:CSS Grid

CSS 變量對於網格很是有用。 假設但願網格容器根據定義的首選寬度顯示其子項。 與爲每一個變體建立類並複製CSS相比,使用變量更容易作到這一點。

clipboard.png

.wrapper {
  --item-width: 300px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
  grid-gap: 1rem;
}

.wrapper-2 {
  --item-width: 500px;

這樣,咱們能夠建立一個完整的網格系統,該系統靈活,易於維護,而且能夠在其餘項目中使用。 能夠將相同的概念應用於grid-gap屬性。

wrapper {
  --item-width: 300px;
  --gap: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
}

.wrapper.gap-1 {
  --gap: 16px;
}

clipboard.png

用例五:全值聲明,CSS 漸變

以全值表示,例如,相似漸變的東西。 若是整個系統中使用漸變或背景,將其存儲到CSS變量中多是一件好事。

:root {
  --primary-gradient: linear-gradient(150deg, #235ad1, #23d1a8);
}

.element {
  background-image: var(--primary-gradient);
}

或者咱們能夠存儲一個值。 以角度爲例:

.element {
  --angle: 150deg;
  background-image: linear-gradient(var(--angle), #235ad1, #23d1a8);
}

.element.inverted {
  --angle: -150deg;
}

clipboard.png

用例六: Background Position

咱們能夠在 CSS 變量中包含多個值,這在須要根據特定上下文將元素放置在不一樣位置的狀況下頗有用。

clipboard.png

.table {
  --size: 50px;
  --pos: left center;
  background: #ccc linear-gradient(#000, #000) no-repeat;
  background-size: var(--size) var(--size);
  background-position: var(--pos);
}

用例七: 在明暗模式之間切換

如今,網站比以往任什麼時候候都更須要深色和淺色模式。 使用CSS變量,咱們能夠存儲它們的兩個版本,並根據用戶或系統偏好在它們之間切換。

clipboard.png

:root {
  --text-color: #434343;
  --border-color: #d2d2d2;
  --main-bg-color: #fff;
  --action-bg-color: #f9f7f7;
}

/* 添加到`<html>`元素的類*/
.dark-mode {
  --text-color: #e9e9e9;
  --border-color: #434343;
  --main-bg-color: #434343;
  --action-bg-color: #363636;
}

圖片描述

用例八: 設置默認值

在某些狀況下,您將須要使用JavaScript設置CSS變量。 假設咱們須要獲取可擴展組件的高度。

變量--details-height-open爲空,它將被添加到特定的HTML元素中。 當JavaScript因爲某種緣由失敗時,提供適當的默認值或後備值很重要。

.section.is-active {
  max-height: var(--details-height-open, auto);
}

auto值是 JS 失敗時的回退值,而且沒有定義CSS變量——details-height-open

用例九: 控制 wrapper 寬度

clipboard.png

網站wrapper 能夠有多種變化。有時候是須要一個小包裝一個頁面,一個大包裝另外一個頁面。在這種狀況下,合併CSS變量多是有用的。

.wrapper {
  --size: 1140px;
  max-width: var(--size);
}

.wrapper--small {
  --size: 800px;
}

用例十一: 動態網格項目

咱們能夠在style屬性中添加--item-width變量,僅此而已。 例如,這種方法能夠幫助創建網格原型。

HTML

<div class="wrapper" style="--item-width: 250px;">
  <div></div>
  <div></div>
  <div></div>
</div>

CSS

.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--item-width), 1fr));
  grid-gap: 1rem;
}

事例:https://codepen.io/shadeed/pe...

用例十二: 用戶頭像

clipboard.png

另外一個有用的用例是大小調整元素。 假設咱們須要四種不一樣大小的用戶頭像,而且只能使用一個變量來控制其大小。

<img src="user.jpg" alt="" class="c-avatar" style="--size: 1" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 2" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 3" />
<img src="user.jpg" alt="" class="c-avatar" style="--size: 4" />
.c-avatar {
  display: inline-block;
  width: calc(var(--size, 1) * 30px);
  height: calc(var(--size, 1) * 30px);
}

用例十三: 媒體查詢

組合CSS變量和媒體查詢對於調整整個網站中使用的變量很是有用。 我能想到的最簡單的示例是更改間距值。

:root {
  --gutter: 8px;
}

@media (min-width: 800px) {
  :root {
    --gutter: 16px;
  }
}

使用--gutter變量的任何元素都將根據視口大小更改其間距,這是否是很棒嗎?

用例十四:繼承

是的,CSS變量確實繼承。若是父元素中定義了CSS變量,那麼子元素將繼承相同的CSS變量。咱們看下面的例子:

HTML

<div class="parent">
  <p class="child"></p>
</div>

css

.parent {
  --size: 20px;
}

.child {
  font-size: var(--size);
}

.child元素能夠訪問變量--size,由於它從父元素繼承了它。頗有趣,那它在實際的項目中有啥用呢?

clipboard.png

咱們有一組如下需求的操做項

  • 改變一個變量就能夠改變全部項的大小
  • 間距應該是動態的

HTML

<div class="actions">
  <div class="actions__item"></div>
  <div class="actions__item"></div>
  <div class="actions__item"></div>
</div>

CSS

.actions {
  --size: 50px;
  display: flex;
  gap: calc(var(--size) / 5);
}

.actions--m {
  --size: 70px;
}

.actions__item {
  width: var(--size);
  height: var(--size);
}

請注意,這裏是如何將變量--size用於flexbox gap屬性的。 這意味着間距能夠是動態的,而且取決於--size變量。

另外一個有用的例子是使用CSS變量繼承來定製CSS動畫:

@keyframes breath {
  from {
    transform: scale(var(--scaleStart));
  }
  to {
    transform: scale(var(--scaleEnd));
  }
}

.walk {
  --scaleStart: 0.3;
  --scaleEnd: 1.7;
  animation: breath 2s alternate;
}

.run {
  --scaleStart: 0.8;
  --scaleEnd: 1.2;
  animation: breath 0.5s alternate;
}

這樣,咱們就不須要定義@keyframes兩次,它將繼承.walk.run元素的定製CSS 變量。

CSS 變量的工做方式

var()函數中的CSS變量無效時,瀏覽器將根據所使用的屬性用初始值或繼承值替換。

:root {
  --main-color: 16px;
}

.section-title {
  color: var(--main-color);
}

我使用16pxcolor屬性的值。 這是徹底錯誤的。 因爲color屬性是繼承的,所以瀏覽器將執行如下操做:

  • 該屬性是否可繼承?

    • 若是是,父節點是否擁有該屬性?

      • 是的,繼承該值
      • 否:設置爲初始值
    • 否:設置爲初始值

下面解釋瀏覽器工做的流程圖。

clipboard.png

網址值

咱們可能沒法控制網頁中的全部資源,其中一些必須在線託管。 在這種狀況下,您能夠將連接的URL值存儲在CSS變量中。

:root {
  --main-bg: url("https://example.com/cool-image.jpg");
}

.section {
  background: var(--main-bg);
}

可是,能想知道是否可使用url()插入 CSS 變量。 考慮如下

:root {
  --main-bg: "https://example.com/cool-image.jpg";
}

.section {
  background: url(var(--main-bg));
}

因爲var(--main-bg)被視爲url自己,所以無效。 當瀏覽器計算出該值時,該值將再也不有效,而且將沒法按預期運行。

存儲多個值

CSS 變量也能夠表示多個值,看下面的例子:

clipboard.png

:root {
  --main-color: 35, 90, 209;
}

.section-title {
  color: rgba(var(--main-color), 0.75);
}

在示例中,咱們有一個rgba()函數,而且RGB值存儲在CSS變量中,以逗號分隔。 若是咱們想根據元素調整alpha值,這樣作能夠提供靈活性。惟一的缺點是沒法使用DevTools顏色選擇器來調整rgba值。

另外一個例子是將它與background屬性一塊兒使用。

:root {
  --bg: linear-gradient(#000, #000) center/50px;
}

.section {
  background: var(--bg);
}

.section--unique {
  background: var(--bg) no-repeat;
}

@keyframes規則中的動畫變量

若是你閱讀過CSS變量規範,則可能會讀到「動畫污染」一詞。 這個想法是,在@keyframes規則中使用CSS變量時,沒法對其進行動畫處理。

html

<div class="box"></div>

CSS

.box {
  width: 50px;
  height: 50px;
  background: #222;
  --offset: 0;
  transform: translateX(var(--offset));
  animation: moveBox 1s infinite alternate;
}

@keyframes moveBox {
  0% {
    --offset: 0;
  }
  50% {
    --offset: 50px;
  }
  100% {
    --offset: 100px;
  }
}

動畫沒法順利進行。 它將僅對值 (0, 50px, 100px)進行動畫處理。 根據CSS規範:

@keyframes規則中使用的任何自定義屬性都會受到動畫污染,這將影響經過動畫屬性中的 var()函數引用它時如何處理它。

若是咱們但願上述動畫可以正常工做,則應採用老式的方法。 這意味着,咱們須要用要設置動畫的實際CSS屬性替換變量。

@keyframes moveBox {
  0% {
    transform: translateX(0);
  }
  50% {
    transform: translateX(50px);
  }
  100% {
    transform: translateX(100px);
  }
}

計算

你可能不知道可使用 CSS 變量進行計算。 考慮下面示例:

.c-avatar {
  display: inline-block;
  width: calc(var(--size, 1) * 30px);
  height: calc(var(--size, 1) * 30px);
}

.c-avatar 大小會有不一樣的變化。 我將默認值設置爲1,因此默認大小爲(30px * 30px)。 注意不一樣的類變化以及更改--size值如何致使化身的大小變化。

.c-avatar--small {
  --size: 2;
}

.c-avatar--medium {
  --size: 3;
}

.c-avatar--large {
  --size: 4;
}

Devtools和CSS變量

咱們能夠在瀏覽器DevTools中使用一些有用的技巧,這樣就能更輕鬆地使用CSS變量。

看到顏色

使用CSS變量時,看到顏色或背景值的視覺指示器是否有用? Chrome和Edge證實了這一點。

clipboard.png

計算值

要查看CSS變量的計算值,只要將鼠標懸停或單擊便可。

clipboard.png

禁用CSS變量

當咱們須要從使用CSS變量的全部元素中禁用CSS變量時,能夠經過從定義它的元素中取消選中它來實現。 參見下圖:

clipboard.png

本文介紹了 CSS 變量的不少內容,但願能對你有些幫助,二創不易,還望點個贊+轉發。


代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://ishadeed.com/article/...

交流

有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。

相關文章
相關標籤/搜索