CSS世界中那些說起來很冷的知識

chenhongdong發表於2018-07-09

讀書使我快樂-哈哈

最近讀了張鑫旭的新書《CSS世界》收穫了不少奇技淫巧和對CSS的深度理解

也正值個人在公司內部進行部分章節的內容分享,於是順帶著直接把我即將分享的內容先給大家過過目了,就當省去了大家買了書後,無暇顧及觀看的尷尬吧!

本書的最後三章分別是

  • 元素的顯示與隱藏
  • 使用者介面樣式
  • 流向的改變

下面我就直接進入主題,開始對每一章節進行一個非系統的分享了

元素的顯示與隱藏

使用CSS讓元素不可見的方法很多,剪裁、定位到螢幕外、透明度變化等都是可以的。雖然它們都是肉眼看不見,但背後卻在多個維度上都有差別

下面是總結的一些比較好的隱藏實踐,大家一起來根據實際開發場景來選擇合適的使用

比較好的隱藏實踐

  • 不佔空間,不渲染 使用script
    <script type="text/html">
        <!-- 圖片是不會傳送請求的 -->
        <img src="1.jpg" />
        <!-- 如果想巢狀需要藉助textarea了 -->
        <textarea style="display: none;">
            <img src="2.png" />
        </textarea>
    </script>
    複製程式碼
  • 不佔空間,資源可以載入,DOM可訪問 使用display:none
    <div id="box">成都</div>
        <script>
            let oBox = document.getElementById('box');
            console.log(oBox);  // <div id="box">成都</div>
        </script>
    複製程式碼
  • 不佔空間,隱藏顯示時有transition效果
    .hidden {
        position: absolute;
        visibility: hidden;
    }
    
    <div class="div hidden">一杯敬朝陽 一杯敬月光</div>
    複製程式碼
  • 佔空間,不能點選 visibility: hidden
    .vh {
        visibility: hidden;
    }
    複製程式碼
  • 不佔空間,不能點選,鍵盤能訪問 clip裁切
    .out {
        position: relative;
        left: -999em;
    }
    .clip {
        position: absolute;
        clip: rect(0, 0, 0, 0);
    }
    
    <div class="clip">
        <div class="out">青花瓷</div>
    </div>
    複製程式碼
  • 佔空間,不能點選,鍵盤能訪問 relative
    <div style="position: relative;top: -999em;">獅子座</div>
    複製程式碼
  • 佔空間,可以點選 opacity
    <div style="opacity: 0; filter: alpha(opacity=0);">透明度</div>
    複製程式碼
  • 隱藏文字 使用text-indent
    <p style="text-indent: -999999px;">天下無雙</p>
    複製程式碼

根據實際的隱藏場景選擇合適的隱藏方法,這裡就不再多說了,接著往下看吧

display與元素的顯隱

我們都知道display如果值為none,則該元素以及所有後代元素都隱藏,反之如果值是非none的情況,則都為顯示了

display可以說是web顯隱互動中出場頻率最高的一種隱藏方式,是真正意義上的隱藏,乾淨利落,不留痕跡

none做到了無法點選、無法使用螢幕閱讀器等輔助裝置訪問,不佔空間,其實不僅僅是這樣,更應該知道的是

me: 我有酒,那麼別說你沒有故事

我知道display:none你才不是一個沒有故事的女同學

display: none的元素的background-image圖片根據不同瀏覽器的情況載入情況不一

  1. 在Firefox瀏覽器下,display:none的background-image圖片不載入,包括父元素display:none也是如此

  2. 在Chrome和Safari瀏覽器,則根據父元素是否是否為none來影響圖片載入情況,父元素帶有display:none,圖片不載入。

    父元素不帶有display:none,而自身有背景圖元素帶的話,那也照樣載入

    CSS世界中那些說起來很冷的知識

  3. 在IE瀏覽器下,無論怎麼搞都會請求圖片資源,就是這麼任性

因此,在實際開發的時候,例如頭圖輪播切換效果

那些預設需要隱藏的圖片作為背景圖藏在display:none元素的子元素上,這樣的細小改動就可以明顯提升頁面的載入體驗,也是非常實用的小技巧

