久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

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

 前端技術(shù)分享 2019-04-02

雖然CSS簡(jiǎn)單,但CSS是一門(mén)非常有意思的語(yǔ)言,,CSS每年都有變化,,而且都有不同的博主都在不同的時(shí)間段總結(jié)一些CSS的新特性,。雖然這些新特性無(wú)法立刻得到眾多瀏覽器的支持,,但總是隨著時(shí)間的發(fā)展,這些特性都會(huì)得到瀏覽器的支持,。哪怕未得到支持,,也有一些方法讓瀏覽器支持,比如最為出外的cssnext,,就可以讓很多未來(lái)的CSS特性就立馬使用,,并且不用花太多時(shí)間來(lái)考慮瀏覽器的兼容性。

接下來(lái)要介紹的五個(gè)CSS新特性是:

這些CSS特性,,估計(jì)有些同學(xué)已經(jīng)接觸過(guò)了,,如果你未接觸過(guò),建議你繼續(xù)跟隨著下面的步驟繼續(xù)往下閱讀,。

案例:創(chuàng)建一個(gè)新聞提要(Newsfeed)

通過(guò)一個(gè)新聞提要為例,,分不同的步驟向大家闡述這個(gè)新聞提要是怎么制作的,以及在制作這個(gè)案例的時(shí)候,,這五個(gè)CSS特性是如何在案例中得到運(yùn)用,。

Step1:新聞提要的HTML模板

我們這個(gè)案例其實(shí)很簡(jiǎn)單,并未使用任何JavaScript框架,,還是使用原始的HTML結(jié)構(gòu)來(lái)做這個(gè)Demo,。所以我們需要一些簡(jiǎn)單的HTML的標(biāo)簽,幫助我們創(chuàng)建Demo,。這里使用了一個(gè)類(lèi)名為.containerdiv,,該div包含了一個(gè)類(lèi)名為.feedul,然后創(chuàng)建了十個(gè)li,,每個(gè)li包含了一個(gè)類(lèi)名為.carddiv,。

在第五個(gè)和第六個(gè)li之間創(chuàng)建了另一個(gè)名為nestedli,其包含了一個(gè)無(wú)序列表ul,而且包含了三個(gè)li創(chuàng)建三個(gè)卡片,。

<div class="container">
    <ul class="feed">
        <li><div class="card">Card 1</div></li>
        <li><div class="card">Card 2</div></li>
        <li><div class="card">Card 3</div></li>
        <li><div class="card">Card 4</div></li>
        <li><div class="card">Card 5</div></li>
        <li class="nested">
            <ul>
                <li><div class="card">Card A</div></li>
                <li><div class="card">Card B</div></li>
                <li><div class="card">Card C</div></li>
            </ul>
        </li>
        <li><div class="card">Card 6</div></li>
        <li><div class="card">Card 7</div></li>
        <li><div class="card">Card 8</div></li>
        <li><div class="card">Card 9</div></li>
        <li><div class="card">Card 10</div></li>
    </ul>
</div>

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

<iframe id="MBvPvX" src="https:///airen/embed/MBvPvX?height=400&theme-id=0&slug-hash=MBvPvX&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

Step2:添加樣式

現(xiàn)在要給示例添加一些基本樣式,,使其看起來(lái)更像一個(gè)新聞提要:

body {
    background-color: grey;
}

.container {
    max-width: 800px;
    margin: 0 auto;
}

.card {
    background-color: #fff;
    padding: 10px;
    margin: 10px;
    min-height: 300px;
}

最后,,在.feed上使用Flexbox相關(guān)的特性,讓每行有兩張卡片:

.feed {
    display: flex;
    flex-wrap: wrap;

    li {
        flex: 1 0 50%;
    }
}

效果如下:

<iframe id="mjMzGO" src="https:///airen/embed/mjMzGO?height=400&theme-id=0&slug-hash=mjMzGO&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

如果你從未接觸過(guò)Flexbox相關(guān)的知識(shí),,強(qiáng)烈建議你花點(diǎn)時(shí)間閱讀這些文章,。因?yàn)镕lexbox發(fā)展到今天,已經(jīng)開(kāi)始取代float來(lái)布局,,成為最主流的布局方式之一,,特別是在移動(dòng)端上的布局。

Step03:解決布局問(wèn)題

當(dāng)你向下滾動(dòng)列表時(shí),,你會(huì)發(fā)現(xiàn).nested下的三個(gè)li(對(duì)應(yīng)的是CardA ~ CardC)影響了整體的布局效果:

image

image

