<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          純 CSS 實現(xiàn)標(biāo)簽自動顯示超出數(shù)量

          共 5547字,需瀏覽 12分鐘

           ·

          2024-07-12 12:11

             

          大廠技術(shù)  高級前端  Node進階

          點擊上方 程序員成長指北,關(guān)注公眾號

          回復(fù)1,加入高級Node交流群

          前言

          看到這個就想起游戲標(biāo)簽的場景。介紹了如何使用純 CSS 實現(xiàn)在標(biāo)簽溢出容器時自動顯示超出數(shù)量的功能,通過 CSS 計數(shù)器和滾動驅(qū)動動畫技術(shù),實現(xiàn)了在標(biāo)簽數(shù)量超出容器寬度時,自動計算并顯示隱藏標(biāo)簽的數(shù)量。

          現(xiàn)代 CSS 強大的令人難以置信。

          這次我們來用 CSS 實現(xiàn)這樣一個功能:有多個寬度不同的標(biāo)簽水平排列,當(dāng)外層寬度不足時,會提示超出的數(shù)量,演示效果如下

          如果讓我用 JavaScript 來實現(xiàn)估計都有點折騰,畢竟寬度都是動態(tài)的,要監(jiān)聽各部分的尺寸變化,包括標(biāo)簽的位置和外層的寬度,總之不是一兩行代碼就能搞定的。

          現(xiàn)如今,純 CSS 也能完美的實現(xiàn)這樣的效果,而且比 JS 實現(xiàn)更加簡單,一起來看看吧

          一、CSS 實現(xiàn)思路

          很多時候,CSS 并沒有直接的實現(xiàn)方式,需要 “繞” 點彎路,將需求拆分成很多小點,然后逐一突破。

          回到本文這里,其實有幾個問題需要考慮:

          • CSS 如何動態(tài)累計數(shù)字?

          • CSS 如何知道哪些元素在容器之外?

          • CSS 如何區(qū)分是否溢出(顯示數(shù)量)

          那么第一點,CSS 有沒有什么方式可以統(tǒng)計數(shù)量呢?

          沒錯,相信很多小伙伴已經(jīng)猜到了,就是利用 CSS 計數(shù)器,示意如下

           counter-reset: num var(--num);
          counter-increment: num;
          ::after{
          content: "+"counter(num);
          }

          然后是第二點,CSS 有什么方式可以知道元素是出去了還是在視野之內(nèi)呢?

          如果是用 JS 來判斷的話,最穩(wěn)妥的方式應(yīng)該 Intersection Observer(交叉觀察者),相信很多同學(xué)都用過,這個在圖片懶加載非常有用。

          那么,CSS 中有什么類似的呢?沒錯,還是之前提到過的 CSS 滾動驅(qū)動動畫。

          不過這里用到的是視圖進度,也就是關(guān)注的是元素自身位置,元素進入到容器范圍之內(nèi)就會觸發(fā)動畫,非常類似 JS 中的 Intersection Observer

           tag{
          animation: appear;
          animation-timeline: view(inline);
          animation-range: contain;
          }
          @keyframes appear{
          to {
          background-color: #9747FF;
          }
          }

          好了,關(guān)鍵原理就這些了,我們需要做的就是想辦法將計數(shù)器和元素進出容器范圍關(guān)聯(lián)起來就行了,接著往下看

          二、CSS 計數(shù)器

          利用 CSS 計數(shù)器,我們可以很輕松的統(tǒng)計元素的數(shù)量。

          先簡單布局一下文章開頭的例子,HTML 如下所示

           <div class="con">
          <a class="tag">HTML</a>
          <a class="tag">CSS</a>
          <a class="tag">JavaScript</a>
          <a class="tag">Flutter</a>
          <a class="tag">Vue</a>
          <a class="tag">React</a>
          <a class="tag">Svelte</a>
          </div>
          <span class="num"></span><!--用來計數(shù)的標(biāo)簽-->

          然后美化一下

           .con{
          display: flex;
          gap: 5px;
          padding: 5px;
          overflow: hidden;
          }
          .tag{
          padding: .2em .5em;
          background-color: #c49ef5;
          color: #fff;
          border-radius: 4px;
          animation: appear;
          }
          .num::after{
          content: "+0";
          padding: .2em .5em;
          background-color: #FFE8A3;
          color: #191919;
          border-radius: 4px;
          }

          這樣就得到了水平排列的 tag 布局(超出隱藏),后面跟一個數(shù)字

          現(xiàn)在我們定義一個計數(shù)器,然后通過每個 tag 進行累計,有多個 tag 相當(dāng)于多少次累加,最后在::after 中顯示出來

           .con{
          counter-reset: num; /*計數(shù)器初始值,默認(rèn)為0*/
          }
          .tag{
          counter-increment: num; /*計數(shù)器增量值,默認(rèn)為1*/
          }
          .num::after{
          content: "+"counter(num);
          }

          默認(rèn)計數(shù)器的起始值是 0,每次累計是 1,所以這里最后得到了 7,這樣就能實時統(tǒng)計元素的數(shù)量了

          當(dāng)然,我們也可以自定義這些默認(rèn)值,比如

           .con{
          counter-reset: num 10;
          }
          .tag{
          counter-increment: num -1;
          }

          這種情況下,起始值是 10,增量值是 - 1,所以最后得到了 3,如下

          那么,該如何統(tǒng)計容器之外的標(biāo)簽數(shù)量呢?

          三、CSS 滾動驅(qū)動動畫

          這里我們要利用 CSS 視圖進度時間軸,也就是觀察元素自身的位置,在進入到容器范圍之內(nèi)執(zhí)行動畫。

          拿上面這個例子,我們給標(biāo)簽添加一個動畫,讓標(biāo)簽在進入到容器之內(nèi)時變個顏色,實現(xiàn)如下

           .tag{
          animation: appear;
          animation-timeline: view(inline);
          }
          @keyframes appear{
          to {
          background-color: #4d47ff;
          }
          }

          由于是水平方向,所以這里需要設(shè)置 view (inline) ,效果如下

          好像不是很明顯?這是因為動畫是在整個視區(qū)內(nèi)過渡的,我們可以改變動畫時間線的區(qū)間 animation-range,讓這個動畫在進出的一瞬間就變化

           .tag{
          animation: appear;
          animation-timeline: view(inline);
          animation-range: contain;
          }
          @keyframes appear{
          from,to {
          background-color: #4d47ff;
          }
          }

          效果如下

          那么,這個效果和前面的計數(shù)器有什么關(guān)聯(lián)呢?

          從效果上來看,在視區(qū)內(nèi)會執(zhí)行一個動畫,如果在這個動畫中加入計數(shù)器的累加會怎么樣呢?先去除原先的累加器

           .tag{
          /* counter-increment: num; */
          }
          @keyframes appear{
          from,to {
          background-color: #4d47ff;
          counter-increment: num;
          }
          }

          效果如下

          可以看到計數(shù)器已經(jīng)生效了,不過現(xiàn)在統(tǒng)計的在可視區(qū)內(nèi)標(biāo)簽的數(shù)量。而我們要統(tǒng)計的是可視區(qū)外的數(shù)量,好像反過來了,如何實現(xiàn)呢?

          這里有兩種思路。

          第一種,用總數(shù)減去可視區(qū)內(nèi)的數(shù)量,不就行了嗎?由于現(xiàn)在動畫是針對可視區(qū)內(nèi)的,我們可以給計數(shù)器設(shè)置一個初始值,就是總量,然后動畫中給累加值設(shè)置為 - 1,就相當(dāng)于減去當(dāng)前數(shù)量了,實現(xiàn)如下

           .con{
          counter-reset: num 7;
          }
          @keyframes appear{
          from,to {
          background-color: #4d47ff;
          counter-increment: num -1;
          }
          }

          這樣就完美統(tǒng)計出了可視區(qū)外的數(shù)量了

          還有一種方式,我覺得更加巧妙,需要反向思考。原理是重置當(dāng)前的累加值,比如默認(rèn)情況下,正常累加,進入可視范圍,把累加值設(shè)置為 0,不就相當(dāng)于可視區(qū)外的正常累加了嗎?

           .tag{
          counter-increment: num;
          }
          @keyframes appear{
          from,to {
          background-color: #4d47ff;
          counter-increment: num 0;
          }
          }

          同樣能達(dá)到相同的效果

          現(xiàn)在基本已經(jīng)達(dá)到我們需要的效果了

          四、其他細(xì)節(jié)修正

          首先是,在超出范圍時,需要在邊緣出添加一個半透明蒙層,這樣體驗效果會更好。

          半透明蒙層很好實現(xiàn),只需要添加一個水平漸變的 mask 遮罩就行了

           .con{
          -webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
          }

          效果如下

          那么,如何在沒有超出時,不出現(xiàn)這個遮罩呢?

          利用 CSS 滾動驅(qū)動動畫,可以檢測容器是否可滾動,也就是是否超出。所以我們只需要將遮罩放在滾動驅(qū)動動畫里就行了,關(guān)鍵實現(xiàn)如下

           .con{
          animation: check;
          animation-timeline: scroll(x self);
          }
          @keyframes check{
          from,to {
          -webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
          }
          }

          效果如下

          還有一個問題,希望在沒有超出的時候不顯示后面的數(shù)量。

          關(guān)于這個,我本來是打算用樣式查詢來實現(xiàn),但是遇到了一個問題,由于樣式查詢只能匹配到子元素,所以不得不將顯示數(shù)量的標(biāo)簽放到.con 容器內(nèi)。但是這樣一來,mask 遮罩就會出現(xiàn)問題,就像這樣

          遮罩層連同數(shù)量標(biāo)簽一起被裁剪了!

          于是又想出了另一種方案,這個在以前的布局中其實用到的更多,那就是負(fù) margin。

          實現(xiàn)很簡單,給標(biāo)簽容器一個的負(fù) margin-right,這樣,右邊的數(shù)量就會被左邊的標(biāo)簽蓋住,比如

           .con{
          margin-right: -20px;
          }

          效果如下

          是不是已經(jīng)被蓋住一部分了?我們繼續(xù)向左偏移

           .con{
          margin-right: -50px;
          }

          這樣就完全看不到右邊的數(shù)量了

          那么,如何在超出時顯示數(shù)量呢?這里就體現(xiàn)出負(fù) margin 的好處了,可以借助前一個元素來隱藏后一個元素,在這里,我們直接在前面的動畫中還原 margin 就行了

           .con{
          animation: check;
          animation-timeline: scroll(x self);
          }
          @keyframes check{
          from,to {
          -webkit-mask: linear-gradient(to right, #fff calc(100% - 30px), transparent);
          margin-right: 0;
          }
          }

          這樣就完美實現(xiàn)了文章開頭所示效果了

          訪問以下鏈接來體驗真實效果(Chrome115+):https://codepen.io/xboxyan/pen/rNbYpZV

          五、總結(jié)一下

          以上就是本文的全部內(nèi)容了,不知道你學(xué)會了嗎?下面總結(jié)一下實現(xiàn)重點:

          • 很多時候,CSS 并沒有直接的實現(xiàn)方式,需要 “繞” 點彎路

          • CSS 計數(shù)器可以實現(xiàn)數(shù)字累加

          • CSS 滾動驅(qū)動動畫可以檢測元素是否在可視范圍之內(nèi)

          • CSS 滾動驅(qū)動動畫還能檢測元素是否內(nèi)容超出

          • 計數(shù)累加器可以放在滾動驅(qū)動動畫中,這樣在動畫觸發(fā)時也就相當(dāng)于計數(shù)器生效了,這樣就能統(tǒng)計可視區(qū)的標(biāo)簽數(shù)量了

          • 樣式查詢只能匹配到子元素,但是用子元素會受到 mask 遮罩的影響

          • 負(fù) margin 可以借助前一個元素來隱藏后一個元素

          • Node 社群

          •      


            我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學(xué)習(xí)感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關(guān)的交流、學(xué)習(xí)、共建。下方加 考拉 好友回復(fù)「Node」即可。


          • 最后不要忘了點個贊再走噢

          瀏覽 213
          5點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          5點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  丰满少妇好紧好爽好湿无码 | 五月情丁香五月情婷婷 | 日韩一区二区三区视频在线观看 | 国产激情操逼 | 国产毛片一区二区三区亖区内套视频 |