雖然CSS簡單,但CSS是一門非常有意思的語言,CSS每年都有變化,而且都有不同的博主都在不同的時間段總結一些CSS的新特性。雖然這些新特性無法立刻得到眾多瀏覽器的支援,但總是隨著時間的發展,這些特性都會得到瀏覽器的支援。哪怕未得到支援,也有一些方法讓瀏覽器支援,比如最為出外的cssnext,就可以讓很多未來的CSS特性就立馬使用,並且不用花太多時間來考慮瀏覽器的相容性。

今天這篇文章,@Daniel Crisp就當下的CSS的新特性做了一個簡單的總結 —— 五個最新的CSS特性(事實上這些特性,對我而言並不是新特性),並且用示例告訴大家怎麼使用這些特性。那麼接下來,咱們看看這五個新特性是什麼?以及怎麼使用。如果您感興趣,歡迎繼續往下閱讀。

前言

@Daniel Crisp在他的博文中,探討了CSS的五個新特性,介紹了這五個特效能做什麼,以及如何將它們應用到你的專案中。而且提供示例每一步的程式碼,可以在GitHub的倉庫中獲取這些程式碼,不過在接下來,我將會藉助Codepen來向大家展示。

接下來要介紹的五個CSS新特性是:

CSS Display Module Level 3

display:contents

CSS Conditional Rules Module Level 3

@support(。。。){。。。}

CSS Overscroll Behavior Module Level 1

overscroll-behavior: contain

CSS Selectors Module Level 4

:focus-within

:placeholder-shown

CSS Containment Module Level 1

contain:paint

這些CSS特性,估計有些同學已經接觸過了,如果你未接觸過,建議你繼續跟隨著下面的步驟繼續往下閱讀。

案例:建立一個新聞提要(Newsfeed)

透過一個新聞提要為例,分不同的步驟向大家闡述這個新聞提要是怎麼製作的,以及在製作這個案例的時候,這五個CSS特性是如何在案例中得到運用。

Step1:新聞提要的HTML模板

我們這個案例其實很簡單,並未使用任何JavaScript框架,還是使用原始的HTML結構來做這個Demo。所以我們需要一些簡單的HTML的標籤,幫助我們建立Demo。這裡使用了一個類名為

。container

div

,該

div

包含了一個類名為

。feed

ul

,然後建立了十個

li

,每個

li

包含了一個類名為

。card

div

在第五個和第六個

li

之間建立了另一個名為

nested

li

,其包含了一個無序列表

ul

,而且包含了三個

li

建立三個卡片。

  • Card 1
  • Card 2
  • Card 3
  • Card 4
  • Card 5
    • Card A
    • Card B
    • Card C

  • Card 6
  • Card 7
  • Card 8
  • Card 9
  • Card 10

在沒有任何樣式的情況之下,你看到的效果是這樣的:

Step2:新增樣式

現在要給示例新增一些基本樣式,使其看起來更像一個新聞提要:

body {

background-color: grey;

}

。container {

max-width: 800px;

margin: 0 auto;

}

。card {

background-color: #fff;

padding: 10px;

margin: 10px;

min-height: 300px;

}

最後,在

。feed

上使用Flexbox相關的特性,讓每行有兩張卡片:

。feed {

display: flex;

flex-wrap: wrap;

li {

flex: 1 0 50%;

}

}

效果如下:

如果你從未接觸過Flexbox相關的知識,強烈建議你花點時間閱讀這些文章。因為Flexbox發展到今天,已經開始取代

float

來佈局,成為最主流的佈局方式之一,特別是在移動端上的佈局。

Step03:解決佈局問題

當你向下滾動列表時,你會發現

。nested

下的三個

li

(對應的是

CardA ~ CardC

)影響了整體的佈局效果:

五個最新的CSS特性以及如何使用它們

其實我們想要的,或者說理想狀態下,所有的卡片按流的方式排列,但事實並未如此。造成這種現象的原因是Flex容器 ——

ul。feed

設定了

display:flex