其實(shí)我們想要的,,或者說(shuō)理想狀態(tài)下,所有的卡片按流的方式排列,,但事實(shí)并未如此,。造成這種現(xiàn)象的原因是Flex容器 —— ul.feed設(shè)置了display:flex(創(chuàng)建了一個(gè)Flex容器),創(chuàng)建Flex容器之后,,只會(huì)對(duì)其子元素(ul.feed > li.card)有影響,,即可子元素自動(dòng)會(huì)變成Flex項(xiàng)目。但不會(huì)影響其后代子元素,,換句話(huà)說(shuō),,.nested > li是無(wú)法自動(dòng)變成Flex項(xiàng)目,。

通常解決這個(gè)問(wèn)題的唯一方法是更改HTML模板,但有些情況之下,,比如說(shuō)在CMS系統(tǒng)中(假設(shè)你沒(méi)有修改HTML標(biāo)簽的權(quán)利),,那么面對(duì)這種情況,你就會(huì)束手無(wú)策了,。當(dāng)然,,你也許會(huì)想到使用JavaScript來(lái)處理?;蛟S以前你會(huì)這么想,,但時(shí)至今日,咱們可以通過(guò)新的CSS特性來(lái)解決這個(gè)問(wèn)題 —— display:contents,。

W3C規(guī)范是這樣對(duì)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.“

大至意思是:“元素本身不產(chǎn)生任何邊界框,,而元素的子元素與偽元素仍然生成邊界框,元素文字照常顯示,。為了同時(shí)照顧邊界框與布局,,處理這個(gè)元素時(shí),要想象這個(gè)元素不在元素樹(shù)型結(jié)構(gòu)里,,而只有內(nèi)容留下,。這包括元素在原文檔中的子元素與偽元素,比如::before::after這兩個(gè)偽元素,,如平常一樣,,前者仍然在元素子元素之前生成,后者在之后生成,。

那么display: contents這一簡(jiǎn)單的代碼實(shí)際上讓元素表現(xiàn)得好像不存在一樣,。但仍然可以看到元素的后代,而且元素自身并不影響布局,。也就是說(shuō),,.nested的子元素.card也將變成Flex項(xiàng)目。

首先刪除現(xiàn)有.feed li的類(lèi)名,,然后在ulli是使用display: contents

.feed ul,
.feed li {
    display: contents;
}

這個(gè)時(shí)候.feed下所有的.card都變成了Flex項(xiàng)目(不僅是.feed下的子元素li,,還包括后代的li元素):

image

image

現(xiàn)在你看到的所有卡片都是有序的排列,但是尺寸不對(duì):

image

image

可以通過(guò)在.card上添加flex屬性來(lái)解決這個(gè)問(wèn)題:

.card {
    flex: 1 0 40%;
}

這個(gè)時(shí)候每張卡片的尺寸就又恢復(fù)正常了:

<iframe id="KBvbZg" src="https:///airen/embed/KBvbZg?height=400&theme-id=0&slug-hash=KBvbZg&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

這個(gè)時(shí)候就好象ul不存在了一樣,。如果你夠仔細(xì)的話(huà),,你可以發(fā)現(xiàn)flex-basis的值設(shè)置為40%了,雖然我們?cè)O(shè)置了所有元素的box-sizing的值為border-box,,但大家都知道,,box-sizing可以影響盒模型的計(jì)算,但對(duì)margin不包括在內(nèi),,所以為了有足夠的空間放置卡片,,把flex-basis的值重新計(jì)算了,,也就是大家所看到的40%

這個(gè)示例也再次向大家說(shuō)明了display:contents的神奇之處,。當(dāng)然,,這里并沒(méi)有對(duì)display:contents做詳細(xì)的介紹,但也足夠向大家展示其強(qiáng)大之處,。如果你對(duì)該特性感興趣,,或者想深入的學(xué)習(xí),建議閱讀下面這幾篇文章:

Step04:探索CSS查詢(xún)特性

盡管display:contents實(shí)現(xiàn)了我們想要的效果,,但它仍然處于W3C的工作草案狀態(tài),。目前只在Chrome 65+、Firefox 59+ 中看到效果,。

如果你在瀏覽器開(kāi)發(fā)者工具中,,禁掉display: contents,你可以看到你的布局又開(kāi)始混亂了,。這樣做只是模擬瀏覽器不支持該屬性時(shí)的效果,。那么我們接下來(lái)能做什么呢?這就引出了下一個(gè)CSS新特性 —— CSS查詢(xún)特性,。

它的原理有點(diǎn)類(lèi)似于CSS中的媒體查詢(xún)@media)一樣,,但是它允許你單獨(dú)使用CSS表達(dá)式,類(lèi)似于JavaScript語(yǔ)言中的if / else之類(lèi),。如果條件符合應(yīng)用對(duì)應(yīng)塊中的樣式,。接下來(lái)讓我們把display:contents作為查詢(xún)特性的條件,然后將對(duì)應(yīng)的CSS樣式放置在{...}塊中,。就像下面這樣:

