1. 程式人生 > >【溫故知新】——CSS黑魔法小技巧可以少些不必要的js

【溫故知新】——CSS黑魔法小技巧可以少些不必要的js

人員 lan 溢出 簡單 chrome 元素屬性 tps ins none

前言:這篇文章是轉載【前端開發博客】的一篇技術文章,並非本人所寫。只是個人覺得很實用,所以分享給大家。原文鏈接:github.com

1、利用 CSScontent 屬性 attr 抓取資料需求

鼠標懸浮實現一個提示的文字,類似github的這種,如圖:

技術分享

想必大家都想到了偽元素 after,但是文字怎麽獲得呢,又不能用 JavaScript

CSS 的偽元素是個很強大的東西,我們可以利用他做很多運用,通常為了做一些效果,content:" " 多半會留空,但其實可以在裏面寫上 attr 抓資料哦!

<div data-msg="Open this file in Github Desktop">  
hover
</div>
div{
width:100px;
border:1px solid red;  
position:relative;
}
div:hover:after{
content:attr(data-msg);
position:absolute;
font-size: 12px;
width:200%;
line-height:30px;
text-align:center;
left:0;
top:25px;
border:1px solid green;
}

attr 裏面塞入我們在 html 新增的 data-msg 屬性,這樣偽元素 (:after) 就會得到該值。

最終效果

技術分享

同樣的,你還可以結合其他強大的選擇器使用,例如:使用屬性選擇器選擇空鏈接

顯示沒有文本值但是 href 屬性具有鏈接的 a 元素的鏈接:

a[href^="http"]:empty::before {
  content: attr(href);
}

這樣做很方便。

2、利用用 :valid:invalid 來做表單即時校驗

需求

讓表單檢驗變得簡單優雅,不需要寫冗長的 JS 代碼來校驗設置樣式

html5 豐富了表單元素,提供了類似 required,email,tel 等表單元素屬性。同樣的,我們可以利用 :valid:invalid 來做針對html5表單屬性的校驗。

  • :required 偽類指定具有required 屬性的表單元素
  • :valid
    偽類指定一個通過匹配正確的所要求的表單元素
  • :invalid 偽類指定一個不匹配指定要求的表單元素

代碼

 <div class="container">
    <div class="row" style="margin-top: 2rem;">
      <form>
        <div class="form-group">
          <label>name</label>
          <input type="text" required placeholder="請輸入名稱">
        </div>
        <div class="form-group">
          <label>email</label>
          <input type="email" required placeholder="請輸入郵箱">
        </div>
        <div class="form-group">
          <label>homepage</label>
          <input type="url" placeholder="請輸入博客url">
        </div>
        <div class="form-group">
          <label>Comments</label>
          <textarea required></textarea>
        </div>
      </form>
    </div>
  </div>
.valid {
  border-color: #429032;
  box-shadow: inset 5px 0 0 #429032;
}

.invalid {
  border-color: #D61D1D;
  box-shadow: inset 5px 0 0 #D61D1D;
}

.form-group {
  width: 32rem;
  padding: 1rem;
  border: 1px solid transparent;
  &:hover {
    border-color: #eee;
    transition: border .2s;
  }
  label {
    display: block;
    font-weight: normal;
  }
  input,
  textarea {
    display: block;
    width: 100%;
    line-height: 2rem;
    padding: .5rem .5rem .5rem 1rem;
    border: 1px solid #ccc;
    outline: none;
    &:valid {
      @extend .valid;
    }
    &:invalid {
      @extend .invalid;
    } 
  }
}

更多偽元素技巧可以參看這篇文章:你不知道的CSS

最終效果

技術分享

3、利用 nth-of-type 選擇某範圍內的子元素

需求

table表格紅綠相間,顯示的更加直觀

代碼

<table>
  <tbody>
    <tr>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
    </tr>
    <tr>
      <td>4</td>
    </tr>
    <tr>
      <td>5</td>
    </tr>
    <tr>
      <td>6</td>
    </tr>
  </tbody>
</table>
tbody tr:nth-of-type(2n){  
background-color: red;
}

tbody tr:nth-of-type(2n+1){
background-color: green;
}

最終效果

技術分享

你也這樣來做,選擇5-10的子元素。

table tr:nth-child(n+5):nth-child(-n+10) {
    background-color: red;
}

4、讓文字像古詩一樣豎著呈現

需求

有時候,需要容器的文字從上到下排列,而不是從左往右排列,如圖所示:

技術分享

這是segmentfault的回到頂部,他的實現很簡單,就是設置一定寬度讓其折行,如果我要實現這種需求呢?