(建立了一個Flex容器),建立Flex容器之後,只會對其子元素(

ul。feed > li。card

)有影響,即可子元素自動會變成Flex專案。但不會影響其後代子元素,換句話說,

。nested > li

是無法自動變成Flex專案。

通常解決這個問題的唯一方法是更改HTML模板,但有些情況之下,比如說在CMS系統中(假設你沒有修改HTML標籤的權利),那麼面對這種情況,你就會束手無策了。當然,你也許會想到使用JavaScript來處理。或許以前你會這麼想,但時至今日,咱們可以透過新的CSS特性來解決這個問題 ——

display:contents

W3C規範是這樣對display:contents描述的:

“The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal。 For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree。“

大至意思是:“

元素本身不產生任何邊界框,而元素的子元素與偽元素仍然生成邊界框,元素文字照常顯示。為了同時照顧邊界框與佈局,處理這個元素時,要想象這個元素不在元素樹型結構裡,而只有內容留下。這包括元素在原文件中的子元素與偽元素,比如::before和::after這兩個偽元素,如平常一樣,前者仍然在元素子元素之前生成,後者在之後生成。

那麼

display: contents

這一簡單的程式碼實際上讓元素表現得好像不存在一樣。但仍然可以看到元素的後代,而且元素自身並不影響佈局。也就是說,

。nested

的子元素

。card

也將變成Flex專案。

首先刪除現有

。feed li

的類名,然後在

ul

li

是使用

display: contents

。feed ul,

。feed li {

display: contents;

}

這個時候

。feed

下所有的

。card

都變成了Flex專案(不僅是

。feed

下的子元素

li

,還包括後代的

li

元素):

五個最新的CSS特性以及如何使用它們

現在你看到的所有卡片都是有序的排列,但是尺寸不對:

五個最新的CSS特性以及如何使用它們

可以透過在

。card

上新增

flex

屬性來解決這個問題:

。card {

flex: 1 0 40%;

}

這個時候每張卡片的尺寸就又恢復正常了:

這個時候就好象

ul

不存在了一樣。如果你夠仔細的話,你可以發現

flex-basis

的值設定為

40%

了,雖然我們設定了所有元素的

box-sizing

的值為

border-box

,但大家都知道,

box-sizing

可以影響盒模型的計算,但對

margin

不包括在內,所以為了有足夠的空間放置卡片,把

flex-basis

的值重新計算了,也就是大家所看到的

40%

這個示例也再次向大家說明了

display:contents

的神奇之處。當然,這裡並沒有對

display:contents

做詳細的介紹,但也足夠向大家展示其強大之處。如果你對該特性感興趣,或者想深入的學習,建議閱讀下面這幾篇文章:

“https://www。w3cplus。com/css/how-well-do-you-know-display。html”>如何理解CSS的display屬性

ref=“

https://www。

w3cplus。com/css/display

-contents-is-coming。html

”>CSS的display:contents

ref=“

https://www。

w3cplus。com

/css3/w

hy-display-contents-is-not-css-grid-layout-subgrid。html”>為什麼是display:contents而不是CSS Grid的subgrid

ref=“

https://

bitsofco。de/how-display

-contents-works/

”>How display: contents; Works

Vanishing boxes with display contents

More accessible markup with display: contents

Step04:探索CSS查詢特性

儘管

display:contents

實現了我們想要的效果,但它仍然處於W3C的工作草案狀態。目前只在Chrome 65+、Firefox 59+ 中看到效果。

如果你在瀏覽器開發者工具中,禁掉

display: contents

,你可以看到你的佈局又開始混亂了。這樣做只是模擬瀏覽器不支援該屬性時的效果。那麼我們接下來能做什麼呢?這就引出了下一個CSS新特性 ——

CSS查詢特性

它的原理有點類似於CSS中的媒體查詢(

@media

)一樣,但是它允許你單獨使用CSS表示式,類似於JavaScript語言中的

if / else

之類。如果條件符合應用對應塊中的樣式。接下來讓我們把

display:contents

作為查詢特性的條件,然後將對應的CSS樣式放置在