@supports (display: contents) {
    .feed ul,
    .feed li {
        display: contents;
    }
    .card {
        flex: 1 0 40%;
    }
}

<iframe id="QBMYRx" src="https:///airen/embed/QBMYRx?height=400&theme-id=0&slug-hash=QBMYRx&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

在CSS中,,查詢(xún)特性很多時(shí)候也被稱(chēng)為CSS的條件特性,,其主要包括@media,、@supports@viewport。有關(guān)于這方面的介紹可以閱讀@webinista寫(xiě)的PPT —— 《Conditional CSS》,。

可能你第一次接觸到@supports()的話(huà)會(huì)感到很好奇,,并不知道該屬性的具體使用,如果你愿意的話(huà),,建議你花點(diǎn)時(shí)間閱讀早期整理過(guò)的文章《CSS3條件判斷:@supports》和《說(shuō)說(shuō)CSS中的@supports》,。

Step05: 使用not關(guān)鍵讓代碼變得更清晰

在CSS的世界中,像@supports這樣其實(shí)也就是一種漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)的方案,。我們可以使用@supports來(lái)添加新的樣式,,但也可以添加降級(jí)所需的一些原始樣式。

如果忽略IE瀏覽器的話(huà),,@supports已得到很好的支持,。實(shí)際上你可能希望使用的是CSS查詢(xún)特性,,而不是某一種操作符。它的工作方式和你預(yù)期的一樣,,因此我們可以通過(guò)@supportsnot關(guān)鍵詞對(duì)那些不支持display: contents瀏覽器添加對(duì)應(yīng)的樣式,。基于這個(gè)原因,,我們可以把示例的代碼修改成:

// 支持 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;
    }
}

<iframe id="XBaGZm" src="https:///airen/embed/XBaGZm?height=400&theme-id=0&slug-hash=XBaGZm&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

在支持display:contens的瀏覽器,,你將看到的效果如下:

image

image

在不支持display:contents的瀏覽器,,看到的效果又像下面這樣:

image

image

Step06: 更進(jìn)一步優(yōu)化

經(jīng)過(guò)上面的示例,估計(jì)你已經(jīng)體會(huì)到了CSS查詢(xún)特性的魅力與潛力了,,上面用到的僅僅是查查詢(xún)特性中的部分功能,,更強(qiáng)大的是你可以andornot結(jié)合起來(lái),,讓你的條件表達(dá)式更為強(qiáng)大,。比如說(shuō),你的降級(jí)方案除了考慮display:contents之外,,還會(huì)說(shuō)有可能用戶(hù)的瀏覽器對(duì)display:flex也不支持,。在這樣的情況之下,咱們可以繼續(xù)降級(jí)到float的布局,。

不過(guò)我們?cè)谶@里不會(huì)考慮降級(jí)到float的布局,。但我們可以對(duì)display: flexdisplay:contents進(jìn)行降級(jí)處理。這里會(huì)用到@supports中的andnot關(guān)鍵詞,。上面的代碼就變成像下面這樣:

@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;
    }
}

<iframe id="JByVbM" src="https:///airen/embed/JByVbM?height=400&theme-id=0&slug-hash=JByVbM&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

甚至你還可以在@supports中使用CSS的自定義屬性,,比如像下面這樣:

@supports (--foo: green) {
    ...
}

如果你對(duì)@supports或CSS查詢(xún)特性相關(guān)的知識(shí)點(diǎn)還不足夠滿(mǎn)足的話(huà),建議你閱讀下面的文章,,深入的學(xué)習(xí)這方面的知識(shí):

案例:聊天框

現(xiàn)在我們有了一個(gè)漂亮的新聞提要(Newsfeed),,接下來(lái)在前面的Newsfeed基礎(chǔ)上添加一個(gè)小的聊天框,這個(gè)聊天框固定在屏幕的右下角,。

Step7: 添加聊天框

我們需要一個(gè)消息列表和一個(gè)文本域字段,,方便用戶(hù)輸入消息。那么在<body>標(biāo)簽的后面添加這個(gè)聊天框所需要的HTML標(biāo)簽:

<div class="chat">
    <div class="messages">
        <ul>
            <li><div class="message">Message 1</div></li>
            <li><div class="message">Message 2</div></li>
            <li><div class="message">Message 3</div></li>
            <li><div class="message">Message 4</div></li>
            <li><div class="message">Message 5</div></li>
            <li><div class="message">Message 6</div></li>
            <li><div class="message">Message 7</div></li>
            <li><div class="message">Message 8</div></li>
            <li><div class="message">Message 9</div></li>
            <li><div class="message">Message 10</div></li>
        </ul>
    </div>
    <input type="text" class="input">
</div>

在沒(méi)有給聊天添加任何樣式的情況下,,我們看到的效果是:

<iframe id="pZrBKR" src="https:///airen/embed/pZrBKR?height=400&theme-id=0&slug-hash=pZrBKR&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

Step08:給聊天框添加樣式

先給聊天框添加一些基本樣式,,讓它看起來(lái)有點(diǎn)像聊天框的樣子:

.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%;
}

效果看起來(lái)像下面這樣:

<iframe id="yqorwX" src="https:///airen/embed/yqorwX?height=400&theme-id=0&slug-hash=yqorwX&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

Step09:滾動(dòng)鏈接

現(xiàn)在頁(yè)面上可以看到已經(jīng)美化好的聊天框了,這個(gè)聊天框有一個(gè)可滾動(dòng)的消息列表和一個(gè)文本輸入框,,而且位于前面創(chuàng)建子的Newsfeed上面(如果沒(méi)有的話(huà),,你可以把你的瀏覽器縮小),如下:

image

image

看上去是不是不錯(cuò),。但是你有沒(méi)有注意到,,當(dāng)你滾動(dòng)聊天框中的信息列表到底部的時(shí)候,會(huì)發(fā)生什么,?感興趣的話(huà),,親自試一試。咱們做兩個(gè)小測(cè)試,,先滾動(dòng)頁(yè)面body,,看看效果:

image

image

然后再聊天框的信息列表中滾動(dòng),一直滾動(dòng)到最底端,,滾不動(dòng)為止,,看看效果以是:

image

image

滾動(dòng)Newsfeed,和我們想象的并沒(méi)有差異,;但滾動(dòng)聊天框中的消息列表時(shí),,卻不一樣,滾動(dòng)到消息列表末端時(shí),,可以看到頁(yè)面body將開(kāi)始滾動(dòng),。這種效果被稱(chēng)為滾動(dòng)鏈接,即Scroll Chaining,。

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

比較拙的解決方案就是給body添加overflow:hidden,,但這有可能會(huì)影響我們的操作,甚至影響你瀏覽你的頁(yè)面,。但值得慶幸的是,,CSS有一個(gè)新特性可以做得更為完美,體驗(yàn)更佳,,而且使用起來(lái)并不復(fù)雜,,只需要一行代碼即可,,那就是CSS的overscroll-behavior,,這個(gè)屬性有三個(gè)可取值:

  • auto:其默認(rèn)值。元素(容器)的滾動(dòng)會(huì)傳播給其祖先元素,。有點(diǎn)類(lèi)似JavaScript中的冒泡行為一樣

  • contain:阻止?jié)L動(dòng)鏈接,。滾動(dòng)行為不會(huì)傳播給其祖先元素,但會(huì)影響節(jié)點(diǎn)內(nèi)的局部顯示。例如,,Android上的光輝效果或iOS上的回彈效果,。當(dāng)用戶(hù)觸摸滾動(dòng)邊界時(shí)會(huì)通知用戶(hù)。注意,,overscroll-behavior:containhtml元素上使用,,可以阻止導(dǎo)航滾動(dòng)操作

  • none:和contain一樣,但它也可以防止節(jié)點(diǎn)本身的滾動(dòng)效果

overscroll-behavior屬性是overscroll-behavior-xoverscroll-behavior-y的簡(jiǎn)寫(xiě),,如果你只想控制其中一個(gè)方向的滾動(dòng)行為,,可以使用其中的某一個(gè)屬性。

回到我們的示例來(lái),,在.messages類(lèi)中添加下面這行代碼:

.messages {
    overscroll-behavior-y: contain;
}

<iframe id="xJLNWo" src="https:///airen/embed/xJLNWo?height=400&theme-id=0&slug-hash=xJLNWo&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

現(xiàn)在你再?lài)L試一下,,在聊天框中的消息列表中上下滾動(dòng)。此時(shí)你再滾動(dòng)到消息列表末端時(shí),,它不再會(huì)影響body的滾動(dòng)了(頁(yè)面的滾動(dòng)):

image

image

如果你想在PWA中實(shí)現(xiàn)下拉刷新的效果,,比如下拉時(shí)刷新Newsfeed,那么這個(gè)屬性就非常方便,。只需要在bodyhtml元素中添加overscroll-behavior:contain即可,。

值得注意的是,這個(gè)屬性還不是W3C標(biāo)準(zhǔn),,而是Web孵化器WICG的一個(gè)建議,。不過(guò),說(shuō)不定哪一天,,這個(gè)特性就進(jìn)入到W3C工作組中,,成為W3C的一個(gè)標(biāo)準(zhǔn)。

有關(guān)于這方面的更多介紹,,建議閱讀下面幾篇文章:

Step10:折疊聊天框

