SS變量(又名自定義屬性)已在Web瀏覽器中支持了近四年。我一般也會根據(jù)項目情況使用它們。它們非常有用且易于使用,但是前端開發(fā)人員通常可能會誤用或誤解它們。
CSS變量是在CSS文檔中定義的值,其目的是可重用性并減少CSS值中的冗余。下面是一個基本示例。
.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變量,可以更快解決這個問題。定義變量名需要用--開頭。首先,我們現(xiàn)在將在: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 變量的有效命名應(yīng)包含字母數(shù)字字符,下劃線和破折號。另外,值得一提的是 CSS 變量區(qū)分大小寫。
/* 合法命名 */
: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 為例:
:root {
--primary-color: #235ad1;
}
.section-title {
--primary-color: d12374;
color: var(--primary-color);
}
變量element是全局的,因此可以在cool()函數(shù)內(nèi)部訪問。但是,只能在cool()函數(shù)中訪問變量otherElement。
:root {
--primary-color: #235ad1;
}
.section-title {
--primary-color: d12374;
color: var(--primary-color);
}
變量--primary-color是全局變量,可以從文檔中的任何地方訪問。變量--primary-color由于是在.section-title定義的,所以只能在.section-title中訪問。
下面是一個比較直觀的示例圖片,可以加強我們的理解:
變量--primary-color用于標(biāo)題顏色。我們想為作者名和最新文章標(biāo)題自定義顏色,因此我們需要將--primary-color覆蓋。這同樣適用于--unit變量。
/* 全局變量 */
:root {
--primary-color: #235ad1;
--unit: 1rem;
}
/* section-title 默認(rèn)的顏色和間距 */
.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));
}
在變量值依賴于某個動作的情況下,該特性非常有用。當(dāng)變量沒有值時,為它提供一個回退很重要。
在設(shè)計系統(tǒng)中,按鈕通常有多種尺寸。通常,按鈕可以具有三種尺寸(Small, normal, large)。使用 CSS 變量來實現(xiàn)它并不容易:
.button {
--unit: 1rem;
padding: var(--unit);
}
.button--small {
--unit: 0.5rem;
}
.button--large {
--unit: 1.5rem;
}
通過在按鈕組件作用域內(nèi)更改變量--unit,我們創(chuàng)建了按鈕的不同變體。
HSL代表色調(diào),飽和度,亮度。色相的值決定了顏色,飽和度和亮度值可以控制顏色的深淺。
: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,F(xiàn)igma或Adobe XD之類的設(shè)計程序,那么我們會想在調(diào)整元素大小的同時按住Shift鍵以避免扭曲它。
在CSS中,沒有直接的方法來做到這一點,但是我們有一個簡單的解決方法,使用CSS變量。
假設(shè)有一個圖標(biāo),并且其寬度和高度應(yīng)該相等。我定義了變量--size,用于寬度和高度。
.icon {
--size: 22px;
width: var(--size);
height: var(--size);
}
現(xiàn)在,您只需更改--size變量的值即可模擬Shift調(diào)整大小的效果。
CSS 變量對于網(wǎng)格非常有用。假設(shè)希望網(wǎng)格容器根據(jù)定義的首選寬度顯示其子項。與為每個變體創(chuàng)建類并復(fù)制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;
這樣,我們可以創(chuàng)建一個完整的網(wǎng)格系統(tǒng),該系統(tǒng)靈活,易于維護,并且可以在其他項目中使用。可以將相同的概念應(yīng)用于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;
}
以全值表示,例如,類似漸變的東西。如果整個系統(tǒng)中使用漸變或背景,將其存儲到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 變量中包含多個值,這在需要根據(jù)特定上下文將元素放置在不同位置的情況下很有用。
.table {
--size: 50px;
--pos: left center;
background: #ccc linear-gradient(#000, #000) no-repeat;
background-size: var(--size) var(--size);
background-position: var(--pos);
}
現(xiàn)在,網(wǎng)站比以往任何時候都更需要深色和淺色模式。使用CSS變量,我們可以存儲它們的兩個版本,并根據(jù)用戶或系統(tǒng)偏好在它們之間切換。
: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設(shè)置CSS變量。假設(shè)我們需要獲取可擴展組件的高度。
變量--details-height-open為空,它將被添加到特定的HTML元素中。當(dāng)JavaScript由于某種原因失敗時,提供適當(dāng)?shù)哪J(rèn)值或后備值很重要。
.section.is-active {
max-height: var(--details-height-open, auto);
}
auto值是 JS 失敗時的回退值,并且沒有定義CSS變量——details-height-open。
網(wǎng)站wrapper 可以有多種變化。有時候是需要一個小包裝一個頁面,一個大包裝另一個頁面。在這種情況下,合并CSS變量可能是有用的。
.wrapper {
--size: 1140px;
max-width: var(--size);
}
.wrapper--small {
--size: 800px;
}
我們可以在style屬性中添加--item-width變量,僅此而已。例如,這種方法可以幫助建立網(wǎng)格原型。
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/pen/7d3e0d575a5cecb86233fc7d72fa90d4
另一個有用的用例是大小調(diào)整元素。假設(shè)我們需要四種不同大小的用戶頭像,并且只能使用一個變量來控制其大小。
<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變量和媒體查詢對于調(diào)整整個網(wǎng)站中使用的變量非常有用。我能想到的最簡單的示例是更改間距值。
:root {
--gutter: 8px;
}
@media (min-width: 800px) {
:root {
--gutter: 16px;
}
}
使用--gutter變量的任何元素都將根據(jù)視口大小更改其間距,這是不是很棒嗎?
是的,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屬性的。這意味著間距可以是動態(tài)的,并且取決于--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 變量。
當(dāng)var()函數(shù)中的CSS變量無效時,瀏覽器將根據(jù)所使用的屬性用初始值或繼承值替換。
:root {
--main-color: 16px;
}
.section-title {
color: var(--main-color);
}
我使用16px是color屬性的值。這是完全錯誤的。由于color屬性是繼承的,因此瀏覽器將執(zhí)行以下操作:
下面解釋瀏覽器工作的流程圖。
我們可能無法控制網(wǎng)頁中的所有資源,其中一些必須在線托管。在這種情況下,您可以將鏈接的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本身,因此無效。當(dāng)瀏覽器計算出該值時,該值將不再有效,并且將無法按預(yù)期運行。
CSS 變量也可以表示多個值,看下面的例子:
:root {
--main-color: 35, 90, 209;
}
.section-title {
color: rgba(var(--main-color), 0.75);
}
在示例中,我們有一個rgba()函數(shù),并且RGB值存儲在CSS變量中,以逗號分隔。如果我們想根據(jù)元素調(diào)整alpha值,這樣做可以提供靈活性。唯一的缺點是無法使用DevTools顏色選擇器來調(diào)整rgba值。
另一個例子是將它與background屬性一起使用。
:root {
--bg: linear-gradient(#000, #000) center/50px;
}
.section {
background: var(--bg);
}
.section--unique {
background: var(--bg) no-repeat;
}
如果你閱讀過CSS變量規(guī)范,則可能會讀到“動畫污染”一詞。這個想法是,在@keyframes規(guī)則中使用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)進行動畫處理。根據(jù)CSS規(guī)范:
@keyframes規(guī)則中使用的任何自定義屬性都會受到動畫污染,這將影響通過動畫屬性中的var()函數(shù)引用它時如何處理它。
如果我們希望上述動畫能夠正常工作,則應(yīng)采用老式的方法。這意味著,我們需要用要設(shè)置動畫的實際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 大小會有不同的變化。我將默認(rèn)值設(shè)置為1,所以默認(rèn)大小為(30px * 30px)。注意不同的類變化以及更改--size值如何導(dǎo)致化身的大小變化。
.c-avatar--small {
--size: 2;
}
.c-avatar--medium {
--size: 3;
}
.c-avatar--large {
--size: 4;
}
我們可以在瀏覽器DevTools中使用一些有用的技巧,這樣就能更輕松地使用CSS變量。
使用CSS變量時,看到顏色或背景值的視覺指示器是否有用?Chrome和Edge證明了這一點。
要查看CSS變量的計算值,只要將鼠標(biāo)懸停或單擊即可。
當(dāng)我們需要從使用CSS變量的所有元素中禁用CSS變量時,可以通過從定義它的元素中取消選中它來實現(xiàn)。參見下圖:
本文介紹了 CSS 變量的很多內(nèi)容,希望能對你有些幫助,二創(chuàng)不易,還望點個贊+轉(zhuǎn)發(fā)。
作者:Ahmad Shadeed 譯者:前端小智 來源:ishadeed
原文:https://ishadeed.com/article/css-vars-101/
html的文件結(jié)構(gòu)大家都是知道的了,總體分為head和body部分
我們要實現(xiàn)變色,在head部分實現(xiàn)格式
<style>
.tablex {border-collapse: collapse;}
.tablex tr {}
.tablex tr td {text-align:center; line-height:30px;}
.tablex tr td:hover { background-color:#f00; color:#fff;}
</style>
然后在body部分,使用table時候,注明class="tablex".這樣的話,就實現(xiàn)了我們所說的效果了。
附上完整代碼:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK" />
<title>測試鼠標(biāo)移到到表格單元格背景顏色改變的</title>
<style>
.table1 {border-collapse: collapse;}
.table1 tr {}
.table1 tr td {text-align:center; line-height:30px;}
.table1 tr td:hover { background-color:#006030; color:#006030;}
</style>
</head>
<body>
<table class="table1" width="70%" border="1">
<tr>
<td>測試</td>
<td>測試</td>
<td>測試</td>
<td>測試</td>
</tr>
<tr>
<td>測試</td>
<td>測試</td>
<td>測試</td>
<td>測試</td>
</tr>
<tr>
<td>測試</td>
<td>測試</td>
<td>測試</td>
<td>測試</td>
</tr>
<tr>
<td>測試</td>
<td>測試</td>
<td>測試</td>
<td>測試</td>
</tr>
<tr>
<td>測試</td>
<td>測試</td>
<td>測試</td>
<td>測試</td>
</tr>
</table>
</body>
</html>
在任何一個瀏覽器中運行,效果如下
南大盛聯(lián)20年來一直致力于高端IT培訓(xùn)--打造高級軟件人才實戰(zhàn)培訓(xùn)專家,學(xué)生對我們的認(rèn)可是我們一直前進的動力;項目團隊全球招聘,特聘來自海外的老師進行任教,采用100%商業(yè)項目進行實戰(zhàn)培訓(xùn),線上線下同步進行。
課程全部緊隨市場需求進行設(shè)計,并且動態(tài)進行調(diào)整;7天免費試聽,0首付開始學(xué)習(xí),學(xué)完后進行100%推薦就業(yè),不滿意工作崗位2次推薦。
選定一個平臺,認(rèn)識一群志同道合的朋友,你的未來人生路必定不一樣。
目前已經(jīng)開設(shè)下面這些培訓(xùn)項目
Java培訓(xùn)
安卓培訓(xùn)
JavaWeb培訓(xùn)
Linux培訓(xùn)
云服務(wù)器布置培訓(xùn)
HTML5培訓(xùn)
SEO培訓(xùn)
視頻剪輯培訓(xùn)
UI培訓(xùn)
歡迎您們分享給自己愿意分享的朋友,大家一起來進步;相互轉(zhuǎn)告,咨詢,學(xué)習(xí)。
南大盛聯(lián)培訓(xùn)理念:我懂,我也能讓你懂。
今年國慶假期終于可以憋在家里了不用出門了,不用出去看后腦了,真的是一種享受。這么好的光陰怎么浪費,睡覺、吃飯、打豆豆這怎么可能(耍多了也煩),完全不符合我們程序員的作風(fēng),趕緊起來把文章寫完。
這篇文章比較基礎(chǔ),在國慶期間的業(yè)余時間寫的,這幾天又完善了下,力求把更多的前端所涉及到的關(guān)于文件上傳的各種場景和應(yīng)用都涵蓋了,若有疏漏和問題還請留言斧正和補充。
以下是本文所涉及到的知識點,break or continue ?
原理很簡單,就是根據(jù) http 協(xié)議的規(guī)范和定義,完成請求消息體的封裝和消息體的解析,然后將二進制內(nèi)容保存到文件。
我們都知道如果要上傳一個文件,需要把 form 標(biāo)簽的enctype設(shè)置為multipart/form-data,同時method必須為post方法。
那么multipart/form-data表示什么呢?
multipart互聯(lián)網(wǎng)上的混合資源,就是資源由多種元素組成,form-data表示可以使用HTML Forms 和 POST 方法上傳文件,具體的定義可以參考RFC 7578。
multipart/form-data 結(jié)構(gòu)
看下 http 請求的消息體
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次請求要上傳文件,其中boundary表示分隔符,如果要上傳多個表單項,就要使用boundary分割,每個表單項由———XXX開始,以———XXX結(jié)尾。
每一個表單項又由Content-Type和Content-Disposition組成。
Content-Disposition: form-data 為固定值,表示一個表單元素,name 表示表單元素的 名稱,回車換行后面就是name的值,如果是上傳文件就是文件的二進制內(nèi)容。
Content-Type:表示當(dāng)前的內(nèi)容的 MIME 類型,是圖片還是文本還是二進制數(shù)據(jù)。
解析
客戶端發(fā)送請求到服務(wù)器后,服務(wù)器會收到請求的消息體,然后對消息體進行解析,解析出哪是普通表單哪些是附件。
可能大家馬上能想到通過正則或者字符串處理分割出內(nèi)容,不過這樣是行不通的,二進制buffer轉(zhuǎn)化為string,對字符串進行截取后,其索引和字符串是不一致的,所以結(jié)果就不會正確,除非上傳的就是字符串。
不過一般情況下不需要自行解析,目前已經(jīng)有很成熟的三方庫可以使用。
至于如何解析,這個也會占用很大篇幅,后面的文章在詳細(xì)說。
使用 form 表單上傳文件
在 ie時代,如果實現(xiàn)一個無刷新的文件上傳那可是費老勁了,大部分都是用 iframe 來實現(xiàn)局部刷新或者使用 flash 插件來搞定,在那個時代 ie 就是最好用的瀏覽器(別無選擇)。
DEMO
這種方式上傳文件,不需要 js ,而且沒有兼容問題,所有瀏覽器都支持,就是體驗很差,導(dǎo)致頁面刷新,頁面其他數(shù)據(jù)丟失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
選擇文件:
<input type="file" name="f1"/> input 必須設(shè)置 name 屬性,否則數(shù)據(jù)無法發(fā)送<br/>
<br/>
標(biāo)題:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 傳</button>
</form>
復(fù)制代碼
服務(wù)端文件的保存基于現(xiàn)有的庫koa-body結(jié)合 koa2實現(xiàn)服務(wù)端文件的保存和數(shù)據(jù)的返回。
在項目開發(fā)中,文件上傳本身和業(yè)務(wù)無關(guān),代碼基本上都可通用。
在這里我們使用koa-body庫來實現(xiàn)解析和文件的保存。
koa-body 會自動保存文件到系統(tǒng)臨時目錄下,也可以指定保存的文件路徑。
然后在后續(xù)中間件內(nèi)得到已保存的文件的信息,再做二次處理。
NODE
/**
* 服務(wù)入口
*/
var http=require('http');
var koaStatic=require('koa-static');
var path=require('path');
var koaBody=require('koa-body');//文件保存庫
var fs=require('fs');
var Koa=require('koa2');
var app=new Koa();
var port=process.env.PORT || '8100';
var uploadHost=`http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//設(shè)置文件的默認(rèn)保存目錄,不設(shè)置則保存在系統(tǒng)臨時目錄下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 開啟文件上傳,默認(rèn)是關(guān)閉
}));
//開啟靜態(tài)文件訪問
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次處理,修改名稱
app.use((ctx)=> {
var file=ctx.request.files.f1;//得道文件對象
var path=file.path;
var fname=file.name;//原文件名稱
var nextPath=path+fname;
if(file.size>0 && path){
//得到擴展名
var extArr=fname.split('.');
var ext=extArr[extArr.length-1];
var nextPath=path+'.'+ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 json 形式輸出上傳文件地址
ctx.body=`{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
}`;
});
/**
* http server
*/
var server=http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
復(fù)制代碼
CODE
https://github.com/Bigerfe/fe-learn-code/
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。