{。。。}

塊中。就像下面這樣:

@supports (display: contents) {

。feed ul,

。feed li {

display: contents;

}

。card {

flex: 1 0 40%;

}

}

在CSS中,查詢特性很多時候也被稱為CSS的條件特性,其主要包括

@media

@supports

@viewport

。有關於這方面的介紹可以閱讀@webinista寫的PPT —— 《Conditional CSS》。

可能你第一次接觸到

@supports()

的話會感到很好奇,並不知道該屬性的具體使用,如果你願意的話,建議你花點時間閱讀早期整理過的文章《CSS3條件判斷:@supports》和《=“

https://www。

w3cplus。com/css3/suppor

ts-will-change-your-life。html

”>說說CSS中的@supports》。

Step05: 使用

not

關鍵讓程式碼變得更清晰

在CSS的世界中,像

@supports

這樣其實也就是一種漸進增強和優雅降級的方案。我們可以使用

@supports

來新增新的樣式,但也可以新增降級所需的一些原始樣式。

如果忽略IE瀏覽器的話,

@supports

已得到很好的支援。實際上你可能希望使用的是CSS查詢特性,而不是某一種運算子。它的工作方式和你預期的一樣,因此我們可以透過

@supports

not

關鍵詞對那些不支援

display: contents

瀏覽器新增對應的樣式。基於這個原因,我們可以把示例的程式碼修改成:

// 支援 display: contents的瀏覽器,採用的是這段程式碼

@supports (display: contents) {

。feed ul,

。feed li {

display: contents;

}

。card {

flex: 1 0 40%;

}

}

// 不支援display:contents的瀏覽器,採用下面這段程式碼

@supports not (display: contents) {

。feed li {

flex: 1 0 50%;

}

。feed li。nested {

flex-basis: 100%;

}

。feed li。nested ul {

display: flex;

flex-wrap: wrap;

}

}

在支援

display:contens

的瀏覽器,你將看到的效果如下:

五個最新的CSS特性以及如何使用它們

在不支援

display:contents

的瀏覽器,看到的效果又像下面這樣:

五個最新的CSS特性以及如何使用它們

Step06: 更進一步最佳化

經過上面的示例,估計你已經體會到了CSS查詢特性的魅力與潛力了,上面用到的僅僅是查查詢特性中的部分功能,更強大的是你可以

and

or

not

結合起來,讓你的條件表示式更為強大。比如說,你的降級方案除了考慮

display:contents

之外,還會說有可能使用者的瀏覽器對

display:flex

也不支援。在這樣的情況之下,咱們可以繼續降級到

float

的佈局。

不過我們在這裡不會考慮降級到

float

的佈局。但我們可以對

display: flex

display:contents

進行降級處理。這裡會用到

@supports

中的

and

not

關鍵詞。上面的程式碼就變成像下面這樣:

@supports (display: flex) and (display: contents) {

。feed ul,

。feed li {

display: contents;

}

。card {

flex: 1 0 40%;

}

}

@supports (display: flex) and (not (display: contents)) {

。feed li {

flex: 1 0 50%;

}

。feed li。nested {

flex-basis: 100%;

}

。feed li。nested ul {

display: flex;

flex-wrap: wrap;

}

}

甚至你還可以在

@supports

中使用CSS的自定義屬性,比如像下面這樣:

@supports (——foo: green) {

。。。

}

如果你對

@supports

或CSS查詢特性相關的知識點還不足夠滿足的話,建議你閱讀下面的文章,深入的學習這方面的知識:

CSS3條件判斷:@supports

=“

https://www。

w3cplus。com/css3/suppor

ts-will-change-your-life。html

”>說說CSS中的@supports

Conditional CSS

在 CSS 中使用特徵查詢

Conditional CSS using CSS feature queries

Using Feature Queries in CSS

How to use CSS Feature Queries

Basic grid layout with fallbacks using feature queries

Layout Design with CSS Grid & Feature Queries

Feature Queries for CSS Grid fallbacks

案例:聊天框

