社群精選 | 不容錯過的9個冷門css屬性

語言: CN / TW / HK

今天小編為大家帶來的是社群作者  lulu_up  的文章,讓我們一起來學習 9個冷門css屬性。

背景

可能我們有時候潛意識裡認為, 當前實際開發中css屬性已經足夠用了, 但是前段時間突然想到:"會不會我們只是思維被限制在了常用的css屬性中, 從而喪失了創造力", 就像發明 車 之前大多數人會認為 騎馬 已經足夠快可以滿足自己的需求了, 所以我專門整理了一下自己的學習筆記並且專門去學習了一些冷門的css屬性, 果然收穫滿滿, 所以今天也要在這裡把這些腦洞大開的屬性較少給你, 準備好一起來感受css的魅力吧。

一、開胃菜 css畫背景圖: paint

我們開發中使用的背景圖大部分是(png, webp等)圖片、svg向量圖、canvas畫圖, 但是其實我們也可以選擇css直接畫圖, 那css這種甚至都"稱不上"程式語言的傢伙怎麼繪製複雜的圖片那?

1: 為元素賦予css屬性

div class="box"></div>
<style>
  .box {
    width: 180px;
    height: 180px;
    border: 1px solid; 
    background: paint(xxxx); // 主角在此
  }

paint(xxxx); 這裡填入的是繪圖的"方法名", 往下看就知道啥是"方法名"了, 之所以我這裡寫"xxxx"非常隨意, 是因為我想表達這個名字隨便起。

2: 引入js檔案

    <script>
      if (window.CSS) {
        // 因為載入檔案 需要啟動server
        CSS.paintWorklet.addModule("./paint-grid.js");
      }
    </script>

用法有點詭異, 但核心其實是引入了一個js檔案。

3: js檔案內定義匯出的方法

paint-grid.js檔案:

registerPaint(
  "xxxx", // 這就是: 方法名
  class {
    paint(context, size) {
      context.fillStyle = 'red';
      context.fillRect(10, 10, 39, 39);
    }
  }
);

paint方法裡面就類似canvas了, 可以正常使用部分js程式碼。

當前的效果展示:

4: 可多匯出

當看到需要指定繪製的"方法名"而不是"檔名", 我就知道他一定可以匯出多個嘍:

registerPaint(
  "xxxx1",
  class {
    paint(context, size) {
      context.fillStyle = 'red';
      context.fillRect(10, 10, 39, 39);
    }
  }
);

registerPaint(
  "xxxx2",
  class {
    paint(context, size) {
      context.fillStyle = 'green';
      context.fillRect(10, 10, 39, 39);
    }
  }
);

兩個元素的樣式設定

   <style>
      .box {
        background: paint(xxxx1);
      }
      .box2 {
        margin-top: 20px;
        background: paint(xxxx2);
      }

5: 變數賦予背景靈動

我們時長遇到需要繪製"非固定大小背影", 此時在paint-grid.js中window是獲取不到的, 但是我們可以使用css變數:

// 在全域性定義方便js修改
  :root {
    --bg-size: 60;
  }

paint-grid.js檔案

registerPaint(
  "xxxx1",
  class {
    static get inputProperties() {
      return ["--bg-size"];
    }
    paint(context, size, properties) {
      var bgSize = properties.get('--bg-size');
      context.fillStyle = "red";
      context.fillRect(10, 10, bgSize, bgSize);
    }
  }
);

inputProperties定義了需要獲取哪些屬性, paint的第三個引數可以接收這些屬性, 這樣瞬間就感覺這個屬性還有點用啦。

6: 注意事項

  1. 不能在js檔案的繪製方法裡面寫alert, 會導致報錯阻斷繪製:

  2. 要注意維護 paint-grid.js檔案與css檔案的相關性, 因為大家寫程式碼會下意識的不會認為js方法被css檔案裡的屬性所使用, 這就導致可能後續無刪除或者是不敢刪除等問題。

  3. 適合處理簡單的圖形, 如果複雜度高了或者還需藉助其他"庫"的情況, 則不建議使用。

二、字型三連 (鏤空、漸變、背景)