技術分享

代碼

writing-mode 這個 CSS 屬性,我們是不是很少見到,很少用到!我們往往稱不常見的東西為“生僻”,就像是不常見的文字我們叫“生僻字”,因此不常見的 CSS 屬性,我們可以叫做“生僻屬性”,writing-mode 給我們的感覺就是一個“生僻屬性”,很弱,可有可無。這個屬性可以追溯到 IE 5.5 時代,兼容性是相當好的。

<h4>詠柳</h4>
<p>碧玉妝成一樹高,<br>萬條垂下綠絲絳。<br>不知細葉誰裁出,<br>二月春風似剪刀。</p>

<div class="verticle-mode">
    <h4>詠柳</h4>
    <p>碧玉妝成一樹高,<br>萬條垂下綠絲絳。<br>不知細葉誰裁出,<br>二月春風似剪刀。</p>
.verticle-mode {
    writing-mode: tb-rl;
    -webkit-writing-mode: vertical-rl;      
    writing-mode: vertical-rl;
}
/* IE7比較弱,需要做點額外的動作 */
.verticle-mode {
    *width: 120px;
}
.verticle-mode h4,
.verticle-mode p {
    *display: inline;
    *writing-mode: tb-rl;
}
.verticle-mode h4 {
    *float:right;
}

最終效果

技術分享

更多細節與討論請移步張鑫旭老師的這篇文章:改變CSS世界縱橫規則的writing-mode屬性

5、實現鼠標懸浮內容自動撐開的過渡動畫

需求

需要為一個列表添加個動畫,容器的高度是不確定的,也就是高度為 auto,懸浮時候撐開內容有個過渡動畫

如下圖所示:

技術分享

而用 CSS3 實現的話,由於高度的不確定,而 transtion 是需要具體的樹枝,所以設置 height:auto 是無法實現效果的,可以通過 max-height 這個屬性間接的實現這麽個效果,css 樣式是這樣的:

代碼

<ul>
  <li>
    <div class="hd"> 列表1 </div>
    <div class="bd">列表內容<br>內容列表內容<br>內容列表內容<br>內容</div>
  </li>
  <li>
    <div class="hd"> 列表1 </div>
    <div class="bd">列表內容<br>內容列表內容<br>內容列表內容<br>內容</div>
  </li>
  <li>
    <div class="hd"> 列表1 </div>
    <div class="bd">列表內容<br>內容列表內容<br>內容列表內容<br>內容</div>
  </li>
</ul>
.bd {
  max-height:0;
  overflow:hidden;
  transition: all 1s ease-out;
}
li:hover .bd {
  max-height: 600px;
  transition-timing-function: ease-in;
}

最終效果

跟前面 GIF 差不多,這裏就不錄 GIF 了,有興趣的可以自己嘗試感受一下

技術分享

6、利用 pointer-events 禁用 a 標簽事件效果

需求:

在做 tab 切換的時候,當選中當前項,禁用當前標簽的事件,只有切換其他 tab 的時候,才重新請求新的數據。

pointer-events 是一個用於 HTML 指針事件的屬性。

pointer-events 可以禁用 HTML 元素的 hover/focus/active 等動態效果。

默認值為 auto,語法:pointer-events: auto | none | visiblepainted | visiblefill | visiblestroke | visible | painted | fill | stroke | all;

代碼

 <ul>
    <li>
        <a class="tab" href="https://google.com">aaa</a>
    </li>
    <li>
         <a class="tab active" href="https://facebook.com">bbb</a>
    </li>
    <li>
        <a class="tab" href="https://stackoverflow.com">ccc</a>
     </li>
    </ul>
   .active{
         pointer-events: none;
     }

最終效果

技術分享

好像沒什麽效果 技術分享

7、CSS 如何實現文字兩端對齊

需求

紅框所在的文字有四個字的、三個字的、兩個字的,如果不兩端對齊可以選擇居中對齊,或者右對齊。但是如果要想文字兩端對齊呢?

代碼

<div>姓名</div>
<div>手機號碼</div>
<div>驗證碼</div>
<div>賬號</div>
<div>密碼</div>
div{
margin:10px 0; 
width:100px;
border:1px solid red;
text-align-last: justify;
}

最終效果

技術分享

8、使用 :not() 去除導航上不需要的屬性

需求

有時候導航欄需要之間需要用逗號,進行隔離,但是最後一個不需要

代碼

<ul class="nav">
  <li>a</li>
  <li>b</li>
  <li>c</li>
  <li>d</li>
  <li>e</li>