現在我們有了一個漂亮的新聞提要(Newsfeed),接下來在前面的Newsfeed基礎上新增一個小的聊天框,這個聊天框固定在螢幕的右下角。

Step7: 新增聊天框

我們需要一個訊息列表和一個文字域欄位,方便使用者輸入訊息。那麼在

標籤的後面新增這個聊天框所需要的HTML標籤:

  • Message 1
  • Message 2
  • Message 3
  • Message 4
  • Message 5
  • Message 6
  • Message 7
  • Message 8
  • Message 9
  • Message 10

在沒有給聊天新增任何樣式的情況下,我們看到的效果是:

Step08:給聊天框新增樣式

先給聊天框新增一些基本樣式,讓它看起來有點像聊天框的樣子:

。chat {

background: #fff;

border: 10px solid #000;

bottom: 0;

font-size: 10px;

position: fixed;

right: 0;

width: 300px;

}

。messages {

border-bottom: 5px solid #000;

overflow: auto;

padding: 10px;

max-height: 300px;

}

。message {

background: #000;

border-radius: 5px;

color: #fff;

margin: 0 20% 10px 0;

padding: 10px;

}

。messages li:last-child 。message {

margin-bottom: 0;

}

。input {

border: none;

display: block;

padding: 10px;

width: 100%;

}

效果看起來像下面這樣:

Step09:滾動連結

現在頁面上可以看到已經美化好的聊天框了,這個聊天框有一個可滾動的訊息列表和一個文字輸入框,而且位於前面建立子的Newsfeed上面(如果沒有的話,你可以把你的瀏覽器縮小),如下:

五個最新的CSS特性以及如何使用它們

看上去是不是不錯。但是你有沒有注意到,當你滾動聊天框中的資訊列表到底部的時候,會發生什麼?感興趣的話,親自試一試。咱們做兩個小測試,先滾動頁面

body

,看看效果:

五個最新的CSS特性以及如何使用它們

然後再聊天框的資訊列表中滾動,一直滾動到最底端,滾不動為止,看看效果以是:

五個最新的CSS特性以及如何使用它們

滾動Newsfeed,和我們想象的並沒有差異;但滾動聊天框中的訊息列表時,卻不一樣,滾動到訊息列表末端時,可以看到頁面

body

將開始滾動。這種效果被稱為

滾動連結

,即

Scroll Chaining

在我們這個示例中,這可能不是什麼大問題,但在某些情況下,它可能就是一大問題了。比如Modal彈框,那就很有必要解決這樣現象。

比較拙的解決方案就是給

body

新增

overflow:hidden

,但這有可能會影響我們的操作,甚至影響你瀏覽你的頁面。但值得慶幸的是,CSS有一個新特性可以做得更為完美,體驗更佳,而且使用起來並不複雜,只需要一行程式碼即可,那就是CSS的

overscroll-behavior

,這個屬性有三個可取值:

auto

:其預設值。元素(容器)的滾動會傳播給其祖先元素。有點類似JavaScript中的冒泡行為一樣

contain

:阻止滾動連結。滾動行為不會傳播給其祖先元素,但會影響節點內的區域性顯示。例如,Android上的光輝效果或iOS上的回彈效果。當用戶觸控滾動邊界時會通知使用者。注意,

overscroll-behavior:contain

html

元素上使用,可以阻止導航滾動操作

none

:和

contain

一樣,但它也可以防止節點本身的滾動效果

overscroll-behavior

屬性是

overscroll-behavior-x

overscroll-behavior-y

的簡寫,如果你只想控制其中一個方向的滾動行為,可以使用其中的某一個屬性。

回到我們的示例來,在

。messages

類中新增下面這行程式碼:

。messages {

overscroll-behavior-y: contain;

}

現在你再嘗試一下,在聊天框中的訊息列表中上下滾動。此時你再滾動到訊息列表末端時,它不再會影響

body

的滾動了(頁面的滾動):

五個最新的CSS特性以及如何使用它們

如果你想在PWA中實現下拉重新整理的效果,比如下拉時重新整理Newsfeed,那麼這個屬性就非常方便。只需要在

