在這篇文章我會介紹 9 個使你的 CSS 更加簡潔優雅的使用技巧。這些技巧小生常用,以爲挺高效實用,因此也就有了這篇文章。css
特此聲明,這裏說的 CSS 並不止包含 CSS,也包含 CSS 預處理器(Less Sass 等),願各位看官不要糾結於此。html
正文如今開始。前端
咱們在設計稿還原的時候, padding 和 margin 兩個是經常使用的屬性,但咱們知道屬於同一個 BFC 的兩個相鄰 Box 的 margin 會發生重疊,因此若是 margin 使用的過於頻繁的時候,Box 的垂直距離可能就會發生重疊。webpack
還有一個問題就是第一個子元素的 margin-top 值會加在父元素上的 bug(最後一個子元素的 margin-bottom 也存在相似的問題)。這裏是否是有人問爲何呢?web
緣由就在於:express
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.瀏覽器
翻譯過來就是:sass
全部毗鄰的兩個或多個盒元素的 margin 將會合併爲一個 margin 共享。 毗鄰的定義爲:同級或者嵌套的盒元素,而且它們之間沒有非空內容、 Padding 或 Border 分隔。安全
至於爲何合併我我的以爲這和排隊取款的安全距離有點相似,人與人之間的安全距離是 1m,若是安全距離不合並,那麼咱們在排隊的時候是否是人與人的距離就變成 2m 了。固然極可能不是這個緣由。性能優化
因此咱們能夠在首位元素使用 padding 來替代 margin。固然有的時候使用 padding 不能知足需求,這時你也能夠在「非空內容」這個條件作文章。即在父元素添加一個僞元素。
因此咱們在使用 margin 的時候必定要注意 collapsing margins 問題。
不知道曾經的你是否是遇到吸頂效果,就是使用 position:fixed 這個屬性。其實若是其父元素中有使用 transform, fixed 的效果會降級爲 absolute。
既然會降級爲 absolute 效果,咱們該怎麼解決這個問題呢?咱們就改考慮什麼狀況下 fixed 和 absolute 的表現效果會是同樣的。
即當使用 fixed 的直接父元素的高度和屏幕的高度相同時 fixed 和 absolute 的表現效果會是同樣的。
若是這個直接父級內的元素存在滾動的狀況,那就加上 overflow-y:auto。
在 CSS 中有許多距離單位,好比 px | em | rem | %,還有 CSS3 中的 vh | vw 等單位。
那麼咱們在項目中應該如何使用呢?咱們在 pc 端不須要考慮的這麼複雜,因此這裏咱們主要講講這些單位在移動端中的使用。
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; } }
這個問題下面我會單獨作一小節講,在這裏就不累述。
通常狀況字體的大小我也會使用 rem 做爲單位,由於精度丟失我認爲在能夠接受的範圍以內。
rem 是 CSS3 新增的一個相對單位(root em),即相對 HTML 根元素的字體大小的值。
rem 應該是自適應使用的最普遍的單位了。
em 也是一個相對單位,倒是相對當前元素的字體大小。
通常建議在 line-height 使用 em。由於在須要調整字體大小的時候,只需修改 font-size 的值,而 line-height 已經設置成了相對行高了。
在存在首行縮進的需求,我也會使用這個單位。
text-indent: 2em
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; }
通常設計稿中的某一類的文字(元素)都是用相同的字體大小、顏色、行高等樣式屬性,因此這些值咱們沒必要每次都重複寫,由於當 UI 更新設計方案,你須要改的地方就不少了。這些重複使用的值咱們徹底能夠存放在變量裏面。
Sass 和 Less 稍微有點區別:
// sass $direction: left; // less @direction: left;
固然 CSS 原生也是存在變量的,使用規則以下:
變量定義的語法是: --; // *爲變量名稱。 變量使用的語法是:var();
不管是變量的定義和使用只能在聲明塊 {} 裏面
: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); }
和重複變量同樣,重複的樣式也能夠歸類。我以爲優秀的代碼其中有一條確定是代碼的複用性強。
以前咱們寫 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 就能夠開始迭代需求了。
作過移動端需求的前端確定是避免不了處理 1px 細線問題,這個問題的緣由就是 UI 對頁面美觀度的要求愈來愈高(不要和我說這是 retina 屏的問題)。
據小生所知好像沒有什麼兼容性特別好的方案,這裏我只是提供兩種種相對較好的方案。
.border_bottom { overflow: hidden; position: relative; border: none!important; } .border_bottom:after { content: "."; 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 年了,版本較低的機型也淘汰的差很少了。
.border_bottom { box-shadow: inset 0px -1px 1px -1px #d4d6d7; }
這個方案基本能夠知足全部場景,不過有個缺點也就是顏色會變淺。
在大多數狀況下咱們在設置元素的 border 和 padding 並不但願改變元素的 width,height 值,這個時候咱們就能夠爲該元素設置 box-sizing:border-box;。
我不但願每次都重寫一遍,而是但願他是繼承而來的,那麼咱們可使用以下代碼:
html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; }
這樣的好處在於他不會覆蓋其餘組件的 box-sizing 值,又無需爲每個元素重複設置 box-sizing:border-box;。
性能優化中有一個重要的指標 —— 首次有效繪製(FMP),即指頁面的首要內容(primary content)出如今屏幕上的時間。這一指標影響用戶看到頁面前所需等待的時間,而 內聯首屏關鍵 CSS(即 Critical CSS,能夠稱之爲首屏關鍵 CSS) 能給用戶一個更好的心理預期。
如圖:
咱們知道內聯 CSS 可以使瀏覽器開始頁面渲染的時間提早,即在 HTML 下載完成以後就能渲染了。
既然是內聯關鍵 CSS,也就說明咱們只會將少部分的 CSS 代碼直接寫入 HTML 中。至於內聯哪些 CSS 你可使用 Critical。
需求中咱們也常常遇到這樣的需求,這裏直接提供方案。
超出省略
.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-last: justify; }
效果以下:
《前端詞典》這個系列會持續更新,每一期我都會講一個出現頻率較高的知識點。但願你們在閱讀的過程中能夠斧正文中出現不嚴謹或是錯誤的地方,本人將不勝感激;若經過本系列而有所得,本人亦將不勝欣喜。
若是你以爲個人文章寫的還不錯,能夠關注個人微信公衆號,公衆號裏會提早劇透呦。
你也能夠添加個人微信 wqhhsd, 歡迎交流。
在接下來的幾篇文章中我會介紹 Vue 相關