</ul>
li{
list-style:none;
margin-bottom:10px;
display:inline-block;
}

ul > li:not(:last-child)::after {
  content: ",";
}

當然,你可以使用 .nav li + li(不包括第一個li) 或者 .nav li:first-child ~ li(不包括最後一個li), 但是使用 :not() 的意圖特別清晰,CSS選擇器按照人類描述它的方式定義邊框。

最後效果

技術分享

或者,你已經學習了一些關於 使用 :not(),你還可以嘗試:

/* 選擇1到3的元素並顯示 */
li:not(:nth-child(-n+3)){
  display: none;
}

9、移動web頁面支持彈性滾動

需求

在IOS機型中,非body元素的滾動條會非常不流暢,又不想用JS模擬滾動條。

傳統 pc 端中,子容器高度超出父容器高度,通常使用 overflow:auto 可出現滾動條拖動顯示溢出的內容,而移動web開發中,由於瀏覽器廠商的系統不同、版本不同,導致有部分機型尤其是 IOS 機型不支持彈性滾動,從而在開發中制造了所謂的 BUG

代碼

body{
-webkit-overflow-scrolling: touch; /* ios5+ */
}
ele{
overflow:auto;
}

-webkit-overflow-scrolling屬性具有繼承效果,所以在 body 上設置即可,這樣局部滾動條就非常的流暢了。

最終效果

所有滾動條都相當的流暢了

10、美化瀏覽器自帶的 radiocheckbox 屬性

需求

設計師:你那個單選框按鈕好醜啊,跟我的設計稿差好遠。程序員:我有什麽辦法,瀏覽器就是這樣的。。。

記得剛開始寫頁面時候,被瀏覽器各種默認的 UI 樣式惡心到了,當初確實也沒啥辦法,反正也不影響功能,就那樣吧。

先講一下原理:checkbox hack技術

我們使用 CSS 一些特殊的選擇器,然後配合單選框以及復選框自帶的一些特性,可以實現元素的顯示隱藏效果。然後通過一些簡單的擴展,我們可以不使用任何 JavaScript代碼實現類似:自定義的單復選框,“更多”展開與收起效果,選項卡切換效果,或是多級下拉列表效果等等。

相信很多前端開發人員都會遇到 boss 讓修改 checkboxradio 樣式,畢竟自帶的樣式太醜了。後來我們發現修改自帶樣式並不是那麽容易,最後直接使出殺手鐧——點擊之後替換圖片。

今天教大家一種方法,不用替換圖片,隨意修改樣式。

先講一下原理:兩個關鍵東東,一是偽類選擇器 :checked,表示對應控件元素(單選框或是復選框)選中時的樣式;二就是加號 + 相鄰兄弟選擇器,這個符號表示選擇後面的兄弟節點。於是,兩者配合,就可以輕松自如控制後面元素的顯示或者隱藏,或是其他樣式了。

而如何讓單復選框選中和不選中了,那就是 label 標簽了哈,for 屬性錨定對應的單選框或是復選框,然後點擊這裏的 label 標簽元素的時候,對應的單復選框就會選中或是取消選中。然後,就有上面的效果啦!

代碼

這裏只給一個 radio 單選框的代碼,僅供參考:

<div class="radio-beauty-container">
    <label>
        <span class="radio-name">前端工程師</span>
        <input type="radio" name="radioName" id="radioName1" hidden/>
        <label for="radioName1" class="radio-beauty"></label>
    </label>
    <label>
        <span class="radio-name">後端工程師</span>
        <input type="radio" name="radioName" id="radioName2" hidden/>
        <label for="radioName2" class="radio-beauty"></label>
    </label>
    <label>
        <span class="radio-name">全棧工程師</span>
        <input type="radio" name="radioName" id="radioName3" hidden/>
        <label for="radioName3" class="radio-beauty"></label>
    </label>
</div>
.radio-beauty-container {
    font-size: 0;
    $bgc: green;
    %common {
        padding: 2px;
        background-color: $bgc;
        background-clip: content-box;
    }
    .radio-name {
        vertical-align: middle;
        font-size: 16px;
    }
    .radio-beauty {
        width: 18px;
        height: 18px;
        box-sizing: border-box;
        display: inline-block;
        border: 1px solid $bgc;
        vertical-align: middle;
        margin: 0 15px 0 3px;
        border-radius: 50%;
        &:hover {
            box-shadow: 0 0 7px $bgc;
            @extend %common;
        }
    }
    input[type="radio"]:checked+.radio-beauty {
        @extend %common;
    }
}