body

html

元素中新增

overscroll-behavior:contain

即可。

值得注意的是,這個屬性還不是W3C標準,而是Web孵化器WICG的一個建議。不過,說不定哪一天,這個特性就進入到W3C工作組中,成為W3C的一個標準。

有關於這方面的更多介紹,建議閱讀下面幾篇文章:

滾動的特性

ref=“

https://www。

w3cplus。com/css/overscr

oll-behavior。html

”>CSS overscroll-behavior

Take control of your scroll: customizing pull-to-refresh and overflow effects

Step10:摺疊聊天框

目前,聊天框佔據了相當大的空間,如果我們不與其互動的話,會有點分散使用者的注意力。辛運的是,我們可以用CSS的選擇器特性來解決這個問題。這也是CSS的另一新特性,再一次向大家展示了CSS的魔力。

首先調整一下現有的樣式。預設情況下,我們希望聊天框是處理一個摺疊狀態,因此把

。message

max-height

值重置一下,在此設定為

0

,並且把

padding

也重置為

0

。因為這個值剛剛好摺疊了聊天框,而且又不影響其美觀。為了讓聊天框摺疊和展開時有一個過渡的動畫效果,藉助ref=“

https://www。

w3cplus。com/blog/tags/9

4。html

”>CSS的transition屬性來實現。

。messages {

。。。

max-height: 0;

padding: 0;

transition: max-height 500ms;

}

效果看起來還不錯,如下所示:

Step11:當聊天框得到焦點時,展開聊天框

現在我們的聊天框中的資訊列表是看不到。因為我們前面把資訊列表摺疊起來了。現在我們要思考的是如何透過CSS來將其展開。這就會用到CSS的另一新特性 ——

:focus-within

有點類似於

:focus

偽類選擇器一樣,但是

:focus-within

與其不同之處是,

如果元素的任何後代元素得到焦點,它就會被匹配

。這就是這個屬性特別之處,因為它與CSS通常的工作方式相反,通常我們只能根據元素的祖先來選擇元素。

在我們這個示例中,當

。chat

區域內的任何內容得到焦點時,重置一下

。message

max-height

padding

值。請記住,一個元素必須接受鍵盤或滑鼠事件或其他形式的輸入,以便接收焦點。比如我們這個示例,點選

輸入框就符合這個要求,可以達到我們想要的預期效果。

。chat:focus-within 。messages {

max-height: 300px;

padding: 10px;

}

你現在可以嘗試一下效果。點選

input

讓其得到焦點,可以看到聊天框可以展開,反之聊天框又會摺疊起來:

五個最新的CSS特性以及如何使用它們

Step12:進一步突顯

:focus-within

的魔力

如果僅僅實現聊天框的摺疊和展開效果,到上一步其實已經完成了。但對於一位有追求的前端,總是在嘗試很多極限性。回到我們的示例中來,如果PM跟你提了一個新需求,當文字輸入框得到焦點之後,除了能展開聊天框之外,還希望聊天框底下的Newsfeed變得模糊。對於這樣的一個效果,怎麼來實現呢?

要實現這樣的效果,其實並不複雜,如果你有做過自定義單選按鈕或複選框(當然是純CSS),你應該會想到解決方案。我們可以使用CSS選擇器中的兄弟組合器~,就可以很容易的做到這一點。使用

~

選擇器有一個前提需要注意,聊天框

。chat

需要在Newsfeed(

。container

)前面(指的是HTML結構,事實上我們已經這樣做了)。只有這樣才能透過下面的方式讓Newsfeed變得模糊:

。chat:focus-within ~ 。container {

filter: blur(5px)

}

當然,這可能不是最佳的一個方案,但僅透過CSS的技術手段就能達到預期的效果,已經很酷了。感興趣的話,自己可以體驗一下:

五個最新的CSS特性以及如何使用它們

注意,Newfeed添加了

filter

效果,這將會改變元素的層疊順序,造成聊天框在Newsfeed下面。所以需要顯式的

。chat