whatever

上面說的興致盎然,但實際中不可能全部都是背景圖去載入圖片資源的

還有另外一個好朋友,img元素,然並卵的是,上面說了一大堆載入不載入的情況,對img來說沒個鳥用,人家不管你none不none的,依舊帶著勇闖天涯的氣概去請求著資源

活久見

都說display:none做事最純粹,最乾淨,不能被點選,觸碰到,然而下面這種情況又是什麼鬼?

出來解釋解釋,我們都是文明人是絕對不會動武的!

<form action="/index.php">
    <input type="submit" id="hi" style="display: none;">
    <label for="hi">提交</label>
</form>
複製程式碼

隱藏的按鈕會觸發click,觸發表單提交,此現象出現在時髦的瀏覽器中(IE9+,現代標準瀏覽器中)

既然有這種例外情況那加了display:none的意義又是什麼呢?

  • 意義在於:當按鈕和label元素不在一個水平線上的時候,點選label元素不會觸發錨點定位
  • But:作者不推薦這麼做,因為submit按鈕會丟失鍵盤可訪問性

很多都是純天然的

HTML中有很多標籤和屬性天然自帶display:none

  • 標籤:style, script, dialog
  • 屬性:
    <input type="hidden" name="id" value="1" />
    // 專門用來放置類似token或id這些隱藏資訊的
    // 所以說,表單元素的顯隱並不影響資料的提交
    // 其真正影響的是disabled屬性
    複製程式碼
  • HTML5中新增了hidden這個布林屬性,可以讓元素天生隱藏起來
    <div hidden>看不見我</div>
    // IE11及現代標準瀏覽器都支援,如果做相容需要這樣寫下即可
    [hidden] {
        display: none;
    }
    複製程式碼
  • 對於ol有序列表來說,如果子元素li有一項被設定了display:none,那麼原本有10相的元素,最後總計數會被計算成9項,設定display:none的那項被後面的兄弟給取代了
  • 還有一點就是display:none其實並不會影響css3 animation動畫的實現,而只是會影響transition過渡效果的執行,因此transition和visibility屬性關係更好 (老鐵扎心了)

既然說到了visibility了,那麼就趕緊邀請visibility閃亮登場吧

visibility與元素的顯隱

visibility要為自己正名,不僅僅是保留空間這麼簡單

看點多多:

  1. 繼承性(最有意思的一個特點,不是我說的)
    • 父元素設定visibility:hidden,子元素也繼承了該屬性,也是看不見的
    • 不過本質區別在於,父元素設定了hidden後,子元素設定visible後,子元素是可以被看都的
    • 這點父元素設定了display:none,子元素就永遠看不到了
    <ul style="visibility: hidden;">
        <li style="visibility: visible;">1</li>
        <li>2</li>
        <li>3</li>
        <li style="visibility: visible;">4</li>
    </ul>
    複製程式碼

CSS世界中那些說起來很冷的知識
2. 與css計數器

visibility:hidden雖然讓元素不可見了,但是不影響其計數效果,不會重新計算結果

CSS世界中那些說起來很冷的知識
3. 與transition

設定了visibility:hidden的元素,可以很好的展現transition過渡效果

這是因為transition支援的css屬性中有visibility(果然是兄弟),而並沒有display屬性

  1. 與JS

visibility:hidden除了對transition友好外,對js來說也很友好

在實際開發中,需要對隱藏元素進行尺寸和位置的獲取,來實現佈局精確定位的互動

此時,就建議使用visibility:hidden

.hidden {
    position: absolute;
    visibility: hidden;
}
let ele = document.getElementById('demo');

console.log('clientWidth: ' + ele.clientWidth);
console.log('clientHeight: ' + ele.clientHeight);
console.log('left: ' + ele.clientLeft);
console.log('top ' + ele.clientTop);
console.dir(ele.getBoundingClientRect());
複製程式碼

CSS世界中那些說起來很冷的知識

好了以上內容要告一段落了,我們繼續開始新的征程吧,哈哈