目前,,聊天框占據(jù)了相當(dāng)大的空間,如果我們不與其交互的話(huà),,會(huì)有點(diǎn)分散用戶(hù)的注意力,。辛運(yùn)的是,我們可以用CSS的選擇器特性來(lái)解決這個(gè)問(wèn)題,。這也是CSS的另一新特性,,再一次向大家展示了CSS的魔力。

首先調(diào)整一下現(xiàn)有的樣式,。默認(rèn)情況下,,我們希望聊天框是處理一個(gè)折疊狀態(tài),因此把.messagemax-height值重置一下,,在此設(shè)置為0,,并且把padding也重置為0,。因?yàn)檫@個(gè)值剛剛好折疊了聊天框,而且又不影響其美觀(guān),。為了讓聊天框折疊和展開(kāi)時(shí)有一個(gè)過(guò)渡的動(dòng)畫(huà)效果,,借助CSS的transition屬性來(lái)實(shí)現(xiàn)。

.messages {
    ...
    max-height: 0;
    padding: 0;
    transition: max-height 500ms; 
}

效果看起來(lái)還不錯(cuò),,如下所示:

<iframe id="Owjeyz" src="https:///airen/embed/Owjeyz?height=400&theme-id=0&slug-hash=Owjeyz&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

Step11:當(dāng)聊天框得到焦點(diǎn)時(shí),,展開(kāi)聊天框

現(xiàn)在我們的聊天框中的信息列表是看不到。因?yàn)槲覀兦懊姘研畔⒘斜碚郫B起來(lái)了?,F(xiàn)在我們要思考的是如何通過(guò)CSS來(lái)將其展開(kāi),。這就會(huì)用到CSS的另一新特性 —— :focus-within

有點(diǎn)類(lèi)似于:focus偽類(lèi)選擇器一樣,,但是:focus-within與其不同之處是,,如果元素的任何后代元素得到焦點(diǎn),它就會(huì)被匹配,。這就是這個(gè)屬性特別之處,,因?yàn)樗cCSS通常的工作方式相反,通常我們只能根據(jù)元素的祖先來(lái)選擇元素,。

在我們這個(gè)示例中,,當(dāng).chat區(qū)域內(nèi)的任何內(nèi)容得到焦點(diǎn)時(shí),重置一下.messagemax-heightpadding值,。請(qǐng)記住,,一個(gè)元素必須接受鍵盤(pán)或鼠標(biāo)事件或其他形式的輸入,以便接收焦點(diǎn),。比如我們這個(gè)示例,,點(diǎn)擊<input>輸入框就符合這個(gè)要求,可以達(dá)到我們想要的預(yù)期效果,。

.chat:focus-within .messages {
    max-height: 300px;
    padding: 10px;
}

<iframe id="xJLoXO" src="https:///airen/embed/xJLoXO?height=400&theme-id=0&slug-hash=xJLoXO&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

你現(xiàn)在可以嘗試一下效果,。點(diǎn)擊input讓其得到焦點(diǎn),可以看到聊天框可以展開(kāi),,反之聊天框又會(huì)折疊起來(lái):

image

image

Step12:進(jìn)一步突顯:focus-within的魔力

如果僅僅實(shí)現(xiàn)聊天框的折疊和展開(kāi)效果,,到上一步其實(shí)已經(jīng)完成了。但對(duì)于一位有追求的前端,,總是在嘗試很多極限性,。回到我們的示例中來(lái),,如果PM跟你提了一個(gè)新需求,,當(dāng)文本輸入框得到焦點(diǎn)之后,除了能展開(kāi)聊天框之外,,還希望聊天框底下的Newsfeed變得模糊,。對(duì)于這樣的一個(gè)效果,,怎么來(lái)實(shí)現(xiàn)呢,?

要實(shí)現(xiàn)這樣的效果,,其實(shí)并不復(fù)雜,如果你有做過(guò)自定義單選按鈕或復(fù)選框(當(dāng)然是純CSS),,你應(yīng)該會(huì)想到解決方案,。我們可以使用CSS選擇器中的兄弟組合器~,就可以很容易的做到這一點(diǎn),。使用~選擇器有一個(gè)前提需要注意,,聊天框.chat需要在Newsfeed(.container)前面(指的是HTML結(jié)構(gòu),事實(shí)上我們已經(jīng)這樣做了),。只有這樣才能通過(guò)下面的方式讓Newsfeed變得模糊:

.chat:focus-within ~ .container {
    filter: blur(5px)
}

<iframe id="RBLojW" src="https:///airen/embed/RBLojW?height=400&theme-id=0&slug-hash=RBLojW&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

當(dāng)然,,這可能不是最佳的一個(gè)方案,但僅通過(guò)CSS的技術(shù)手段就能達(dá)到預(yù)期的效果,,已經(jīng)很酷了,。感興趣的話(huà),自己可以體驗(yàn)一下:

image

image