中新增

z-index

的值。比如這裡設定了

z-index: 1001

。具體原因可以查閱@張鑫旭老師的《深入理解CSS中的層疊上下文和層疊順序》一文。

探索

:placeholder-shown

五個最新的CSS特性以及如何使用它們

首先要先分清楚,

:placeholder-shown

::placeholder

是不同的兩個東東。神奇的是

:placholder-shown

是W3C標準規範的一個屬性,而

::placeholder

卻不是。

::placeholder-shown

仍然會影響佔位符文字的樣式。

注意:

:placeholder-shown

是一個偽類選擇器(它是一個處於特定狀態的元素);

::placeholder

是一個偽元素(一個在DOM中並不存在的可見元素)。

另外,

:placeholder-shown

也是新的選擇器之一(CSS Selectors Module Level 4新增了很多種偽類選擇器),它可以匹配任何顯示佔位符文字的輸入。在我們的示例中,文字輸入框(

input

)並沒有任何佔位符文字,所以先在HTML中的

input

元素中,新增

placeholder

,新增佔位符文字。

然後在

input

之後新增一個新的元素,用來幫助使用者操作:

Press enter to send

現在給這個幫助資訊

。prompt

新增一些樣式,預設情況之它是被摺疊起來了。

。prompt {

line-height: 2em;

max-height: 0;

overflow: hidden;

padding: 0 10px;

text-align: right;

transition: max-height 500ms;

}

僅從外觀上看,似乎好像沒多出什麼,就是在文字框中多了一個佔位符文字:

五個最新的CSS特性以及如何使用它們

雖然沒多大區別,但這為後續的效果已埋下了一個伏筆。接著往下看。

Step14:使用提示資訊可見

此時提示資訊處於摺疊狀態,並不可見,我想大家也想到了,要怎麼使用

:placeholder-shown

讓其可見?大多數瀏覽器會顯示佔位符文字,直到使用者在

input

中輸入真的值。為了提高使用者使用表單的體驗,如果

input

得到對應的焦點之後,佔位符文字並不隱藏,還起著提示作用,是不是更有意思,也對使用者有更好的幫助,畢竟我們不希望使用者傳送空的訊息,所以我們可以將這種行為關聯起來,只有在使用者輸入值時才顯示提示資訊(也就是

。prompt

展開可見)。

:placeholder-shown

表示的是佔位文字符可見的狀態,而提示資訊可見的時候,佔位文字符不可見,也就是

input

有了一個真正的值。換句話來說,我們需要有一個

:placeholder-shown

的反轉(佔位文字符不可見),這個時候我們可以藉助

:not()

選擇器來幫我們做這樣的反轉。

。input:not(:placeholder-shown) + 。prompt {

max-height: 2em;

}

max-height

設定為

font-size:10px

的兩倍,這裡使用了

2em

,這個時候可以展開提信資訊塊。簡單而有整潔。如果這個看似平凡的偽類選擇器能過透過最終的規範,那麼我們將會看到一些巧妙的運用。來到這一步,效果變成:

親自體驗一下,你在

input

隨便輸入一點內容,哪怕是空格,也能看到提示資訊被展示出來了:

五個最新的CSS特性以及如何使用它們

不管

:focus-within

還是

:placeholder-shown

,它們都是CSS選擇器新增加的偽類選擇器,如果感興趣,建議你花些時間對這些方面進行了一瞭解:

Focusing on Focus Styles

A CSS Approach to Trap Focus Inside of an Element

ref=“

https://www。

scottohara。me/blog/2017

/05/14/focus-within。html

”>CSS :focus-within

ref=“

https://www。

w3cplus。com/css/focus-w

ithin。html

”>CSS :focus-within via @w3cplus

:placeholder-shown

Visually validate an input field using CSS

Intriguing CSS Level 4 Selectors

The Future Generation of CSS Selectors: Level 4

下一代選擇器:CSS4

即將推出的CSS4 Level 4 Selectors

CSS Level 4 Selectors to Watch Out For

Step15:讓它充滿生機