使用者介面樣式

使用者介面樣式指的是CSS世界中用來幫助使用者進行介面互動的一些CSS樣式,主要有outline和cursor等屬性

和border形似的outline屬性

outline表示元素的輪廓,語法也和border一樣,分為寬度、型別和顏色三個值

.outline {
    height: 60px;
    width: 60px;
    outline: 2px dashed #0c9;
}
複製程式碼

樣式表示上相同,但是設計的初衷卻是不太相同的,這一點天地日月可鑑

outline是一個和使用者體驗密切相關的屬性,與focus狀態以及鍵盤訪問密切相關

對於按鈕或連結,通常的鍵盤操作是:Tab鍵按次序不斷focus控制元件元素(連結、按鈕、輸入框等表單元素),或者focus設定了tabindex的普通元素,然後按Shift+Tab是反向訪問

重點來了

預設狀態下,對於處於focus狀態的元素,瀏覽器會通過發光or虛框的形式進行區分和提示,這是友好的使用者體驗,很有必要,不然使用者很難知道自己當前聚焦在了哪個元素上面,會迷失自我

元素如果聚焦到了a連結上,按下Enter鍵就會跳轉到相應連結,以上的互動都是基於鍵盤訪問的,這就是為什麼outline和鍵盤訪問如此親密了

不專業的行為

很多時候直接在reset樣式的時候,寫成如下形式是非常不可取的

* { outline: 0 none; }
或
a { outline: 0 none; }
複製程式碼

這樣直接一竿子打死一群鴨子的做法是不對的,更多的時候是因為瀏覽器內建的focus效果和設計風格格格不入,才需要重置,而且要使用專門的類名

例如:
.input {
    outline: 0;
}
// 但是,必須把focus狀態樣式加上
.input:focus {
    border-color: Highlight
}
複製程式碼

最後再強調一遍:萬萬不可在全域性設定outline: 0 none;

這樣的操作會造成鍵盤訪問的時候使用者找不到當前焦點,容易產生困擾的,為了大家好,收斂一下吧

下面來點乾貨: 在實際開發中,有時候需要讓普通元素代替表單控制元件元素有outline效果

舉個例子:submit按鈕來完成UI設計是非常麻煩的,所以使用label元素來移花接木,通過for屬性和這些原生的表單控制元件相關聯

[type="submit"] {
    position: absolute;
    clip: rect(0, 0, 0, 0);
}
.btn {
    display: inline-block;
    padding: 2px 12px;
    background-color: #19b955;
    color: #fff;
    font-size: 14px;
    cursor: pointer;
}
:focus + label.btn {
    outline: 1px dashed hotpink;
    outline: 3px auto -webkit-focus-ring-color;
}

<div class="panel">
    <input type="submit" id="box">
    <label for="box" class="btn">提交</label>
</div>
複製程式碼

CSS世界中那些說起來很冷的知識
CSS世界中那些說起來很冷的知識

真正的不佔據空間的outline及其應用

outline是一個真正意義上不佔任何空間的屬性,Amazing

頭像剪裁的矩形鏤空效果

先來看個效果圖

CSS世界中那些說起來很冷的知識
上圖就是矩形鏤空效果,那麼下面直接上程式碼,滿滿的乾貨

核心css是
.crop {
    overflow: hidden;
}
.crop .crop-area {
    width: 80px;
    height: 80px;
    outline: 256px solid #000;
    outline: 256px solid rgba(0, 0, 0, .5);
    background: url(about:blank);
    background: linear-gradient(to top, transparent, transparent);
    filter: alpha(opacity=50);
    cursor: move;
}
:root .crop-area {
    filter: none;
}
複製程式碼

用一個大大的outline來實現周圍半透明的黑色遮罩,因為outline無論設定多麼多麼大,都不會佔據空間影響佈局,至於超出的部分,直接給父元素設定一個overflow:hidden就搞定了 注意:

  • 因為考慮到IE8不支援rgba,所以上面藉助了filter設定了透明度為一半效果
  • 但是由於IE9支援rgba,再借助:root來進行重置,不使用filter
  • 再加上IE10針對鏤空元素會有點選穿透問題,所以再給background設定看不見的背景內容就可以解決