注意,,Newfeed添加了filter效果,,這將會(huì)改變?cè)氐膶盈B順序,造成聊天框在Newsfeed下面,。所以需要顯式的.chat中添加z-index的值,。比如這里設(shè)置了z-index: 1001。具體原因可以查閱@張?chǎng)涡窭蠋煹摹?a href="https://www./wordpress/?p=5115" target="_blank" style="box-sizing: border-box; color: rgb(49, 148, 208); background-color: transparent; outline: none; transition: color 0.3s; touch-action: manipulation;">深入理解CSS中的層疊上下文和層疊順序》一文,。

探索:placeholder-shown

image

image

首先要先分清楚,,:placeholder-shown::placeholder是不同的兩個(gè)東東。神奇的是:placholder-shown是W3C標(biāo)準(zhǔn)規(guī)范的一個(gè)屬性,,而::placeholder卻不是,。::placeholder-shown仍然會(huì)影響占位符文本的樣式。

注意::placeholder-shown是一個(gè)偽類(lèi)選擇器(它是一個(gè)處于特定狀態(tài)的元素),;::placeholder是一個(gè)偽元素(一個(gè)在DOM中并不存在的可見(jiàn)元素),。

另外,:placeholder-shown也是新的選擇器之一(CSS Selectors Module Level 4新增了很多種偽類(lèi)選擇器),,它可以匹配任何顯示占位符文本的輸入,。在我們的示例中,文本輸入框(input)并沒(méi)有任何占位符文本,,所以先在HTML中的input元素中,,添加placeholder,新增占位符文本,。

<input type="text" class="input" placeholder="Enter your message">

然后在input之后添加一個(gè)新的元素,,用來(lái)幫助用戶(hù)操作:

<div class="prompt">Press enter to send</div>

現(xiàn)在給這個(gè)幫助信息.prompt添加一些樣式,,默認(rèn)情況之它是被折疊起來(lái)了。

.prompt {
    line-height: 2em;
    max-height: 0;
    overflow: hidden;
    padding: 0 10px;
    text-align: right;
    transition: max-height 500ms; 
}

<iframe id="ZjXKjM" src="https:///airen/embed/ZjXKjM?height=400&theme-id=0&slug-hash=ZjXKjM&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

僅從外觀(guān)上看,,似乎好像沒(méi)多出什么,,就是在文本框中多了一個(gè)占位符文本:

image

image

雖然沒(méi)多大區(qū)別,但這為后續(xù)的效果已埋下了一個(gè)伏筆,。接著往下看,。

Step14:使用提示信息可見(jiàn)

此時(shí)提示信息處于折疊狀態(tài),并不可見(jiàn),,我想大家也想到了,,要怎么使用:placeholder-shown讓其可見(jiàn)?大多數(shù)瀏覽器會(huì)顯示占位符文本,,直到用戶(hù)在input中輸入真的值,。為了提高用戶(hù)使用表單的體驗(yàn),如果input得到對(duì)應(yīng)的焦點(diǎn)之后,,占位符文本并不隱藏,,還起著提示作用,是不是更有意思,,也對(duì)用戶(hù)有更好的幫助,,畢竟我們不希望用戶(hù)發(fā)送空的消息,所以我們可以將這種行為關(guān)聯(lián)起來(lái),,只有在用戶(hù)輸入值時(shí)才顯示提示信息(也就是.prompt展開(kāi)可見(jiàn)),。

:placeholder-shown表示的是占位文本符可見(jiàn)的狀態(tài),而提示信息可見(jiàn)的時(shí)候,,占位文本符不可見(jiàn),,也就是input有了一個(gè)真正的值。換句話(huà)來(lái)說(shuō),,我們需要有一個(gè):placeholder-shown的反轉(zhuǎn)(占位文本符不可見(jiàn)),,這個(gè)時(shí)候我們可以借助:not()選擇器來(lái)幫我們做這樣的反轉(zhuǎn)。

.input:not(:placeholder-shown) + .prompt {
    max-height: 2em; 
}

max-height設(shè)置為font-size:10px的兩倍,,這里使用了2em,,這個(gè)時(shí)候可以展開(kāi)提信信息塊。簡(jiǎn)單而有整潔,。如果這個(gè)看似平凡的偽類(lèi)選擇器能過(guò)通過(guò)最終的規(guī)范,,那么我們將會(huì)看到一些巧妙的運(yùn)用。來(lái)到這一步,,效果變成:

<iframe id="jpGwmQ" src="https:///airen/embed/jpGwmQ?height=400&theme-id=0&slug-hash=jpGwmQ&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

親自體驗(yàn)一下,,你在input隨便輸入一點(diǎn)內(nèi)容,哪怕是空格,,也能看到提示信息被展示出來(lái)了:

image

image