1: 鏤空字不算罕見

 p {
    font-size: 150px;
    color: white;
    -webkit-text-stroke: 6px red;
  }

2: 漸變色文字

p {
        font-size: 150px;
        color: white;
        -webkit-text-stroke: 6px red;
        background-color: rosybrown;
        background-image: -webkit-linear-gradient(top, red, #fd8403, yellow);
        -webkit-background-clip: text;
        color: transparent;
      }
 <p>
  高
  <br>
  低
 </p>

3: 文字背景

我們把"白金之星"(jojo的奇妙冒險中的'人物')的圖片作為文字的背景:

 div {
        font-size: 150px;
        background: url(../imgs/jojo.webp) no-repeat;
        background-size: 100%;
        background-origin: border-box;
        -webkit-background-clip: text;
        color: transparent;
      }

這裡的關鍵點是-webkit-background-clip: text, 意思是將dom內文字以外的區域裁剪掉, 所以就剩文字區域了, 然後文字再設定成透明的。

三、他來了他來了, 他帶著炫酷的過場動畫走來了

先看一下咱們用css字型屬性做的動動畫效果:

倒計時骨王登場:

這裡的思路就是利用文字的背景圖屬性, 但是難點是如何讓文字變大。

1: 難點與坑點

文字變大有什麼難的? 你可能會說這些so簡單, 我們設定文字所在的span標籤position: absolute;定位在父級中間不就OK了? 但是如果這樣設定就會導致-webkit-background-clip: text;失效, 也就是文字脫離了文件流。

有同學有會想到 transform:scale(1.5); 來動態控制文字的變大, 但是transform依然會使-webkit-background-clip: text;失效。

所以我想到的是在div中設定flex讓文字上下左右居中, 然後調大font-size屬性。

還有一個問題就是背景色問題, 因為設定了背景圖的同時沒法設定文字外層的背景色。

2: 實現思路

首先總共需要三層結構, 第一層wrap負責黑色背景色以及overflow: hidden;來截斷我們的文字變大, 第二層box負責文字的居中, 並且設定font-size屬性讓內部元素繼承, 第三層span標籤負責文字①②③的存放, 因為要控制這些文字的顯隱所以需要dom標籤包裹。

3: 實現程式碼

程式碼有些粗鄙沒有潤色:blush:

<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      #wrap {
        background-color: black;
        width: 500px;
        height: 500px;
        margin: 0 auto;
        overflow: hidden;
      }
      .box0 {
        background: url(../imgs/jojo.webp) no-repeat;
      }
      .box1 {
        background: url(../imgs/一起幹飯.jpeg) no-repeat;
      }
      .box2 {
        background: url(../imgs/gat.webp) no-repeat;
      }
      #box {
        width: 500px;
        height: 500px;
        font-size: 150px;
        margin: 0 auto;
        background-size: 500px 500px;
        background-position: center;
        -webkit-background-clip: text;
        -webkit-text-fill-color: rgba(0, 0, 0, 0.2);
        display: flex;
        justify-content: center;
        align-items: center;
      }
      .text {
        display: none;
      }
    </style>
  </head>
  <body>
    <div id="wrap">
      <div id="box">
        <span class="text">①</span>
        <span class="text">②</span>
        <span class="text">③</span>
      </div>
    </div>
    <script>
      const oBox = document.getElementById("box");
      const textArr = document.getElementsByClassName('text')

      let i = 0;
      let n = 800;
      setInterval(()=>{
        oBox.style.fontSize = n + 'px';
         n+=3
         if(n > 800){
            n = 10;
            textArr[1].style.display = 'none'
            textArr[2].style.display = 'none'
            textArr[0].style.display = 'none'
            textArr[i].style.display = 'block'
            oBox.classList.remove('box1')
            oBox.classList.remove('box2')
            oBox.classList.remove('box3')
            oBox.classList.add(`box${i}`)
            i++
            if(i > 2){
              i = 0
            }
         }
      },5)
    </script>
  </body>
</html>

把文案改成 "◤ ◢ ✿" 就會出現第一個動圖的效果啦!

四、引號: quotes

所謂引號就相當於給書名加上'書名號', 給語言加上'冒號雙引號', 當然他還有一些神奇玩法。