自動填滿螢幕剩餘空間的應用技巧

開發中很多時候,由於頁面內容不夠多,導致底部footer會出現尷尬的剩餘空間,解決方法往往也有很多種,在此我們還是依然利用outline的功能來完美實現一下

關鍵的css就是設定一個超大輪廓範圍的outline屬性,如給個9999px,保證無論螢幕多高,輪廓顏色都能覆蓋

值得注意的是,outline無法指定方位,它是直接向四周發散的,所以需要配合clip剪裁來進行處理,以左邊和上邊為邊界進行裁剪

.footer {
    height: 50px;
}
.footer > p {
    position: absolute;
    left: 0;
    right: 0;
    text-align: center;
    padding: 15px 0;
    background-color: #00a1f5;
    outline: 9999px solid #00a1f5;
    color: #fff;
    clip: rect(0, 9999px, 9999px, 0);
}

<div class="footer">
    <p>沒錯,我就是footer</p>
</div>
複製程式碼

CSS世界中那些說起來很冷的知識

游標屬性

游標屬性cursor我們真的是最熟悉的陌生人啊

為什麼這麼說呢,因為在眾多的屬性值面前,我們似乎只用到了pointer(手形)(最常用的,沒有之一),move(移動),default(系統預設)這幾樣

在cursor的世界裡,遠比我們想象的要豐富很多,下面按照功能特性來對其進行分類吧

琳琅滿目的cursor屬性值

友情不友情的小提示:☆(表示常用)

  • 常規
    • cursor: auto; 預設值
      • 輸入框表現是cursor: text (文字游標)
      • href屬性的連結表現為cursor: pointer (手形游標)
      • button表現為cursor: default (預設箭頭)
    • ☆ cursor: default; 系統預設游標
      • 誤區產生的小故事:
        • 由於瀏覽器原生按鈕樣式相容方面無法完善,尤其是IE盛行的年代,黑框、寬高不一致等問題層出不窮, 於是大家就使用a標籤來模擬按鈕,在每次hover上去的時候都會有一個手型效果,省去了額外新增, 所以久而久之就成了業內約定俗成的做法了
    • cursor: none; 這是讓游標隱藏不見
      • what? 有何用?它的作用在看視屏的時候,全屏後滑鼠靜止不動3秒鐘,就設定隱藏游標效果
      • IE8不支援,還要通過自定義游標來處理
      // 自定義游標
      .cur-none {
          cursor: url(transparent.cur), auto;
      }
      :root .cur-none {   // IE9+
          cursor: none
      }
      複製程式碼
  • 連結和狀態
    • ☆ cursor: pointer; 手形
    • cursor: help; 幫助游標
      • 用在幫助連結或者提示資訊的問號小圖示上
      • 不過目前很少在網頁上看到,更多的是使用cursor:pointer手形處理
    • cursor: progress; 進行中
      • 一個適用場景是網頁載入js的情況,網路不好時,載入js時間過長
      body {
          cursor: progress;
      },
      // 當js載入完成後再將游標cursor設為auto;
      // 增加了使用者體驗
      document.addEventListener('DOMContentLoaded', () => {
          document.body.style.cursor = 'auto';
      });
      複製程式碼
    • cursor: wait;
      • 沒用的游標,有個沙漏的樣子
    • cursor: context-menu;
      • 上下文選單,相容性很複雜,汽油桶形狀,用處不大
  • 選擇
    • ☆ cursor: text; 文字可被選中
      • input預設游標表現就是cursor:text
        • 但是如果設定了disabled後,游標會自動變成cursor:default
      • 還有如果在現代瀏覽器中不允許文字選中的情況下,設定了user-select:none後,還要把對應的游標改變為cursor:default
      p {
          -webkit-user-select: none;
          -moz-user-select: none;
          -ms-user-select: none;
          cursor: default;
      }
      <p>弱水三千</p>
      // 不過現在最新版的瀏覽器都自動設定了cursor:default
      複製程式碼
    • cursor: vertical-text;
      • 垂直選中,文字排版是垂直情況的時候,基本沒機會用到
    • cursor: crosshair;
      • 十字游標,它比較適合取色工具的場景中,平時用不到
    • cursor: cell;
      • 單元格游標,適合開發類似Excel表格的網頁使用
      • 而且IE8還不支援,需要自定義,也是沒機會表現了
  • 拖拽
    • ☆ ccursor: move;
      • 移動游標,表示當前元素是可移動的
      • 常用的彈窗元件給標題欄加上cursor:move,讓使用者知道是可以拖動的
    • cursor: copy;
      • 複製游標,表示當前元素可以複製,IE8不支援,需自定義,無實用
    • cursor: alias;
      • 別名游標,表示當前元素可以建立別名或快捷方式,同上copy一樣,沒個卵用
    • cursor: no-drop與cursor: not-allowed;
      • 樣式相同,都表示禁止的
      • 值得注意的是:
        • 不要給禁用按鈕加cursor: not-allowed
        • 因為它的狀態只與拖拽行為相關
        • 所以禁用按鈕游標還是用default更合適
  • 都是CSS3新增的游標型別
    • 縮放
      • cursor: zoom-in; 放大
      • cursor: zoom-out; 縮小
    • 抓取
      • cursor: grab; 五指張開的手
      • cursor: grabbing; 五指收起的手
      • Chrome下還需要加-webkit字首生效
      • 這裡QQ音樂PC端做了這樣的cursor處理,如下圖框選的位置
        CSS世界中那些說起來很冷的知識
  • 自定義游標
    • 遇到一些IE8不支援的游標型別,可以通過自定義的手段來實現相容
    • chrome等瀏覽器可以直接使用png圖片作為游標
    • IE不行,它還是要用專門的.cur格式
    • 而自定義游標最大的作用其實是根據業務需求對游標進行樣式上的自定義
    • 不過現在用的真是不多了

