【前端詞典】提升幸福感的 9 個 CSS 技巧

前言

在這篇文章我會介紹 9 個使你的 CSS 更加簡潔優雅的使用技巧。這些技巧小生常用,以爲挺高效實用,因此也就有了這篇文章。css

9 個 CSS 技巧

特此聲明,這裏說的 CSS 並不止包含 CSS,也包含 CSS 預處理器(Less Sass 等),願各位看官不要糾結於此。html

正文如今開始。前端

1. 建議使用 padding 代替 margin

咱們在設計稿還原的時候,paddingmargin 兩個是經常使用的屬性,但咱們知道屬於同一個 BFC 的兩個相鄰 Box 的 margin 會發生重疊,因此若是 margin 使用的過於頻繁的時候,Box 的垂直距離可能就會發生重疊。webpack

還有一個問題就是第一個子元素的 margin-top 值會加在父元素上的 bug(最後一個子元素的 margin-bottom 也存在相似的問題)。這裏是否是有人問爲何呢?ios

緣由就在於:web

the expression collapsing margins means that adjoining margins (no non-empty content, padding or border areas or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.express

翻譯過來就是:npm

全部毗鄰的兩個或多個盒元素的 margin 將會合併爲一個 margin 共享。 毗鄰的定義爲:同級或者嵌套的盒元素,而且它們之間沒有非空內容、PaddingBorder 分隔。瀏覽器

至於爲何合併我我的以爲這和排隊的安全距離有點相似,人與人之間的安全距離是 1m,若是安全距離不合並,那麼咱們在排隊的時候是否是人與人的距離就變成 2m 了。固然極可能不是這個緣由。緩存

因此咱們能夠在首位元素使用 padding 來替代 margin。固然有的時候使用 padding 不能知足需求,這時你也能夠在「非空內容」這個條件作文章。即在父元素添加一個僞元素。

因此咱們在使用 margin 的時候必定要注意 collapsing margins 問題。

2. position:fixed 降級問題

不知道曾經的你是否是遇到吸頂效果,就是使用 position:fixed 這個屬性。其實若是其父元素中有使用 transformfixed 的效果會降級爲 absolute

解決方案:

既然會降級爲 absolute 效果,咱們該怎麼解決這個問題呢?咱們就改考慮什麼狀況下 fixedabsolute 的表現效果會是同樣的。

即當使用 fixed 的直接父元素的高度和屏幕的高度相同時 fixedabsolute 的表現效果會是同樣的。

若是這個直接父級內的元素存在滾動的狀況,那就加上 overflow-y: auto

3. 合理使用 px | em | rem | % 等單位

在 CSS 中有許多距離單位,好比 px | em | rem | %,還有 CSS3 中的 vh | vw 等單位。

那麼咱們在項目中應該如何使用呢?咱們在 pc 端不須要考慮的這麼複雜,因此這裏咱們主要講講這些單位在移動端中的使用。

基礎單位 px

px 是咱們最先接觸到的單位了,不過咱們在移動端自適應的要求下,使用的頻率不是很高;我總結了如下使用的狀況:

比較小的圖案

好比須要咱們畫一個 r 爲 5px 的圓,若是咱們使用 rem 做爲單位,咱們很快會發如今一些機型上的圖案不圓,會呈現橢圓形。這是因爲 rem 轉 px 會存在精度丟失問題。

因此這個時候咱們就須要使用 px 配合 dpr 來實現:

// less 
/*@size 建議取雙數*/
.circle(@size, @backgroundColor) {  
    width: @size;
    height: @size;
    background-color: @backgroundColor;
    [data-dpr="1"] & {
        width: @size * 0.5;
        height: @size * 0.5;
    }
    [data-dpr="3"] & {
        width: @size * 1.5;
        height: @size * 1.5;
    }
}
複製代碼

1px 細線問題

這個問題下面我會單獨作一小節講,在這裏就不累述。

字體大小(基本都是用 rem 做爲單位)

通常狀況字體的大小我也會使用 rem 做爲單位,由於精度丟失我認爲在能夠接受的範圍以內。

相對單位 rem

rem 是 CSS3 新增的一個相對單位(root em),即相對 HTML 根元素的字體大小的值。

rem 應該是自適應使用的最普遍的單位了。

相對單位 em

em 也是一個相對單位,倒是相對於當前對象內文本的字體大小。

line-height

通常建議在 line-height 使用 em。由於在須要調整字體大小的時候,只需修改 font-size 的值,而 line-height 已經設置成了相對行高了。

首行縮進兩個字符

在存在首行縮進的需求,我也會使用這個單位。

text-indent: 2em
複製代碼

視口單位 vw | vh

vw: 1vw = 視口寬度的 1%
vh: 1vh = 視口高度的 1%

咱們知道以 rem 單位設計的彈性佈局,是須要在頭部加載一段腳原本進行監聽分辨率的變化來動態改變根元素字體大小,使得 CSS 與 JS 耦合了在一塊兒。

那麼有沒有方案解決這個耦合的問題呢?

答案就是視口單位 vw | vh。

如下就是前人給出的使用方案:

$vm_fontsize: 75;
@function rem($px) {
     @return ($px / $vm_fontsize ) * 1rem;
}
$vm_design: 750;
html {
    font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw; 
    @media screen and (max-width: 320px) {
        font-size: 64px;
    }
    @media screen and (min-width: 540px) {
        font-size: 108px;
    }
}
// body 也增長最大最小寬度限制,避免默認100%寬度的 block 元素跟隨 body 而過大太小
body {
    max-width: 540px;
    min-width: 320px;
}
複製代碼

4. 合理使用變量

通常設計稿中的某一類的文字(元素)都是用相同的字體大小、顏色、行高等樣式屬性,因此這些值咱們沒必要每次都重複寫,由於當 UI 更新設計方案,你須要改的地方就不少了。這些重複使用的值咱們徹底能夠存放在變量裏面。

Sass 和 Less 稍微有點區別:

// sass
$direction: left;
// less
@direction: left;
複製代碼

固然 CSS 原生也是存在變量的,使用規則以下:

變量定義的語法是: --*; // 爲變量名稱。
變量使用的語法是:var(
);

  1. 不管是變量的定義和使用只能在聲明塊 {} 裏面
  2. CSS 變量字符限制爲: [0-9]、[a-zA-Z]、_、-、中文和韓文等。
:root {
    --blue_color: #3388ff;
    --main_bgcolor: #fafafa;
    --font_size_12: 12px;
    --font_size_14: 14px;
    --color: 20px;
}
.div1{
    background-color: var(--main_bgcolor);
    font-size: var(--font_size_12);
}
複製代碼

5. 使用 Mixin 歸類重複樣式

和重複變量同樣,重複的樣式也能夠歸類。我以爲優秀的代碼其中有一條確定是代碼的複用性強。

以前咱們寫 CSS 的時候,也會將一些重複使用的代碼放在一個 class 中,這樣的確達到了必定的複用性,不過最後的效果可能就是在一個元素裏面放了不少 class,以下圖:

這樣下一個接手得人不免會有點迷糊,並且這樣會形成樣式愈來愈難修改。

這個時候,mixin( 能夠理解成 class 中的 class )就能發揮它的做用了。

這是一個描述性文字的樣式:

.font-description {
    .font-des-style(24px,#fff,1.5em);
    .line-camp(2);
}

// less
/* 多行顯示 */
.line-camp( @clamp:2 ) {
    text-overflow: -o-ellipsis-lastline;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: @clamp;
    -webkit-box-orient: vertical; 
}

.font-des-style( @fontSize, @color, @lineHeight, @textAlign:left ) {
    font-size: @fontSize;
    color: @color;
    line-height: @lineHeight;
    text-align: @textAlign;
}
複製代碼

這只是一個簡單的例子,咱們能夠把可複用的樣式放在 mixin 中,這樣接手項目的人只須要熟悉你寫的 mixin.less 就能夠開始迭代需求了。

6. 1px 方案

作過移動端需求的前端確定是避免不了處理 1px 細線問題,這個問題的緣由就是 UI 對頁面美觀度的要求愈來愈高(不要和我說這是 retina 屏的問題)。

據小生所知好像沒有什麼兼容性特別好的方案,這裏我只是提供兩種種相對較好的方案。

使用僞類 + transform

.border_bottom { 
    overflow: hidden; 
    position: relative; 
    border: none!important; 
}
.border_bottom:after { 
    content: "";
    display: block;
    position: absolute; 
    left: 0; 
    bottom: 0; 
    width: 100%; 
    height: 1px; 
    background-color: #d4d6d7; 
    -webkit-transform-origin: 0 0;  
    transform-origin: 0 0; 
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
}
複製代碼

固然這個方案在一些版本較低的機型也是會出現粗細不均、細線消失斷裂的兼容性問題。不過如今已經 2019 年了,版本較低的機型也淘汰的差很少了。

使用 box-shadow 模擬

.border_bottom {
  box-shadow: inset 0px -1px 1px -1px #d4d6d7;
}
複製代碼

這個方案基本能夠知足全部場景,不過有個缺點也就是顏色會變淺。

多謝 D文斌 分享的另外一種方案: 這種方案對 dpr 作了不一樣的處理,可謂更加精細。

.min-device-pixel-ratio(@scale2, @scale3) {
  @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {
    transform: @scale2;
  }
  @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {
    transform: @scale3;
  }
}

.border-1px(@color: #DDD, @radius: 2PX, @style: solid) {
  &::before {
    content: "";
    pointer-events: none;
    display: block;
    position: absolute;
    left: 0;
    top: 0;
    transform-origin: 0 0;
    border: 1PX @style @color;
    border-radius: @radius;
    box-sizing: border-box;
    width: 100%;
    height: 100%;
    @media screen and (min-device-pixel-ratio: 2), (-webkit-min-device-pixel-ratio: 2) {
      width: 200%;
      height: 200%;
      border-radius: @radius * 2;
      transform: scale(.5);
    }
    @media screen and (min-device-pixel-ratio: 3), (-webkit-min-device-pixel-ratio: 3) {
      width: 300%;
      height: 300%;
      border-radius: @radius * 3;
      transform: scale(.33);
    }
  }
}

.border-top-1px(@color: #DDD, @style: solid) {
  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    border-top: 1Px @style @color;
    transform-origin: 0 0;
    .min-device-pixel-ratio(scaleY(.5), scaleY(.33));
  }
}
複製代碼

7. 從 html 元素繼承 box-sizing

在大多數狀況下咱們在設置元素的 borderpadding 並不但願改變元素的 width,height 值,這個時候咱們就能夠爲該元素設置 box-sizing:border-box;

我不但願每次都重寫一遍,而是但願他是繼承而來的,那麼咱們可使用以下代碼:

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
複製代碼

這樣的好處在於他不會覆蓋其餘組件的 box-sizing 值,又無需爲每個元素重複設置 box-sizing: border-box;

8. 內聯首屏關鍵 CSS

性能優化中有一個重要的指標 —— 首次有效繪製(FMP),即指頁面的首要內容(primary content)出如今屏幕上的時間。這一指標影響用戶看到頁面前所需等待的時間,而 內聯首屏關鍵 CSS(即 Critical CSS,能夠稱之爲首屏關鍵 CSS) 能給用戶一個更好的心理預期。

如圖:

咱們知道內聯 CSS 可以使瀏覽器開始頁面渲染的時間提早,即在 HTML 下載完成以後就能渲染了。

既然是內聯關鍵 CSS,也就說明咱們只會將少部分的 CSS 代碼直接寫入 HTML 中。至於內聯哪些 CSS 你可使用 Critical。

9. 文字超出省略、文字兩端對齊

需求中咱們也常常遇到這樣的需求,這裏直接提供方案。

超出省略

.line-camp( @clamp:2 ) {
    text-overflow: -o-ellipsis-lastline;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: @clamp;
    -webkit-box-orient: vertical; 
}
複製代碼

所遇到的問題:

-webkit-box-orient: vertical 在使用 webpack 打包的時候這段代碼會被刪除掉,緣由是 optimize-css-assets-webpack-plugin 這個插件的問題。

解決方案:

可使用以下的寫法:

.line-camp( @clamp:2 ) {
    text-overflow: -o-ellipsis-lastline;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: @clamp;
    /*! autoprefixer: off */
    -webkit-box-orient: vertical;
    /* autoprefixer: on */
}
複製代碼

兩端對齊

// html
<div>姓名</div>
<div>手機號碼</div>
<div>帳號</div>
<div>密碼</div>

// css
div {
    margin: 10px 0; 
    width: 100px;
    border: 1px solid red;
    text-align: justify;
    text-align-last:justify
}
div:after{
    content: '';
    display: inline-block;
    width: 100%;
}
複製代碼

效果以下:

Vue 相關文章輸出計劃

最近總有朋友問我 Vue 相關的問題,所以接下來我會輸出 9 篇 Vue 相關的文章,但願對你們有必定的幫助。我會保持在 7 到 10 天更新一篇。

  1. 【前端詞典】Vuex 注入 Vue 生命週期的過程
  2. 【前端詞典】淺析 Vue 響應式原理
  3. 【前端詞典】新老 VNode 進行 patch 的過程
  4. 【前端詞典】如何開發功能組件並上傳 npm
  5. 【前端詞典】從這幾個方面優化你的 Vue 項目
  6. 【前端詞典】從 Vue-Router 設計講前端路由發展
  7. 【前端詞典】在項目中如何正確的使用 Webpack
  8. 【前端詞典】Vue 服務端渲染
  9. 【前端詞典】Axios 與 Fetch 該如何選擇

建議你關注個人公衆號,第一時間就能夠接收最新的文章。

若是你想加羣交流,也能夠添加有點智能的機器人,自動拉你進羣:

熱門文章傳送門

  1. 【前端詞典】滾動穿透問題的解決方案
  2. 【前端詞典】5 種滾動吸頂實現方式的比較(性能升級版)
  3. 【前端詞典】提升幸福感的 9 個 CSS 技巧
  4. 【前端詞典】分享 8 個有趣且實用的 API
  5. 【前端詞典】從輸入 URL 到展示涉及哪些緩存環節(很是詳細)
相關文章
相關標籤/搜索