Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
ayer.js是一個方便的彈出層插件,切圖網專注于PSD2HTML等前端切圖多年,后轉向Vue開發。在vue開發過程中引入layer.js的時候遇到了麻煩。原因是layer.js不支持import導入,這時就需要修改一下它的源碼。在看過它的源碼后,發現需要修改的地方只有兩處,
源碼中已經暴露了一個全局變量layer,故只需在腳本末尾處添加
export default layer;
這表示將這個全局變量導出。
然后在文件中找到下面的代碼注釋掉,這段代碼是為layer添加樣式的,但使用的路徑不對,故沒有太大幫助。
document.head.appendChild(function() {
var link = doc.createElement('link');
link.href = path + 'need/layer.css?2.0';
link.type = 'text/css';
link.rel = 'styleSheet'link.id = 'layermcss';
return link;
} ());
接下來把layer.js和layer.css分別放入static/js和static/css中,在需要的地方,比如組件內部或者全局注冊,因為項目多處都會用到,所以采用全局注冊,在main.js中
import layer from '../static/js/layer.js'
layer.css也使用全局注冊,它可以放在index.html中通過link引入,也可以放在App.vue中
<!--index.html-->
<link rel="stylesheet" href="./static/css/layer.css" />
<!--或者-->
<!--App.vue-->
<style>
@import "../static/css/layer.css";
</style>
接下來就能在各個組件中使用layer.open等方法了。
這種方式應該可以適用于各種不支持import導入的腳本,即非npm提供的module。
如果我們的頁面上存在非常多的樣式,譬如有我們開發頁面的時候的自定義樣式,也有引入的組件庫樣式。這時候樣式將會非常混亂難以管理。
當我們想覆蓋一些本身非我們書寫的樣式時候,往往不得不通過使用優先級權重更高的樣式名,去覆蓋那些樣式。
同時,當樣式優先級感到難以控制時,開發者習慣濫用 !important 去解決,這又循環導致了后續更混亂的樣式結構。
基于讓 CSS 得到更好的控制和管理的背景,CSS @layer 應運而生。
CSS Cascade Layers,也叫做CSS級聯層,是Cascading and Inheritance Level5 規范中新增了一個新的 CSS 特性。
@layer聲明了一個 級聯層, 同一層內的規則將級聯在一起, 這給予了開發者對層疊機制的更多控制。語法也非常簡單,看這樣一個例子:
@layer utilities {
/* 創建一個名為 utilities 的級聯層 */
}
這樣,我們就創建一個名為 utilities 的 @layer 級聯層。
@layer規則可以通過三種方式其一來創建級聯層。第一種方法如上方代碼所示,它創建了一個塊級的@規則,其中包含作用于該層內部的CSS規則。
@layer utilities {
.padding-sm {
padding: .5rem;
}
.padding-lg {
padding: .8rem;
}
}
一個級聯層同樣可以通過 @import 來創建,規則存在于被引入的樣式表內:
@import(utilities.css) layer(utilities);
你也可以創建帶命名的級聯層,但不指定任何樣式。例如,單一的命名層:
@layer utilities
或者,多個命名層也可以被同時定義。例如:
@layer theme, layout, utilities
這一做法很有用,因為層最初被指定的順序決定了它是否有父級層。對于聲明而言,如果同一聲明在多個級聯層中被指定,最后一層中的將優先于其他層。
因此,在上面的例子中,如果 theme 層和 utilities 層中存在沖突的規則,那么 utilities 層中的將優先被應用。
即使 utilities 層中規則的 優先級低于 theme 層中的,該規則仍會被應用。一旦級聯層順序建立之后,優先級和出現順序都會被忽略。
這將使創建CSS選擇器變得更加簡單,因為你不需要確保每一個選擇器都有足夠高的優先級來覆蓋其他沖突的規則,你只需要確保它們出現在一個順序更靠后的級聯層中。
注:在已經聲明級聯層的名字后,它們的順序隨即被確立,你可以重復聲明某級聯層的名字來向其添加CSS規則。這些樣式將被附加到該層的末尾,且級聯層之間的順序不會改變。
其他不屬于任何一級聯層的樣式將被集中到同一匿名層,并置于所有層的前部,這意味著任何級聯層內定義的規則都將覆蓋外部聲明的規則。
級聯層允許嵌套,例如:
@layer framework {
@layer layout {
}
}
向 layout 層內部的 framework 層附加規則,只需用 . 連接這兩層。
@layer framework.layout {
p {
margin-block: 1rem;
}
}
如果創建了一個級聯層但并未指定名字,例如:
@layer {
p {
margin-block: 1rem;
}
}
那么則稱為創建了一個匿名層。除創建后無法向其添加規則外,該層和其他命名層功能一致。
@layer [ <layer-name># | <layer-name>? {
<stylesheet>
} ]
級聯層可以通過多種方式聲明:
1、使用@layer 塊規則,并立即為其分配樣式:
@layer reset {
* { /* Poor Man's Reset */
margin: 0;
padding: 0;
}
}
2、使用規則@layer 語句,沒有指定任何樣式:
@layer reset;
3、將@import 與layer關鍵字或layer()函數一起使用
@import(reset.css) layer(reset);
以上每一個都創建了一個名為 的級聯層reset。
級聯層會按它們聲明的順序排序。
在下面的例子中,我們建立四個級聯層:reset,base,theme,和utilities。
@layer reset { /* 創建級聯層 “reset” */
* {
margin: 0;
padding: 0;
}
}
@layer base { /* 創建級聯層 “base” */
…
}
@layer theme { /* 創建級聯層 “theme” */
…
}
@layer utilities { /* 創建級聯層 “utilities” */
…
}
按照它們的聲明順序,層順序變為:
reset
base
theme
utilities
重復使用級聯層名稱時,樣式將附加到現有級聯層。級聯層的順序保持不變,因為只有第一次的出現已經確定順序:
@layer reset { /* 創建第一個級聯層 “reset” */
…
}
@layer base { /* 創建第二個級聯層 “base” */
…
}
@layer theme { /* 創建第三個級聯層 “theme” */
…
}
@layer utilities { /* 創建第四個級聯層 “utilities” */
…
}
@layer base { /* 會將樣式添加至級聯層“base” */
…
}
重新使用級聯層名稱時層順序保持不變的使@layer 語法變得更加方便和嚴謹。使用它,可以預先建立圖層順序,然后將所有 CSS 附加到它:
@layer reset; /* 創建第一個級聯層 “reset” */
@layer base; /* 創建第二個級聯層 “base” */
@layer theme; /* 創建第三個級聯層“theme” */
@layer utilities; /* 創建第四個級聯層 “utilities” */
@layer reset { /* 添加樣式至級聯層 “reset” */
…
}
@layer theme { /* 添加樣式至級聯層 “theme” */
…
}
@layer base { /* 添加樣式至級聯層 “base” */
…
}
@layer theme { /* 添加樣式至級聯層 “theme” */
…
}
當然你可以用更短的語法來聲明級聯層,
@layer reset, base, theme, utilities;
從上面可以看出,多個級聯層被聲明時,最后一個級聯層的聲明會獲勝。像這樣,
@import(reset.css) layer(reset); /* 第一個級聯層 */
@layer base { /* 第二個級聯層 */
form input {
font-size: inherit;
}
}
@layer theme { /*第三個級聯層 */
input {
font-size: 2rem;
}
}
按以往CSS級聯來進行分析的話,form input(多層級)的優先級會大于input,但是由于級聯層所起的作用,@layer theme的input會取勝。
級聯層支持嵌套使用,如下:
@layer base { /* 第一個級聯層*/
p { max-width: 70ch; }
}
@layer framework { /* 第二個級聯層 */
@layer base { /* 第二級聯層的嵌套子級聯層1 */
p { margin-block: 0.75em; }
}
@layer theme { /* 第二級聯層的嵌套子級聯層2 */
p { color: #222; }
}
}
在這個例子中有兩個級聯外層:
base
framework
該framework層本身也包含兩層:
base
theme
如果要將樣式附加到嵌套級聯層,需要使用以下全名來引用它,
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
@layer theme {
p { color: #222; }
}
}
@layer framework.theme {
/* 這些樣式會被添加到@layer framework層里面的theme層 */
blockquote { color: rebeccapurple; }
}
@media (min-width: 30em) {
@layer layout {
.title { font-size: x-large; }
}
}
@media (prefers-color-scheme: dark) {
@layer theme {
.title { color: white; }
}
}
如果第一個@media (min-width: 30em)匹配(基于視口尺寸),則layout級聯層層將在圖層順序中排在第一位。如果只有@media (prefers-color-scheme: dark)匹配,theme則將是第一層。
如果兩者匹配,則圖層順序將為layout, theme。如果沒有匹配,則不定義層。
近在Weekly郵件推送中查閱到這樣的一條信息:
Chromium 團隊宣布他們將隨 Chromium 99(預計在明年 3 月發布)一起發布CSS Cascade Layers
會發現這條信息里面出現了一個CSS的新名詞CSS Cascade Layers,出于好奇以及對新知識的渴望(說得我自己都信了,哈哈),于是查閱起CSS Cascade Layers的相關資料,試圖搞懂它。
前置知識
at-rule規則, CSS Conditional Rules Module Level 3新增的規則,是一條語句,它為CSS提供了執行或如何執行的指令,常見的at-rule規則有:
@import,允許用戶從其他樣式表導入樣式規則
@font-face,允許我們引用自定義的字體
@keyframes,聲明一個動畫
@media,是條件CSS中的一種,其條件是一個媒體查詢
@supports,測試用戶代理是否支持CSS屬性/值對
@viewport,用來控制移動設備上的viewport設置
級聯(層疊)與繼承經過多年的發展迭代,目前已有多個版本(CSS2.2、Level3、Level4 和 Level5)
何為級聯(層疊)?
層疊本質就是定義了如何合并來自多個源的屬性值的算法,簡單來說,CSS規則的順序很重要。當兩條同級別的規則應用到一個元素的時候,寫在后面的就是實際使用的規則。
h1 {
color: red;
}
h1 {
color: blue;
}
兩條規則優先級相同,所以順序在最后的生效,h1是color:blue'勝出',顯示藍色。
只有CSS聲明,就是屬性名值對,會參與層疊計算。這表示包含CSS聲明以外實體的@規則不參與層疊計算,如包含描述符的@font-face,@規則(at-rule規則)是做為一個整體參與層疊計算。
css屬性一般來自于哪幾個源?
1、用戶代理樣式表:瀏覽器的基本的樣式表,用于給所有網頁設置默認樣式。
2、用戶樣式表:網頁的作者可以定義文檔的樣式。大多數情況下此類型樣式表會定義網站的主題。
3、瀏覽器的用戶使用自定義樣式表定制使用體驗。
層疊(級聯)算法如何過濾來自不同源的css規則?
相互沖突的聲明按以下順序適用,后一種聲明將覆蓋前一種聲明:
1、用戶代理樣式表中的聲明(瀏覽器的默認樣式)。
2、用戶樣式表中的常規聲明(用戶設置的自定義樣式,就如同我們的reset.css)。
3、作者樣式表中的常規聲明(開發人員設置的樣式)。
4、作者樣式表中的!important聲明
5、用戶樣式表中的!important 聲明
過濾來自不同源的css規則后,確定同源優先級高低,決定誰“優勝”
!important > 內聯style > #id > .class > 標簽
了解級聯算法有助于幫助我們理解瀏覽器是如何解決樣式規則沖突,也就是瀏覽器決定哪個樣式規則運用到元素上,更多相關css級聯的了解:
何為繼承?
當元素的一個繼承屬性沒有指定值時,則取父元素的同屬性的計算值 。只有文檔根元素取該屬性定義的默認值,類似的屬性有color、font-size等 。
CSS是由Cascading Style Sheets三個詞的首字母縮寫,很多人將其稱為層疊樣式表或者級聯樣式表.
CSS Cascade Layers,也叫做CSS級聯層,是Cascading and Inheritance Level5 規范中新增了一個新的 CSS 特性,對應的CSS屬性寫法@layer,即一個新的 @ 規則,也就是大家所說的at-rule 規則。
為啥會出現@layer?
通過上面我們對級聯介紹,我們已經看到了順序對于層疊的重要性,同權重的css屬性后者會“優勝”前者,權重不同會根據CSS聲明來源和優先級算法來判斷誰“優勝”。!important的CSS規則自動將它跳到層疊算法的前面,能夠覆蓋普通規則的層疊。
也就是說我們一般會使用選擇器權重和順序作為控制級聯的方法,但是這樣卻會時常碰到:
使用較高權重的選擇器來防止你的代碼被后面的代碼(或別人的代碼)覆蓋。但這也會引起另一個不良的現象,可能會在代碼中新增很多帶有 !important 的樣式規則,這本身就會引起更多的問題,比如 !important 在 CSS 樣式表中隨處可見,需要覆蓋的時候難以被覆蓋 。
使用較低權重的選擇器又很容易被后面的代碼(或別人的代碼)覆蓋。比如你在引入第三方代碼庫或組件時,自己的代碼可能被覆蓋。
這兩個現象也是編寫CSS代碼,特別是在一個大型項目或多人協作的項目中常出現。也給很多CSS開發者帶來很多困擾。
雖然社區有很多第三方方案,如CSS-in-JS、CSS Modules 和 CSS Scoped等來協助解決級聯所帶來的問題,但由于源碼順序(打包產物)仍然起著決定性的作用,順序帶來的覆蓋和沖突依舊未真正的解決,而且選擇器權重仍然比層的順序(源碼順序)更重要。
這樣的背景促進了@layer的出現,要真正的解決級聯帶來的這些問題。
@layer的出現,也要求我們對以往css級聯有個新的了解,
可以看出CSS的級聯層一般位于“Style 屬性”(Style Attribute)和 CSS 選擇器權重(Specificity)之間。
使用CSS級聯層,可以通過@layer at-rule將 CSS 分成多個層。
與 CSS屬性來源 在用戶樣式表和作者樣式表風格之間提供權衡的方式相同,Cascade Layers 提供了一種結構化的方式來組織和權衡單個 來源 內的關注點
如何使用
級聯層可以通過多種方式聲明:
1、使用@layer 塊規則,并立即為其分配樣式:
@layer reset {
* { /* Poor Man's Reset */
margin: 0;
padding: 0;
}
}
2、使用規則@layer 語句,沒有指定任何樣式:
@layer reset;
3、將@import 與layer關鍵字或layer()函數一起使用
@import(reset.css) layer(reset);
以上每一個都創建了一個名為 的級聯層reset。
級聯層會按它們聲明的順序排序。
在下面的例子中,我們建立四個級聯層:reset,base,theme,和utilities。
@layer reset { /* 創建級聯層 “reset” */
* {
margin: 0;
padding: 0;
}
}
@layer base { /* 創建級聯層 “base” */
…
}
@layer theme { /* 創建級聯層 “theme” */
…
}
@layer utilities { /* 創建級聯層 “utilities” */
…
}
按照它們的聲明順序,層順序變為:
reset
base
theme
utilities
重復使用級聯層名稱時,樣式將附加到現有級聯層。級聯層的順序保持不變,因為只有第一次的出現已經確定順序:
@layer reset { /* 創建第一個級聯層 “reset” */
…
}
@layer base { /* 創建第二個級聯層 “base” */
…
}
@layer theme { /* 創建第三個級聯層 “theme” */
…
}
@layer utilities { /* 創建第四個級聯層 “utilities” */
…
}
@layer base { /* 會將樣式添加至級聯層“base” */
…
}
重新使用級聯層名稱時層順序保持不變的使@layer 語法變得更加方便和嚴謹。使用它,可以預先建立圖層順序,然后將所有 CSS 附加到它:
@layer reset; /* 創建第一個級聯層 “reset” */
@layer base; /* 創建第二個級聯層 “base” */
@layer theme; /* 創建第三個級聯層“theme” */
@layer utilities; /* 創建第四個級聯層 “utilities” */
@layer reset { /* 添加樣式至級聯層 “reset” */
…
}
@layer theme { /* 添加樣式至級聯層 “theme” */
…
}
@layer base { /* 添加樣式至級聯層 “base” */
…
}
@layer theme { /* 添加樣式至級聯層 “theme” */
…
}
當然你可以用更短的語法來聲明級聯層,
@layer reset, base, theme, utilities;
從上面可以看出,多個級聯層被聲明時,最后一個級聯層的聲明會獲勝。像這樣,
@import(reset.css) layer(reset); /* 第一個級聯層 */
@layer base { /* 第二個級聯層 */
form input {
font-size: inherit;
}
}
@layer theme { /*第三個級聯層 */
input {
font-size: 2rem;
}
}
按以往CSS級聯來進行分析的話,form input(多層級)的優先級會大于input,但是由于級聯層所起的作用,@layer theme的input會取勝。
級聯層支持嵌套使用,如下:
@layer base { /* 第一個級聯層*/
p { max-width: 70ch; }
}
@layer framework { /* 第二個級聯層 */
@layer base { /* 第二級聯層的嵌套子級聯層1 */
p { margin-block: 0.75em; }
}
@layer theme { /* 第二級聯層的嵌套子級聯層2 */
p { color: #222; }
}
}
在這個例子中有兩個級聯外層:
base
framework
該framework層本身也包含兩層:
base
theme
就像一棵樹,像這樣,
如果要將樣式附加到嵌套級聯層,需要使用以下全名來引用它,
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
@layer theme {
p { color: #222; }
}
}
@layer framework.theme {
/* 這些樣式會被添加到@layer framework層里面的theme層 */
blockquote { color: rebeccapurple; }
}
@media (min-width: 30em) {
@layer layout {
.title { font-size: x-large; }
}
}
@media (prefers-color-scheme: dark) {
@layer theme {
.title { color: white; }
}
}
如果第一個@media (min-width: 30em)匹配(基于視口尺寸),則layout級聯層層將在圖層順序中排在第一位。如果只有@media (prefers-color-scheme: dark)匹配,theme則將是第一層。
如果兩者匹配,則圖層順序將為layout, theme。如果沒有匹配,則不定義層。
隨著 Cascade Layers 的出現,我們的開發人員將擁有更多的工具來控制 Cascade。Cascade Layers 的真正力量來自它在 Cascade 中的獨特位置:Style 屬性(Style Attribute)和 CSS 選擇器權重(Specificity)之間。因此,我們不需要擔心其他層中使用的 CSS 的選擇器特異性,也不需要擔心我們將 CSS 加載到這些層中的順序.
了解到這里,是不是覺得@layer相當地cool,迫不及待地想去使用了,我們看一下caniuse @layer的兼容情況,
很遺憾,支持程度慘不忍睹,想真正使用可能還要再等等,對于明年三月份 Chromium 99,發布我們拭目以待。
當然現在如果想嘗鮮,對于社區也有給出一些辦法,
大家也可以試一試,感謝閱讀!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。