以上內容就介紹完了使用者介面樣式的全部內容了,還有最後一章的冷知識,大家不要方,繼續看下去,瞭解一下,瞭解一下,瞭解一下

流向的改變

說出來你可能不信,direction可以改變水平流向,儘管知道或者使用過的人少之又少,但並不妨礙它的發光發熱

而且屬性簡單好記,值少,相容極好ie6支援,可以來挖掘一下它的神奇功效

direction

僅僅兩個值:

  • direction: ltr; 預設值
    • ltr -> left-to-right(從左到右)
    • 東亞、歐美文字書寫都是屬於ltr模式的
  • direction: rtl;
    • rtl -> right-to-left(從右到左)
    • 阿拉伯語、希伯來語的書寫屬於rtl模式

當然看到這裡你可能會感覺,這些說起來都沒什麼鳥用,因為大招是不輕易放出的,而真正有用的地方在於改變網頁佈局的時候

direction屬性預設有一個特性

可以改變替換元素(img,input,textarea,select)或inline-block/inline-table元素的水平呈現順序

舉個例子:顛倒順序

<div class="box" dir="rtl">
    <p>我是第2名</p>
    <p>我是第一名</p>
</div>

<p dir="rtl">
    <img src="../1.jpg" alt="貓">
    <img src="../2.png" alt="狗">
</p>
複製程式碼

CSS世界中那些說起來很冷的知識
再舉個例子:

比如製作彈窗元件的時候,確認取消按鈕有的時候會根據使用者的使用行為會顯示在不同的位置

下面來看看這種特性的表現在實際開發中的作用

windows使用者看到的樣子:

CSS世界中那些說起來很冷的知識

mac使用者看到的樣子:

CSS世界中那些說起來很冷的知識
好了,direction的話題就告一段落,接下來介紹最後一個知識了,堅持住,快休息了

writing-mode

改變CSS世界縱橫規則的writing-mode,如此強大的功能,居然沒有被大家發掘和廣發應用起來,實屬遺憾了,話不多說,往下看

writing-mode作用及真正需要關注的屬性值

writing-mode可以改變排版,變成垂直流,如下圖所示