1: 基本使用

 <div class="box">jojo的奇妙冒險</div>
<style>
      .box {
        quotes: "《" "》";
      }
      .box::before {
        content: open-quote;
      }
      .box:after {
        content: close-quote;
      }
    </style>

效果圖:

這裡要注意的是如果沒寫content: open-quote;會導致前後'書名號'都消失, 但是唯獨沒寫content: close-quote;則會保留展示"《"。

2: 看似雞肋?

當前這個基礎寫法也太雞肋了, 不就是給"《"起了個別名叫open-quote嗎? 並且關鍵是佔用了我的before與after, 感覺畫蛇添足, 比如我可以用如下的方法進行替換:

:root {
    --open: "《";
    --close: "》";
  }
  div::before {
    content: var(--open);
  }
  div::after {
    content: var(--close);
  }
<div class="box">jojo的奇妙冒險</div>

3: 套娃高手 quotes 雄起

其實quotes的看家本領是它可以接受n個引數!

 .box {
    quotes: "--- start" "---- end" "《" "》";
  }
  .box::before {
    content: open-quote;
  }
  .box:after {
    content: close-quote;
  }
<div class="box">
        <div class="box">jojo的奇妙冒險</div>
        <div class="box">Overlord</div>
        <div class="box">艾爾登法環</div>
    </div>

神奇的事情出現了, 當出現巢狀結構的時候, 內部的元素會使用第三個與第四個引數作為"引號", 套娃事件出現啦:

.box {
    quotes: "--- start" "---- end" "(" ")" "《" "》";
  }
  .box::before {
    content: open-quote;
  }
  .box:after {
    content: close-quote;
  }
<div class="box">
  <div class="box">
    <span class="box">jojo的奇妙冒險</span>
  </div>
  <div class="box">
    <span class="box">Overlord</span>
  </div>
  <div class="box">
    <span class="box">艾爾登法環</span>
  </div>
</div>

說實話這個套娃能力還挺厲害的, 並且我們可以講 close-quote屬性置空, 我想到的就是列表:

.box {
    quotes: "--- start" "---- end" "1: " "" "-- 2:" "" "---- 3: " "" "------ 4: " "";
  }
  .box::before {
    content: open-quote;
  }
  .box:after {
    content: close-quote;
  }
 <div class="box">
      <div class="box">
        第一:
        <div class="box">
          第二:
          <div class="box">第三:</div>
        </div>
        <div class="box">
          第二:
          <div class="box">
            第三:
            <div class="box">第四:</div>
          </div>
        </div>
      </div>
      <div class="box">
        第一:
        <div class="box">第二:</div>
      </div>
    </div>

要注意不寫close-quote會讓css找不到在哪裡結束, 所以最好寫上並給空值。

五、還原大師: all


CSS all 簡寫屬性 將除了 unicode-bidi 與 direction 之外的所有屬性重設至其初始值,或繼承值。

這是一個比較強硬的屬性, 可以把幾乎所有css屬性進行重置:

我們先設定一下基礎的環境

 .wrap {
    font-size: 30px;
    font-weight: 900;
  }
  .box {
    width: 100px;
    height: 100px;
    border: 1px solid;
    background-color: red;
    color: white;
  }
  .box1 {
    all: initial;
  }
  .box2 {
    all: inherit;
  }
  .box3 {
    all: revert;
  }
  <body>
    <div class="wrap">
      <div class="box">你好</div>
      <div class="box box1">你好: initial</div>
      <div class="box box2">你好: inherit</div>
      <div class="box box3">你好: revert</div>
    </div>
  </body>

1: initial : 還原為初始值

顧名思義這裡是將 div身上的所有屬性都重置了, 不管是"背景顏色"還是"字型顏色", 甚至寬高, 所以這裡屬於是完全初始化了。

但是有個大坑, 他會把div原本的display: block改變成display: inline, 也就是說all: initial;將所有屬性置為空了, 而不會根據標籤屬性進行篩選, 所以這個屬性有點太絕對了要小心使用。

2: inherit: 整合值保留

依然是顧名思義, 將所有屬性設定為 "繼承父級", 並且還原自身的屬性, 比如寬高都沒有了但是繼承了字型大小與字型粗細。