不管:focus-within還是:placeholder-shown,,它們都是CSS選擇器新增加的偽類(lèi)選擇器,,如果感興趣,建議你花些時(shí)間對(duì)這些方面進(jìn)行了一了解:

Step15:讓它充滿(mǎn)生機(jī)

到目前為止,,我們通過(guò)簡(jiǎn)單的HTML和一些CSS特性完成了一個(gè)帶有聊天功能的新聞提要的基本架構(gòu),,但是目前它是沒(méi)有生命的,只是一個(gè)純靜態(tài)的東西,。也就是說(shuō)用戶(hù)并不有用它做任何事情,。這個(gè)案例包含了一些有趣的CSS新特性,,但到現(xiàn)在為止不能修改DOM,。如果想讓這個(gè)案例更為生動(dòng),那么就需要借助一些JavaScript功能,,以便用戶(hù)能通過(guò)聊天框添加消息,。

首先,需要向<input>和類(lèi)名.messages的子元素ul添加一個(gè)ID,,以便JavaScript更好的獲取到對(duì)應(yīng)的元素,。同時(shí)給input元素添加一個(gè)required屬性,當(dāng)用戶(hù)未輸入任何信息的時(shí)候,,表單可以自動(dòng)較驗(yàn),。

<ul id="messages" ...
<input type="text" id="input" required ...

然后創(chuàng)建一個(gè)名為script.js文件,并且放置在</body>之前,。不過(guò)我們的案例是在Codepen上做相應(yīng)的演示,,所以無(wú)需考慮創(chuàng)建一個(gè)單的.js文件。

Step16:添加一些JavaScript

我們需要給<input>添加一個(gè)事件函數(shù),,當(dāng)監(jiān)聽(tīng)到鍵盤(pán)的Enter事件,,獲取到input的值(如果有效)并將其添加到消息列表的末尾,清除字段并滾動(dòng)到消息的底部,。

// 獲取相應(yīng)的元素
const input = document.getElementById('input');
const messages = document.getElementById('messages');

// 監(jiān)聽(tīng)input的鍵盤(pán)事件
input.addEventListener('keypress', (event) => {
    // 檢查是否按下Enter鍵
    if (event.keyCode === 13) {
        // 檢查字段是否有效
        if (input.validity.valid) {
            // 使用該值創(chuàng)建DOM元素
            const message = createMessage(input.value);
            // 將新創(chuàng)建的DOM元素添加到消息列表
            messages.appendChild(message);
            // 清除輸入框的值
            input.value = '';
            // 滾動(dòng)到消息列表的底部
            messages.parentNode.scrollTop = messages.parentNode.scrollHeight;
        }
    }
});

// 將input的值轉(zhuǎn)換為HTML的字符串
function createMessage (value) {
    return stringToDom(`<li><div class="message">${value}</div></li>`)
}

// 將字符串轉(zhuǎn)換為真實(shí)的DOM
function stringToDom (string) {
    const template = document.createElement('template');
    template.innerHTML = string.trim();
    return template.content.firstChild;
}

<iframe id="VBMBWP" src="https:///airen/embed/VBMBWP?height=400&theme-id=0&slug-hash=VBMBWP&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

現(xiàn)在,,當(dāng)你在input中輸入字段并按Enter鍵時(shí),你將看到你輸入的消息添加到消息列表的底部,。

image

image

Step17:添加一引起額外的信息

為了向大家演示最后一個(gè)CSS新特性 —— contain,,咱們需要做一些設(shè)計(jì)。我們將實(shí)現(xiàn)一個(gè)效果,,在消息列表頂部的框中發(fā)送新消息的時(shí)間,。當(dāng)你將鼠標(biāo)懸停在消息上時(shí),就會(huì)有這個(gè)效果,。

首先,,我們需要將這些信息添加到我們的新消息中。我們可以修改createMessage函數(shù)返回的值,。

function createMessage (value) {
    return stringToDom(`
        <li>
            <div class="message message--mine" data-timestamp="${new Date().toString()}"> ${value} </div>
        </li>
    `);
}

你已經(jīng)注意到了,,在message中新增加了一個(gè)類(lèi)message--mine,。并給這個(gè)類(lèi)添加相應(yīng)的樣式:

.message--mine {
    background: #ff2089;
    margin-left: 20%;
    margin-right: 0;
}

<iframe id="OwxogG" src="https:///airen/embed/OwxogG?height=400&theme-id=0&slug-hash=OwxogG&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

當(dāng)你新輸入內(nèi)容,按下Enter鍵時(shí),,新增加的消息列表對(duì)應(yīng)的結(jié)構(gòu)就變成像下圖這樣的:

image

image

顯示時(shí)間戳

我們的目的是將創(chuàng)建消息的時(shí)間戳顯示在消息列表的頂部,,我們需要這樣做,以便即使在滾動(dòng)消息列表時(shí),,這個(gè)時(shí)間戳也總是可見(jiàn)的,。這里我們借助CSS的偽元素來(lái)做:

