做者: Ahmad Shadeed
譯者:前端小智
來源:ishadeedcss有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。html
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。前端
CSS變量(又名自定義屬性)已在Web瀏覽器中支持了近四年。 我通常也會根據項目狀況使用它們。 它們很是有用且易於使用,可是前端開發人員一般可能會誤用或誤解它們。git
CSS變量是在CSS文檔中定義的值,其目的是可重用性並減小CSS值中的冗餘。 下面是一個基本示例。github
.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
中訪問。
下面是一個比較直觀的示例圖片,能夠增強咱們的理解:
變量--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)); }
在變量值依賴於某個動做的狀況下,該特性很是有用。當變量沒有值時,爲它提供一個回退很重要。
在設計系統中,按鈕一般有多種尺寸。 一般,按鈕能夠具備三種尺寸(Small
, normal
, large
)。 使用 CSS 變量來實現它並不容易:
.button { --unit: 1rem; padding: var(--unit); } .button--small { --unit: 0.5rem; } .button--large { --unit: 1.5rem; }
經過在按鈕組件做用域內更改變量--unit
,咱們建立了按鈕的不一樣變體。
HSL表明色調,飽和度,亮度。色相的值決定了顏色,飽和度和亮度值能夠控制顏色的深淺。
: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
使按鈕變暗。
若是您使用過Photoshop
,Sketch
,Figma
或Adobe XD
之類的設計程序,那麼咱們會想在調整元素大小的同時按住Shift
鍵以免扭曲它。
在CSS中,沒有直接的方法來作到這一點,可是咱們有一個簡單的解決方法,使用CSS變量。
假設有一個圖標,而且其寬度和高度應該相等。 我定義了變量--size
,用於寬度和高度。
.icon { --size: 22px; width: var(--size); height: var(--size); }
如今,您只需更改--size
變量的值便可模擬Shift
調整大小的效果。
CSS 變量對於網格很是有用。 假設但願網格容器根據定義的首選寬度顯示其子項。 與爲每一個變體建立類並複製CSS相比,使用變量更容易作到這一點。
.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; }
以全值表示,例如,相似漸變的東西。 若是整個系統中使用漸變或背景,將其存儲到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; }
咱們能夠在 CSS 變量中包含多個值,這在須要根據特定上下文將元素放置在不一樣位置的狀況下頗有用。
.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變量,咱們能夠存儲它們的兩個版本,並根據用戶或系統偏好在它們之間切換。
: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
能夠有多種變化。有時候是須要一個小包裝一個頁面,一個大包裝另外一個頁面。在這種狀況下,合併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...
另外一個有用的用例是大小調整元素。 假設咱們須要四種不一樣大小的用戶頭像,而且只能使用一個變量來控制其大小。
<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
,由於它從父元素繼承了它。頗有趣,那它在實際的項目中有啥用呢?
咱們有一組如下需求的操做項
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 變量。
當var()
函數中的CSS變量無效時,瀏覽器將根據所使用的屬性用初始值或繼承值替換。
:root { --main-color: 16px; } .section-title { color: var(--main-color); }
我使用16px
是color
屬性的值。 這是徹底錯誤的。 因爲color
屬性是繼承的,所以瀏覽器將執行如下操做:
該屬性是否可繼承?
若是是,父節點是否擁有該屬性?
下面解釋瀏覽器工做的流程圖。
咱們可能沒法控制網頁中的全部資源,其中一些必須在線託管。 在這種狀況下,您能夠將連接的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 變量也能夠表示多個值,看下面的例子:
: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變量。
使用CSS變量時,看到顏色或背景值的視覺指示器是否有用? Chrome和Edge證實了這一點。
要查看CSS變量的計算值,只要將鼠標懸停或單擊便可。
當咱們須要從使用CSS變量的全部元素中禁用CSS變量時,能夠經過從定義它的元素中取消選中它來實現。 參見下圖:
本文介紹了 CSS 變量的不少內容,但願能對你有些幫助,二創不易,還望點個贊+轉發。
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
原文:https://ishadeed.com/article/...
有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。