義CSS樣式時,經(jīng)常出現(xiàn)兩個或更多樣式規(guī)則應(yīng)用在同一元素上的情況。此時CSS就會根據(jù)樣式規(guī)則的權(quán)重,優(yōu)先顯示權(quán)重最高的樣式。CSS優(yōu)先級指的就是CSS樣式規(guī)則的權(quán)重。在網(wǎng)頁制作中,CSS為每個基礎(chǔ)選擇器都指定了不同的權(quán)重,方便我們添加樣式代碼。為了深入理解CSS優(yōu)先級,我們通過一段示例代碼進行分析。CSS樣式代碼如下:
p{ color:red;} /*標簽樣式*/
.blue{ color:green;} /*class樣式*/
theader{ color:blue;} /*id樣式*/
CSS樣式代碼對應(yīng)的HTML結(jié)構(gòu)為:
<p class="blue" id="header">
幫幫我,我到底顯示什么顏色?
</p>
在上面的示例代碼中,使用不同的選擇器對同一個元素設(shè)置文本顏色,這時瀏覽器會根據(jù)CSS選擇器的優(yōu)先級規(guī)則解析CSS樣式。為了便于判斷元素的優(yōu)先級,CSS為每一種基礎(chǔ)選擇器都分配了一個權(quán)重,我們可以通過虛擬數(shù)值的方式為這些基礎(chǔ)選擇器匹配權(quán)重。假設(shè)標簽選擇器具有權(quán)重為1.類選擇器具有權(quán)重則為10,id選擇器具有權(quán)重則為l00。這樣id選擇器“#header”就具有最大的優(yōu)先級,因此文本顯示為藍色。
對于由多個基礎(chǔ)選擇器構(gòu)成的復合選擇器(并集選擇器除外),其權(quán)重可以理解為這些基礎(chǔ)選擇器權(quán)重的疊加。例如,下面的CSS代碼。
p strong{color:black} /*權(quán)重為:1+1*/
strong.blue{color:green;} /*權(quán)重為:1+10*/
.father strong{color:yellow} /*權(quán)重為:10+1*/
p.father strong{color:orange;} /*權(quán)重為:1+10+1*/
p.father .blue{color:gold;} /*權(quán)重為:1+10+10*/
theader strong{color:pink;} /*權(quán)重為:100+1*/
#header strong.blue{color:red;} /*權(quán)重為:100+1+10*/
對應(yīng)的HTML結(jié)構(gòu)為:
<p class="father" id="header">
<strong class="blue">文本的顏色</strong>
</p>
這時,CsS代碼中的“#header strong.blue”選擇器的權(quán)重最高,文本顏色將顯示為紅色。此外,在考慮權(quán)重時,我們還需要注意一些特殊的情況。
(1)繼承樣式的權(quán)重為0
在嵌套結(jié)構(gòu)中、h不管父元素樣式的權(quán)重多大,被子元素繼承時,它的權(quán)重都為0,也就是說子元素定義的樣式會覆蓋繼承來的樣式。例如,下面的CSS樣式代碼。
strong{color:red;}
#header{color:green;}
CSS樣式代碼對應(yīng)的HTML結(jié)構(gòu)如下:
<p id="header" class="blue">
<strong>繼承樣式不如自己定義的權(quán)重大</strong>
</p>
在上面的代碼中,雖然“#header”具有權(quán)重100,但被標簽繼承時權(quán)重為0。而“strong”選擇器的權(quán)重雖然僅為1,但它大于繼承樣式的權(quán)重,所以頁面中的文本顯示為紅色。
(2)行內(nèi)樣式優(yōu)先
應(yīng)用style屬性的元素,其行內(nèi)樣式的權(quán)重非常高。換算為數(shù)值,我們可以理解為遠大于100。因此行內(nèi)樣式擁有比上面提到的選擇器都高的優(yōu)先級。
(3)權(quán)重相同時,CSS的優(yōu)先級遵循就近原則
也就是說,靠近元素的樣式具有最大的優(yōu)先級,或者說按照代碼排列上下順序,排在最下邊的樣式優(yōu)先級最大。例如,下面為外部定義的CSS示例代碼。
/*CSS文檔,文件名為style_red.css*/
#header{color:red;} /*外部樣式*/
對應(yīng)的HTML結(jié)構(gòu)代碼如下:
<title>CSS優(yōu)先級</title>
<link rel="stylesheet"href="style_red.css"type="text/css"/> /*引入外部
定義的CSS代碼*/
<style type="text/css">
#header{color:gray;}
</style>
</head>
<body>
/*內(nèi)嵌式樣式*/
<p id="header">權(quán)重相同時,就近優(yōu)先</p>
</body>
在上面的示例代碼中,第2行代碼通過外鏈式引入CSS樣式,該樣式設(shè)置文本樣式顯示為紅色。第3~5行代碼通過內(nèi)嵌式引入CSS樣式,該樣式設(shè)置文本樣式顯示為灰色。
上面的頁面被解析后,段落文本將顯示為灰色,即內(nèi)嵌式樣式優(yōu)先。這是因為內(nèi)嵌樣式比外鏈式樣式更靠近HTML.元素。同樣的道理,如果同時引用兩個外部樣式表,則排在下面的樣式表具有較大的優(yōu)先級。如果此時將內(nèi)嵌樣式更改為:
p{color:gray;} /*內(nèi)嵌式樣式*/
此時外鏈式的id選擇器和嵌入式的標簽選擇器權(quán)重不同,“#header”的權(quán)重更高,文字將顯示為外部樣式定義的紅色。
(4)CSS定義“l(fā)important”命令,會被賦予最大的優(yōu)先級
當CSS定義了“l(fā)important”命令后,將不再考慮權(quán)重和位置關(guān)系,使用“l(fā)important”的標簽都具有最大優(yōu)先級。例如,下面的示例代碼。
#header{color:red!important;}
應(yīng)用此樣式的段落文本顯示為紅色,因為“l(fā)important”命令的樣式擁有最大的優(yōu)先級。需要注意的是,“l(fā)important”命令必須位于屬性值和分號之間,否則無效。
復合選擇器的權(quán)重為組成它的基礎(chǔ)選擇器權(quán)重的疊加,但是這種疊加并不是簡單的數(shù)字之和。下面通過一個案例來具體說明,如例1所示。
例1 examplel1.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>復合選擇器權(quán)重的疊加</title>
<style type="text/css">
.inner{text-decoration:line-through;}/*類選擇器定義刪除線,權(quán)重為10*/
div div div div div div div div div div div{text-decoration:underline;}
/*后代選擇器定義下畫線,權(quán)重為11個1的疊加*/
</style>
</head>
<body>
<div>
<div><div><div><div><div><div><div><div><div>
<div class="inner">文本的樣式</div>
</div></div></div></div></div></div></div></div></div>
</div>
</body>
</html>
例1共使用了11對<div>標簽,它們層層嵌套。第15行代碼我們對最里層的<div>定義類名“inner”。第7、8行代碼,使用類選擇器和后代選擇器分別定義最里層div的樣式。此時瀏覽器中文本的樣式到底如何顯示呢?如果僅僅將基礎(chǔ)選擇器的權(quán)重相加,后代選擇器(包含11層div)的權(quán)重為11,大于類選擇器“.inner”的權(quán)重10,文本將添加下畫線。
運行例1,效果如下所示。
在上圖中,文本并沒有像預(yù)期的那樣添加下畫線,而顯示了類選擇器“.inner”定義的刪除線。可見,無論在外層添加多少個標簽,復合選擇器的權(quán)重無論為多少個<div>標簽選擇器的疊加,其權(quán)重都不會高于類選擇器。同理,復合選擇器的權(quán)重無論為多少個類選擇器和標簽選擇器的疊加,其權(quán)重都不會高于i選擇器。
前在項目的過程中遇到了一個問題,某個 div 希望始終顯示在最上面,而在之后的元素都顯示在它之下,當時設(shè)置了 z-index 也沒有效果,不知道什么原因,因此找了一下 CSS 相關(guān)資料,解決了這個問題的同時,也學習了很多知識,特此和大家分享一下。
屏幕是一個二維平面,然而 HTML 元素卻是排列在三維坐標系中, x 為水平方向, y 為垂直方向, z為屏幕由內(nèi)向外方向,我們在看屏幕的時候是沿著 z 軸方向從外向內(nèi)的。由此,元素在用戶視角就形成了層疊的關(guān)系,某個元素可能覆蓋了其他元素也可能被其他元素覆蓋;
這里有幾個重要的概念:層疊上下文 (堆疊上下文, Stacking Context)、層疊等級 (層疊水平, Stacking Level)、層疊順序 (層疊次序, 堆疊順序, Stacking Order)、z-index、BFC(塊級格式化上下文,Block Formatting Context),這些概念共同決定了你看到元素的位置,下面我們就圍繞著這幾個概念來一起學習一下。
聲明:
1. 層疊上下文 (Stacking Context)
層疊上下文 (堆疊上下文, Stacking Context),是 HTML 中一個三維的概念。在 CSS2.1 規(guī)范中,每個元素的位置是三維的,當元素發(fā)生層疊,這時它可能覆蓋了其他元素或者被其他元素覆蓋;排在 z 軸越靠上的位置,距離屏幕觀察者越近。
文章 <關(guān)于z-index 那些你不知道的事> 有一個很好的比喻,這里引用一下;
可以想象一張桌子,上面有一堆物品,這張桌子就代表著一個層疊上下文。如果在第一張桌子旁還有第二張桌子,那第二張桌子就代表著另一個層疊上下文?,F(xiàn)在想象在第一張桌子上有四個小方塊,他們都直接放在桌子上。在這四個小方塊之上有一片玻璃,而在玻璃片上有一盤水果。這些方塊、玻璃片、水果盤,各自都代表著層疊上下文中一個不同的層疊層,而這個層疊上下文就是桌子。
每一個網(wǎng)頁都像一個房間,這個房間就是 <html></html>,其他層疊上下文就像這個房間里的桌子,HTML 標簽中的一切都被置于這個房間中。
當給一個元素的 position 值賦為 fixed 或 sticky 值時,你就創(chuàng)建了一個新的層疊上下文,其中有著獨立于頁面上其他層疊上下文和層疊層的層疊層,這就相當于你把另一張桌子帶到了房間里。
層疊上下文 1 (Stacking Context 1)是由文檔根元素形成的, 層疊上下文 2 和 3 (Stacking Context 2, 3) 都是層疊上下文 1 (Stacking Context 1) 上的層疊層。他們各自也都形成了新的層疊上下文,其中包含著新的層疊上下文。
在層疊上下文中,其子元素按照上面解釋的規(guī)則進行層疊。形成層疊上下文的方法有:
總結(jié):
2. 層疊等級 (Stacking Level)
層疊等級 (層疊水平, Stacking Level) 決定了在同一個層疊上下文中,元素在 z 軸上的顯示的順序;
對于普通元素的層疊水平探討只局限于在當前層疊上下文中:
層疊上下文本身是一個強力的「層疊結(jié)界」,普通的元素水平是無法突破這個結(jié)界和結(jié)界外的元素去較量層疊水平的。
— CSS 世界
另外,層疊等級并不一定由 z-index 決定,只有定位元素的層疊等級才由 z-index 決定,其他類型元素的層疊等級由層疊順序、他們在 HTML 中出現(xiàn)的順序、他們的祖先元素的層疊等級一同決定,詳細的規(guī)則見下面層疊順序的介紹。
3. z-index
在 CSS 2.1 中, 所有的盒模型元素都處于三維坐標系中。除了我們常用的橫坐標和縱坐標, 盒模型元素還可以沿著「z 軸」層疊擺放,當他們相互覆蓋時,z 軸順序就變得十分重要。
-- CSS 2.1 Section 9.9.1 - Layered presentation
z-index 只適用于定位的元素,對非定位元素無效,它可以被設(shè)置為正整數(shù)、負整數(shù)、 0、 auto,如果一個定位元素沒有設(shè)置 z-index,那么默認為 auto;
元素的 z-index 值只在同一個層疊上下文中有意義。如果父級層疊上下文的層疊等級低于另一個層疊上下文的,那么它 z-index 設(shè)的再高也沒用。所以如果你遇到 z-index 值設(shè)了很大,但是不起作用的話,就去看看它的父級層疊上下文是否被其他層疊上下文蓋住了。
4. 層疊順序 (Stacking Order)
層疊順序 (層疊次序, 堆疊順序, Stacking Order) 描述的是元素在同一個層疊上下文中的順序規(guī)則(之前的層疊上下文和層疊等級是概念),從層疊的底部開始,共有七種層疊順序:
第 7 級順序的元素會顯示在之前順序元素的上方,也就是看起來覆蓋了更低級的元素:
除層疊順序優(yōu)先級規(guī)則之外,還有一條后來居上規(guī)則:同一個層疊順序的元素按照在 HTML 里出現(xiàn)的順序依次層疊。這兩個規(guī)則共同決定瀏覽器元素在文檔中是如何層疊的。
5. 文檔流 (Document Flow)
5.1 常規(guī)流 (Normal flow)
5.2 浮動 (Floats)
5.3 絕對定位 (Absolute positioning)
6. BFC (Block Formatting Context)
6.1 什么是 BFC
BFC (Block Formatting Context) 塊級格式化上下文,是用于布局塊級盒子的一塊渲染區(qū)域,相對應(yīng)的還有 IFC(Inline Formatting Context)內(nèi)聯(lián)格式化上下文,不是本文重點,讀者可以自行查閱相關(guān)知識。
BFC 是 Web 頁面 CSS 視覺渲染的一部分,用于決定塊盒子的布局及浮動相互影響范圍的一個區(qū)域。
— MDN - 塊格式化上下文
一個 BFC 的范圍包含創(chuàng)建該上下文元素的所有子元素,但不包括創(chuàng)建了新 BFC 的子元素的內(nèi)部元素。這從另一方角度說明,一個元素不能同時存在于兩個 BFC 中。因為如果一個元素能夠同時處于兩個 BFC 中,那么就意味著這個元素能與兩個 BFC 中的元素發(fā)生作用,就違反了 BFC 的隔離作用。
觸發(fā) BFC 的方式有:
注意: display:table 也可以生成 BFC 的原因在于 Table 會默認生成一個匿名的 table-cell,是這個匿名的 table-cell 生成了 BFC。
6.2 用法
1. 阻止相鄰元素的 margin 合并
屬于同一個 BFC 的兩個相鄰塊級子元素的上下 margin 會發(fā)生重疊,(設(shè)置 writing-mode:tb-rl時,水平 margin 會發(fā)生重疊)。所以當兩個相鄰塊級子元素分屬于不同的 BFC 時可以阻止 margin 重疊。可以給任一個相鄰塊級盒子的外面包一個 div,通過改變此 div 的屬性使兩個原盒子分屬于兩個不同的 BFC,以此來阻止 margin 重疊。
代碼和預(yù)覽參見:Codepen - 使用BFC阻止margin合并:https://codepen.io/SHERlocked93/pen/eVOevN
2. 阻止元素被浮動元素覆蓋
一個正常文檔流的塊級元素可能被一個 float 元素覆蓋,擠占正常文檔流,因此可以設(shè)置一個元素的 float、 display、 position 值等方式觸發(fā) BFC,以阻止被浮動盒子覆蓋。
代碼和預(yù)覽參見:Codepen - 使用BFC阻止元素被浮動元素覆蓋:https://codepen.io/SHERlocked93/pen/pazdzB
3. 包含浮動元素
通過改變包含浮動子元素的父盒子的屬性值,觸發(fā) BFC,以此來包含子元素的浮動盒子。
代碼和預(yù)覽參見:Codepen - 使用BFC包含浮動元素:https://codepen.io/SHERlocked93/pen/OQLOqG
7. 實戰(zhàn)
下面一起來看幾個例子實戰(zhàn)一下,幫助理解。
7.1 普通情況
三個 relative 定位的 div 塊中各有 absolute 的不同顏色的 span.red、 span.green、 span.blue,它們都設(shè)置了 position:absolute;
代碼和預(yù)覽參見:Codepen - 普通情況:https://codepen.io/SHERlocked93/pen/aaPord
那么當沒有元素包含 z-index 屬性時,這個例子中的元素按照如下順序?qū)盈B(從底到頂順序):
紅綠藍都屬于 z-index 為 auto 的定位元素,因此按照 7 層層疊順序規(guī)則來說同屬于層疊順序第 6 級,所以按 HTML 中的出現(xiàn)順序?qū)盈B:紅->綠->藍
7.2 在相同層疊上下文的父元素內(nèi)的情況
紅綠位于一個 div.first-box 下,藍位于 div.second-box 下,紅綠藍都設(shè)置了 position:absolute, first-box 與 second-box 都設(shè)置了 position:relative;
代碼和預(yù)覽參見:Codepen - 父元素不同但都位于根元素下:https://codepen.io/SHERlocked93/pen/RYENBw
這個例子中,紅藍綠元素的父元素 first-box 與 second-box 都沒有生成新的層疊上下文,都屬于根層疊上下文中的元素,且都是層疊順序第 6 級,所以按 HTML 中的出現(xiàn)順序?qū)盈B:紅->綠->藍
7.3 給子元素增加 z-index
紅綠位于一個 div.first-box 下,藍黃位于 div.second-box 下,紅綠藍都設(shè)置了 position:absolute,如果這時給綠加一個屬性 z-index:1,那么此時 .green 位于最上面;
如果再在 .second-box 下 .green 后加一個絕對定位的 span.gold,設(shè)置 z-index:-1,那么它將位于紅綠藍的下面;
代碼和預(yù)覽參見:Codepen - 設(shè)置了z-index:https://codepen.io/SHERlocked93/pen/gdZOrK
這個例子中,紅藍綠黃元素的父元素中都沒有生成新的層疊上下文,都屬于根層疊上下文中的元素
所以這個例子中的從底到高顯示的順序就是:黃->紅->藍->綠
7.4 在不同層疊上下文的父元素內(nèi)的情況
紅綠位于一個 div.first-box 下,藍位于 div.second-box 下,紅綠藍都設(shè)置了 position:absolute,如果 first-box 的 z-index 設(shè)置的比 second-box 的大,那么此時無論藍的 z-index 設(shè)置的多大 z-index:999,藍都位于紅綠的下面;如果我們只更改紅綠的 z-index 值,由于這兩個元素都在父元素 first-box 產(chǎn)生的層疊上下文中,此時誰的 z-index 值大,誰在上面;
代碼和預(yù)覽參見:Codepen - 不同層疊上下文的父元素:https://codepen.io/SHERlocked93/pen/gdZbOJ
這個例子中,紅綠藍都屬于設(shè)置了 z-index 的定位元素,不過他們的父元素創(chuàng)建了新的層疊上下文;
所以這個例子中從低到到顯示的順序:藍->紅->綠
(我遇到的的情況就屬于這個例子類似情形)
7.5 給子元素設(shè)置 opacity
紅綠位于 div.first-box 下,藍位于 div.second-box 下,紅綠藍都設(shè)置了 position:absolute,綠設(shè)置了 z-index:1,那么此時綠位于紅藍的最上面;
如果此時給 first-box 設(shè)置 opacity:.99,這時無論紅綠的 z-index 設(shè)置的多大 z-index:999,藍都位于紅綠的上面;
如果再在 .second-box 下 .green 后加一個 span.gold,設(shè)置 z-index:-1,那么它將位于紅綠藍的下面;
代碼和預(yù)覽參見:Codepen - opacity的影響:https://codepen.io/SHERlocked93/pen/GXPRWB
之前已經(jīng)介紹了,設(shè)置 opacity 也可以形成層疊上下文,因此:
所以這個例子中從低到到顯示的順序:黃->紅->綠->藍
關(guān)注微信公眾號:安徽思恒信息科技有限公司,了解更多技術(shù)內(nèi)容……
演示地址: https://sortablejs.github.io/Sortable/
Github:https://github.com/SortableJS/Sortable
SortableJS是一款用于在現(xiàn)代瀏覽器和觸摸設(shè)備上的拖拽插件,不需要jQuery,但支持jQuery,支持Meteor,AngularJS,React,Polymer,Vue,Knockout和任何CSS庫,例如Bootstrap。
通過npm
npm install sortablejs --save
通過bower
bower install --save sortablejs
<ul id="items"> <li>item 1</li> <li>item 2</li> <li>item 3</li> </ul> var el = document.getElementById('items'); var sortable = Sortable.create(el);
備注:不僅僅是可以使用ul/li,比如div等
根據(jù)官網(wǎng)文檔簡單介紹下:
string:命名,個人建議用元素id就行,用處是為了設(shè)置可以拖放容器時使用 array:[name,pull,put] name:同string的方法, pull:pull用來定義從這個列表容器移動出去的設(shè)置,true/false/'clone'/function true:列表容器內(nèi)的列表單元可以被移出; false:列表容器內(nèi)的列表單元不可以被移出; 'clone':列表單元移出,移動的為該元素的副本; function:用來進行pull的函數(shù)判斷,可以進行復雜邏輯,在函數(shù)中return false/true來判斷是否移出; put:put用來定義往這個列表容器放置列表單元的的設(shè)置,true/false/['foo','bar']/function true:列表容器可以從其他列表容器內(nèi)放入列表單元; false:與true相反; ['foo','bar']:這個可以是一個字符串或者是字符串的數(shù)組,代表的是group配置項里定義的name值; function:用來進行put的函數(shù)判斷,可以進行復雜邏輯,在函數(shù)中return false/true來判斷是否放入;
move 事件對象:
獲取或設(shè)置選項
對于集合中的每個元素,通過測試元素本身并遍歷DOM樹中的祖先來獲取與選擇器匹配的第一個元素
序列化可排序的列表單元的data-id(可通過配置項中dataIdAttr修改)放入一個數(shù)組,并返回這個數(shù)組中
通過自定義列表單元的data-id的數(shù)組對列表單元進行排序
保存當前排序
完全銷毀可拖拽功能
SortableJS在某些場景下非常有用,它是一個很好用的前端拖拽解決方案,合理的使用將會帶來某些意想不到的驚喜,比如讓某些不可拖拽模態(tài)框,變成可拖拽模態(tài)(沒有實踐過),喜歡折騰的小伙伴可以收藏學習了,本人翻譯功底實在有限,如果對你有幫助,請點個關(guān)注吧!謝謝!
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。