最終效果

技術分享

美化radio單選框在線預覽地址:點擊我呀
美化checkbox復選框在線預覽地址:點擊我呀

更多關於這方面的介紹和例子可以參看張鑫旭大神的這篇文章:CSS radio/checkbox單復選框元素顯隱技術

11、改變 input 焦點光標的顏色

需求

設計師覺得默認的光標顏色有點與整體設計風格不符合,有點突兀,想換成紅色的

代碼

<input value="This field uses a default caret." />
<input class="custom" value="I have a custom caret color!" />
input {
  caret-color: auto;
  display: block;
  margin-bottom: .5em;
}

input.custom {
  caret-color: red;
}

最終效果

技術分享

12、rem 布局不再使用 JavaScript 設置

這裏不探討 rem 的原理以及細節,還不熟悉的童鞋建議去惡補一下。

需求

有時候,移動端用 rem 布局時候,根據不同的屏幕寬度要設置不同的 font-size 來做到適配,要寫一坨 JS 來設置,能不能不用JS呢?

例如:以 750px 設計稿作為基準,根節點設置 font-size100px ,只考慮 DPR2 的情況,只考慮最簡單的情況

 document.querySelector(‘html‘).style.fontSize = `${window.innerWidth / 7.5 }px`;

代碼

現在移動端 css3 單位 vw ,wh 兼容性已經很不錯了,在不需要兼容太低版本的安卓機情況下可以這樣來:

html{
font-size: 100vw / 750
}

最終結果

就這麽簡單的設置,rem 就可以使用了

13、利用 transparent 屬性實現各種三角形,提示框

需求

在不使用圖片的情況,實現一個簡單的三角形箭頭

代碼

#triangle-right {
    width: 0;
    height: 0;
    border-top: 50px solid transparent;
    border-left: 100px solid red;
    border-bottom: 50px solid transparent;
}

最終效果

復雜點的話,同樣的原理還可以實現一個五角星,原理都是利用 transparent 的透明屬性。

14、讓網站所有圖片變成黑白色彩的

需求

記得2008年時候汶川大地震時候,很多網站圖片都變成黑白色彩悼念逝者

代碼

<img src="https://user-gold-cdn.xitu.io/2017/9/25/0844cf44a8d8c4ed026d6c488a6e9b80?
imageView2/1/w/500/h/200/q/85/interlace/1" alt="" class="desaturate">
img.desaturate {
    filter: grayscale(100%);
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
}

最終效果

15、實現文字的波浪線效果

需求

實現文字波浪線的強調效果,如圖所示

技術分享

?相信大家對於 text-decoration 這個屬性並不陌生,在重置 a 標簽的默認樣式時,我們經常要這樣寫:text-decoration: none; 可能對它了解的人也很少,實際上 text-decoration 是一個復合屬性,由 linestylecolor 組成。

??所以我們可以實現這樣的效果:
技術分享

??可惜的是 line 只有 underline (下劃線)、overline (上劃線)和 line-through (刪除線)。如果突然需要下劃波浪線,怎麽辦呢?不要急,神奇的 CSS 會幫你做到的。首先,你需要先了解一下 漸變的使用技巧。

??說一下這裏的思路,我們首先要用兩段漸變構造一個基本元素:‘X‘(這裏我就不放圖了),下一步就比較重要了,我們要截取‘X‘的上半部分,得到一個‘V‘,從而結合 repeat 形成波浪線。下面是用 scss 寫的一個 mixin ,方便以後使用。

代碼

    @mixin waveline($color,$h) {
        position: relative;
        &::after {
            content: ‘‘;
            display: block;
            position: absolute;
            top: 100%;
            left: 0;
            width: 100%;
            height: $h;
            background: linear-gradient(135deg, transparent, transparent 45%, $color, transparent 55%, transparent 100%),
                        linear-gradient(45deg, transparent, transparent 45%, $color, transparent 55%, transparent 100%);
            background-size: $h * 2 $h * 2;
        }
    }

最終效果

技術分享

兼容性

這些技巧在當前版本的ChromeFirefoxSafari, 以及Edge, 和IE11可以工作,移動端基本都沒問題,IE 重度開發者慎用。

相關兼容性自行查找:caniuse.com/

推薦一波

有趣的 GitHub 倉庫

國服第一切圖仔的 CSS 倉庫:你想知道的 CSS 奇技淫巧,在這裏,都有。iCSS -- interesting css

張鑫旭老師的博客

前端技術

【溫故知新】——CSS黑魔法小技巧可以少些不必要的js