.message--mine::after {
    content: attr(data-timestamp);
}

這個(gè)時(shí)候你所看到的效果是這樣的:

image

image

這個(gè)效果并不是我們想要的。我們?cè)跇邮缴仙宰鲂薷?,鼠?biāo)懸浮到新添加的消息列表上時(shí)才能看到時(shí)間戳,,而且這個(gè)時(shí)間戳固定在消息區(qū)域的頂部。

.message--mine:hover::after {
    background: #000;
    color: #ff2089;
    content: attr(data-timestamp);
    left: 0;
    padding: 5px;
    position: fixed;
    top: 0;
    width: 100%;
}

這個(gè)效果現(xiàn)在變成這樣了:

image

image

現(xiàn)在時(shí)間戳固定在頁(yè)面的頂部,,可以繼續(xù)優(yōu)化一下,,在.messages中添加position: relative

但也不起作用,,那是因?yàn)楣潭ǘㄎ皇窍鄬?duì)于viewport的,,而不是相對(duì)于其祖先元素。那么這個(gè)時(shí)候,,最后一個(gè)CSS新特性應(yīng)該要出場(chǎng)了,。

<iframe id="pZWOKb" src="https:///airen/embed/pZWOKb?height=400&theme-id=0&slug-hash=pZWOKb&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

Step19:探索Containment

CSS Containment是一個(gè)令人興奮的新命題。它有許多選項(xiàng),,可以限制瀏覽器的樣式,、布局和對(duì)特定元素的繪制。這在修改DOM時(shí)特別有用,。在瀏覽器中,,哪怕是很小的變化都有可能造成瀏覽器重繪整個(gè)頁(yè)面,這樣的消費(fèi)是很貴,,即使瀏覽器努力為我們做了很多優(yōu)化,,頁(yè)面的重繪還是對(duì)性能有一定影響的。

使用CSS Containment,,我們可以把頁(yè)面的部分圈起來(lái),,然后說(shuō)“這里發(fā)生了什么,只在這里做相應(yīng)的事”,。這也是另一種方法,,可以保護(hù)元素不受外部的變化而受影響。

image

image

CSS的Containment是一個(gè)新屬性,,使用關(guān)鍵字contain,,它支持四個(gè)屬性值:

  • layout:這個(gè)值打開(kāi)該元素的布局控制。這確保所包含元素對(duì)布局目的完全不透明;外部不能影響其內(nèi)部布局,,反之亦然

  • paint:這個(gè)值打開(kāi)該元素的繪制控制,。這確保包含元素的后代節(jié)點(diǎn)不顯示在其邊界外,因此,,如果一個(gè)元素在屏幕外或是不可見(jiàn)的,,它的后代節(jié)點(diǎn)同樣也被保證是不可見(jiàn)的

  • size:這個(gè)值打開(kāi)該元素的尺寸控制。這確保包含元素可以無(wú)需檢查其后代節(jié)點(diǎn)進(jìn)行布局,。

  • style:這個(gè)值打開(kāi)該元素的樣式控制,。這確保了,對(duì)于性能這會(huì)不僅僅作用于一個(gè)元素及其后代,,這些效果也不忽視包含的元素

您還可以結(jié)合關(guān)鍵字,,如contain: layout paint,這將僅適用于一個(gè)元素的這些行為,。但也包含支持兩個(gè)額外的值:

  • contain: strict 意同 contain: layout style paint size

  • contain: content 意同 contain: layout style paint

每個(gè)值都有點(diǎn)不透明,,所以我建議你閱讀規(guī)范并在開(kāi)發(fā)者工具中使用它們來(lái)查看實(shí)際發(fā)生的情況,。

layoutpaint是兩個(gè)重要的值,,因?yàn)樗鼈冊(cè)谛枰罅坎僮鱀OM時(shí),對(duì)性能有一定的優(yōu)化,。然而,,在我們的演示中,我們可以利用contain: paint我助我們進(jìn)行時(shí)間戳定位,。

根據(jù)規(guī)范所描述,,當(dāng)使用paint時(shí),“元素作為一個(gè)包含絕對(duì)定位和固定定位后代的塊”,。這意味著,,我們可以在.chat上設(shè)置contain: paint,這樣一來(lái),,.chat中元素的固定定位將基于card而不是viewport,。你可以通過(guò)使用transform: translateZ(0)獲得相同的效果。

<iframe id="KBXGXX" src="https:///airen/embed/KBXGXX?height=400&theme-id=0&slug-hash=KBXGXX&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 4860px; overflow: hidden;"></iframe>

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

image

image

CSS Containment是較新的特性,,目前只在Chrome 52+版本可以看到。

前端學(xué)習(xí)圈

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多