不是所有css屬性的預設值都是'繼承', 比如說position的預設值就不是整合, 但是position可以設定為position: inherit;, 這就埋下了隱患請看下一條屬性。

3: revert: 還原

雖然看起來效果與inherit幾乎一樣, 但是實質上有大區別, 比如如果此時wrap父元素設定position: absolute;, 那麼設定了all: inherit的元素為position: absolute;, 設定了all:revert的元素是position: static, 也就是說目標元素單純的還原成最開始的樣式, 剔除掉了後期設定的屬性, 但保留一些預設的繼承屬性, 這個屬性雖然相容性超差但最牛!

4: all的優先順序

.box{
    all: revert;
    background-color: red;
}

這裡的背景色是可以設定成功的, 所以all應該算一錘子買賣, 只把設定all屬性之前的樣式重置。

// 父級
  .box {
    background-color: red !important;
  }
 .box1 {
   all: revert;
 }

上面是不生效的, 因為all只能重置優先順序不如自己選擇器的屬性, 所以需要all: revert!important;。

六、目標元素樣式 :target

這個屬性讓頁面的url引數與dom元素互動起來

1: 跳轉選中

比如當前url是https://www.xxxxxxxxxxx.com/#target_id則:

  :target {
    background-color: red;
    font-size: 200px;
  }
<div id="target_id">
    你好
</div>

2: 跳轉後動畫

我想到的是每次選中元素後讓元素有個動畫效果, 實在太簡單了就不演示了, 說一下這個屬性的雞肋點吧, 比如無法同時傳遞多個id, 或者傳遞class, 並且他讓css屬性與dom結構之間繫結關係變弱了程式碼不方便維護與閱讀。

七、輸入框的placeholder樣式設定: placeholder-shown

可以設定當input元件中展示placeholder時的樣式:

      input:placeholder-shown {
        background-color: lightblue;
      }

      input {
        width: 300px;
        height: 60px;
      }
 <input placeholder="展示我時為藍色" />

輸入內容則還原

八、換行展示的藝術: hyphens

當英文單詞必須折行時我們是否需要一個'連字元':

<div class="box">
      The auto setting's behavior depends on the language being properly tagged
      so that the appropriate hyphenation rules can be selected.
    </div>
  .box {
    border: 1px solid black;
    width: 200px;
    height: 100px;
  }

主角暴風登場

      .box {
        border: 1px solid black;
        width: 200px;
        height: 100px;
        hyphens: auto;
      }

比較可惜的是無法自由定義'連字元'的樣式, 否則一定有點有趣。

九、滾動的優質體驗: scroll-snap-type

定義一個滾動時的"臨時停頓點", 這個問題直接看gif動畫比較直接:

簡單來看就是每次慣性滑動都會停留在特定元素所在位置, 有點像滾動的'錨點':

<!DOCTYPE html>
<html>
  <head>
    <style>
      .box {
        width: 200px;
        height: 150px;
        border: 1px solid;
        border-left: 5px solid black;
        border-right: 5px solid black;
        margin: 40px;
        overflow: auto;
        scroll-snap-type: y mandatory;
      }
      .item {
        border-top: 1px solid red;
        height: 150px;
        /* scroll-margin-top:20px; */
        scroll-snap-align: start none;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="item">11111</div>
      <div class="item">22222</div>
      <div class="item">33333</div>
      <div class="item">44444</div>
      <div class="item">55555</div>
      <div class="item">66666</div>
    </div>
  </body>
</html>

scroll-snap-type: y mandatory;設定了y軸滾動時儘量停留在'元素點位'上, scroll-snap-align: start none;目標元素自身的滾動起始方向用來對齊, 也就是告訴瀏覽器滾動後要停留在子元素的哪裡。

在子元素身上設定scroll-margin-top: 20px 可以設定一定的檢測距離, 並附加回彈效果:

end

這次神奇的css之旅就是這樣, 希望與你一起進步。

點選左下角閱讀原文,到  SegmentFault 思否社群  和文章作者展開更多互動和交流, 公眾號後臺 回覆“  入群  ”即可加入我們的 技術交流群 ,收穫更多的技術文章~

- END -