CSS世界中那些說起來很冷的知識
在使用語法上,也是需要記兩套的,一套是IE私有屬性,一套是CSS3規範屬性

CSS3語法:

writing-mode: horizontal-tb;    預設值
    文字流是水平方向的
writing-mode: vertical-rl; 
    文字是垂直方向的,閱讀順序從右向左(古詩的順序)
writing-mode: vertical-lr;
    文字垂直方向,閱讀順序從左到右(水平變成了垂直展示)
複製程式碼

IE語法:

IE的writing-mode多達11個,真正有用的記住兩個就好了

-ms-writing-mode: lr-tb;    初始值
    lr-tb對應的是CSS3語法中的horizontal-tb
-ms-writing-mode: tb-rl;
    tb-rl對應的是CSS3語法中的vertical-rl
-ms-writing-mode: tb-lr;
    tb-lr對應的是CSS3語法中的vertical-lr
複製程式碼

針對實戰版來整理一份writing-mode是這樣的

writing-mode: lr-tb | tb-rl | tb-lr (IE8+)
writing-mode: horizontal-tb | vertical-rl | vertical-lr;
複製程式碼

對於垂直排版來說,實際開發是很少會遇到的,不過還是要說說writing-mode帶來的改變

水平方向也能margin合併

我們都知道兩個相鄰的元素垂直的margin會合並,當元素變為垂直流的時候,水平的margin也會合並

.vertical-mode {
    writing-mode: tb-rl;
    -webkit-writing-mode: vertical-rl;
    writing-mode: vertical-rl;
}

<div class="div vertical-mode">
    <div class="list" style="margin-left: 20px;">one</div>
    <div class="list" style="margin-right: 50px;">two</div>
</div>
複製程式碼

普通塊元素可以使用margin: auto實現垂直居中

img {
    display: block;
    margin: auto 0;
}

<div class="box vertical-mode">
    <img src="../1.jpg" alt="">
</div>
<div class="box vertical-mode" style="text-align: -center;background: gray;">
    <div class="demo">青花瓷</div>
    <!-- <img src="../2.png" alt=""> -->
</div>
複製程式碼

上面分別是圖片元素和普通塊元素實現的垂直居中程式碼,眼見為實,看圖

CSS世界中那些說起來很冷的知識

text-align:center實現圖片垂直居中(同上實現的效果)

<div class="box vertical-mode" style="text-align: center;">
    <img src="../2.png" alt="">
</div>
複製程式碼

CSS世界中那些說起來很冷的知識

使用text-indent實現文字下沉效果

核心css

.btn:active {
    text-indent: 2px;
}
<a href="javascript:;" class="btn vertical-mode">領</a>
複製程式碼

這種文字下沉效果只能適合中文,因為在垂直流排版的時候中文是不會旋轉的

而且這種效果只適合一個字的情景

CSS世界中那些說起來很冷的知識

實現全相容的icon fonts圖示旋轉效果

老IE下讓小圖示旋轉很麻煩,writing-mode把文件變成垂直流的時候,英文、數字和字元號都天然的轉了90°

@font-face的相容性很好IE5.5就支援了,所以就算是IE6IE7也沒問題

<span class="icon-play vertical-mode">剪頭朝下</span>
複製程式碼

CSS世界中那些說起來很冷的知識
好了,這就是《CSS世界》裡最後三章的全部內容了,終於寫完了,哈哈,希望大家有收穫一些冷知識,另外看書還是要買正版的,地址我就不發了,大家還請支援張鑫旭老師的作品

簡單說兩句

做個個人的小總結吧:

css有很多奇妙的地方,在某些特性當初被設計出來的時候可能只是為了某些圖文排版而生

但是我們可以利用它們帶來的特性發揮自己的創造力,實現其他很多意想不到的效果,因此,上面所講述的所有知識點,儘管很多內容都有點奇技淫巧以悅婦孺的過程

但這也給我們開發的過程中,提供了一些很出奇的妙招,值得我們好好學習領悟

感謝個位的觀看了,再見了,哈哈

相關文章