到目前為止,我們透過簡單的HTML和一些CSS特性完成了一個帶有聊天功能的新聞提要的基本架構,但是目前它是沒有生命的,只是一個純靜態的東西。也就是說使用者並不有用它做任何事情。這個案例包含了一些有趣的CSS新特性,但到現在為止不能修改DOM。如果想讓這個案例更為生動,那麼就需要藉助一些JavaScript功能,以便使用者能透過聊天框新增訊息。

首先,需要向

和類名

。messages

的子元素

ul

新增一個

ID

,以便JavaScript更好的獲取到對應的元素。同時給

input

元素新增一個

required

屬性,當用戶未輸入任何資訊的時候,表單可以自動較驗。

    然後建立一個名為

    script。js

    檔案,並且放置在

    之前。不過我們的案例是在Codepen上做相應的演示,所以無需考慮建立一個單的

    。js

    檔案。

    Step16:新增一些JavaScript

    我們需要給

    新增一個事件函式,當監聽到鍵盤的

    Enter

    事件,獲取到

    input

    的值(如果有效)並將其新增到訊息列表的末尾,清除欄位並滾動到訊息的底部。

    // 獲取相應的元素

    const input = document。getElementById(‘input’);

    const messages = document。getElementById(‘messages’);

    // 監聽input的鍵盤事件

    input。addEventListener(‘keypress’, (event) => {

    // 檢查是否按下Enter鍵

    if (event。keyCode === 13) {

    // 檢查欄位是否有效

    if (input。validity。valid) {

    // 使用該值建立DOM元素

    const message = createMessage(input。value);

    // 將新建立的DOM元素新增到訊息列表

    messages。appendChild(message);

    // 清除輸入框的值

    input。value = ‘’;

    // 滾動到訊息列表的底部

    messages。parentNode。scrollTop = messages。parentNode。scrollHeight;

    }

    }

    });

    // 將input的值轉換為HTML的字串

    function createMessage (value) {

    return stringToDom(`

  • ${value}
  • `)

    }

    // 將字串轉換為真實的DOM

    function stringToDom (string) {

    const template = document。createElement(‘template’);

    template。innerHTML = string。trim();

    return template。content。firstChild;

    }

    現在,當你在

    input

    中輸入欄位並按

    Enter

    鍵時,你將看到你輸入的訊息新增到訊息列表的底部。

    五個最新的CSS特性以及如何使用它們

    Step17:新增一引起額外的資訊

    為了向大家演示最後一個CSS新特性 ——

    contain

    ,咱們需要做一些設計。我們將實現一個效果,在訊息列表頂部的框中傳送新訊息的時間。當你將滑鼠懸停在訊息上時,就會有這個效果。

    首先,我們需要將這些資訊新增到我們的新訊息中。我們可以修改

    createMessage

    函式返回的值。

    function createMessage (value) {

    return stringToDom(`

  • ${value}

  • `);

    }

    你已經注意到了,在

    message

    中新增加了一個類

    message——mine

    。並給這個類新增相應的樣式:

    。message——mine {

    background: #ff2089;

    margin-left: 20%;

    margin-right: 0;

    }

    當你新輸入內容,按下

    Enter

    鍵時,新增加的訊息列表對應的結構就變成像下圖這樣的:

    五個最新的CSS特性以及如何使用它們

    顯示時間戳

    我們的目的是將建立訊息的時間戳顯示在訊息列表的頂部,我們需要這樣做,以便即使在滾動訊息列表時,這個時間戳也總是可見的。這裡我們藉助CSS的偽元素來做:

    。message——mine::after {

    content: attr(data-timestamp);

    }

    這個時候你所看到的效果是這樣的:

    五個最新的CSS特性以及如何使用它們

    這個效果並不是我們想要的。我們在樣式上稍做修改,滑鼠懸浮到新新增的訊息列表上時才能看到時間戳,而且這個時間戳固定在訊息區域的頂部。

    。message——mine:hover::after {

    background: #000;

    color: #ff2089;

    content: attr(data-timestamp);

    left: 0;

    padding: 5px;

    position: fixed;

    top: 0;

    width: 100%;

    }

    這個效果現在變成這樣了:

    五個最新的CSS特性以及如何使用它們

    現在時間戳固定在頁面的頂部,可以繼續最佳化一下,在

    。messages

    中新增

    position: relative

    但也不起作用,那是因為固定定位是相對於

    viewport

    的,而不是相對於其祖先元素。那麼這個時候,最後一個CSS新特性應該要出場了。

    Step19:探索Containment

    CSS Containment是一個令人興奮的新命題。它有許多選項,可以限制瀏覽器的樣式、佈局和對特定元素的繪製。這在修改DOM時特別有用。在瀏覽器中,哪怕是很小的變化都有可能造成瀏覽器重繪整個頁面,這樣的消費是很貴,即使瀏覽器努力為我們做了很多最佳化,頁面的重繪還是對效能有一定影響的。

    使用CSS Containment,我們可以把頁面的部分圈起來,然後說“這裡發生了什麼,只在這裡做相應的事”。這也是另一種方法,可以保護元素不受外部的變化而受影響。

    五個最新的CSS特性以及如何使用它們

    CSS的Containment是一個新屬性,使用關鍵字

    contain

    ,它支援四個屬性值:

    layout

    :這個值開啟該元素的佈局控制。這確保所包含元素對佈局目的完全不透明;外部不能影響其內部佈局,反之亦然

    paint

    :這個值開啟該元素的繪製控制。這確保包含元素的後代節點不顯示在其邊界外,因此,如果一個元素在螢幕外或是不可見的,它的後代節點同樣也被保證是不可見的

    size

    :這個值開啟該元素的尺寸控制。這確保包含元素可以無需檢查其後代節點進行佈局。

    style

    :這個值開啟該元素的樣式控制。這確保了,對於效能這會不僅僅作用於一個元素及其後代,這些效果也不忽視包含的元素

    您還可以結合關鍵字,如

    contain: layout paint

    ,這將僅適用於一個元素的這些行為。但也包含支援兩個額外的值:

    contain: strict

    意同

    contain: layout style paint size

    contain: content

    意同

    contain: layout style paint

    每個值都有點不透明,所以我建議你閱讀規範並在開發者工具中使用它們來檢視實際發生的情況。

    layout

    paint

    是兩個重要的值,因為它們在需要大量操作DOM時,對效能有一定的最佳化。然而,在我們的演示中,我們可以利用

    contain: paint

    我助我們進行時間戳定位。

    根據規範所描述,當使用

    paint

    時,“

    元素作為一個包含絕對定位和固定定位後代的塊

    ”。這意味著,我們可以在

    。chat

    上設定

    contain: paint

    ,這樣一來,

    。chat

    中元素的固定定位將基於

    card

    而不是

    viewport

    。你可以透過使用

    transform: translateZ(0)

    獲得相同的效果。

    嘗試一下下,效果完美了:

    五個最新的CSS特性以及如何使用它們

    CSS Containment是較新的特性,目前只在Chrome 52+版本可以看到。如果你想深入的瞭解這方面的知識,可以閱讀一下下面的文章:

    CSS Containment in Chrome 52(譯文)

    總結

    到這裡就結束了,我們對這五個新的CSS特性有了一定的瞭解。其中大多數都是非常簡單的,但對於CSS Containment而言還是較為複雜,建議花更多的時間去詳細瞭解。雖然這是一些新特性,而且在部分瀏覽器中還未得到較好的支援,但這些新特終將有一天會來到你的身邊,你可以在專案中使用。今天花這麼的篇幅,並且透過兩個示例來闡述這五個特性,主要是向大家展示這五個特性有何功能,如何在實際專案中使用。

    文章篇幅較長,感謝你花這麼長的時間閱讀完這篇文章。最後再次感謝

    @Daniel Crisp整理的內容和帶來的案例

    如需轉載,煩請註明出處:

    https://www。

    w3cplus。com/css/5-hot-n

    ew-css-features-and-how-to-use-them。html