跳到主要內容
黯羽輕揚每天積累一點點

normalize、reset 與 base

免費2016-08-13#CSS#css分层#css模块化#base common page

reset?normalize?需要嗎?不需要嗎?

寫在前面

一個故事:

你知道 normalize 嗎?與 reset 的區別是什麼?

面試官問,我編(當時確實不知道,但兩個單詞的字面意思其實很明確了)

一。reset

reset:重置,清零

最粗暴的方式:

* {padding:0; margin:0;}

把所有標籤全都扒光。bodyh1-h6divarticle 等一大推本來各不相同的標籤,現在長的一模一樣了,僅剩名字作為最後的尊嚴

當然,也有溫和一點的(更長的):

body, dl, dd, h1, h2, h3, h4, h5, h6, p, form{margin:0;}
ol,ul{margin:0; padding:0;}

溫和 reset 的原則是:只去掉需要去掉的。比如 div 本來就啥也沒穿,還被扒了一遍,這不人道

含 reset 的樣式結構可能是這樣:

reset.css   // 去掉所有預設樣式
common.css  // 項目維護的公共樣式
page.css    // 業務需要的樣式(無法複用)

按順序引入,用下面的覆蓋掉上面的。所以一個樣式屬性可能經過層層重寫後才以最終的模樣展現給用戶,存在冗餘 reset 的問題:如果某塊樣式註定是需要支持訂製的,那就一定會被後來的 css 覆蓋,沒必要先用 reset 扒光吧?

二。normalize

normalize:歸一化,使正常化、標準化

Normalize.css makes browsers render all elements more consistently and in line with modern standards. It precisely targets only the styles that need normalizing.

normalize 做了幾件事情:

  • 保留瀏覽器預設樣式中有用的部分

  • 同時保證跨瀏覽器一致性(修復各瀏覽器中存在的不合 W3C 規範的問題)

  • 在合適的地方設置預設值

normalize 是補丁性質的,不像 reset 是破壞性的,例如 normalize.css 源碼

/**
 * Add the correct display in IE 9-.
 * 1. Add the correct display in IE.
 */

figcaption,
figure,
main { /* 1 */
  display: block;
}

/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */

hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}

此處通過前端方案修復了瀏覽器存在的樣式問題,同時考慮低版本瀏覽器兼容,這裡傾向於「標準化」。此外,也有「正常化」的一面:

/**
 * 1. Change the default font family in all browsers (opinionated).
 * 2. Correct the line height in all browsers.
 * 3. Prevent adjustments of font size after orientation changes in IE and iOS.
 */

html {
  font-family: sans-serif; /* 1 */
  line-height: 1.15; /* 2 */
  -ms-text-size-adjust: 100%; /* 3 */
  -webkit-text-size-adjust: 100%; /* 3 */
}

前輩已經解讀過源碼了,請查看 關於 CSS Reset 那些事(二)之 Normalize.css 源碼解讀

三。normalize 與 reset 的區別

一個段子:

CSS Reset 是革命黨,CSS Reset 裡最激進那一派提倡不管你小子有用沒用,通通給我脫了那身衣服,憑什麼你 body 出生就穿一圈 margin,憑什麼你姓 h 的比別人吃得胖,憑什麼你 ul 戴一胳膊珠子。於是 *{margin:0;} 等等運動,把人家全拍扁了。看似是眾生平等了,實則是浪費了資源又佔不到便宜,有求於人家的時候還得賤賤地給加回去,實在需要人家的預設樣式了怎麼辦?人家鍋都扔爐子裡燒了,自己看著辦吧。

Normalize.css 是改良派。他們提倡,各個元素都有其存在的道理,簡單粗暴地一視同仁是不好的。body 那一圈確實擠壓了頁面的生存空間,那就改掉。士農工商,誰有誰的作用,給他們制定個規範,確保他們在任何瀏覽器裡都幹好自己的活兒。

引自知乎 會擼代碼的段子手的回答

reset 的特點

目標:強制所有瀏覽器表現一致

去掉大多數來自瀏覽器的預設樣式,保證 common, page 等樣式下層是整齊劃一的初始表現

所以一般意義的 reset 是破壞性的,統統扒光

主要存在 2 個問題:

  • 冗餘 reset,影響性能

無論是寫錯的 reset(本不需要),還是在上層一定會被覆蓋的 reset(沒必要),都增大了樣式文件,影響了渲染性能

容易殺錯,也容易放過。精確的高性能 reset?很難實現,甚至不存在(除 FF, Chrome, Safari 外,還有一大堆 xx 瀏覽器,誰知道它預設樣式是啥呀)

  • 分組缺少語義,難以維護

reset 中對標籤的分類不考慮語義,只關注預設表現

引發的後果就是調試工具查看某元素,關注某個屬性,一層層追下去,最後看到一長串不相關的標籤被綁在一起,應用了一兩條規則

至於性能,在成為問題之前都不是問題。據傳言 * {padding:0; margin:0} 對渲染對影響也只是 2ms,如果 真是這樣,那就不用多想了,直接統統扒光最好。因為比起更複雜(更長,更人道)的 reset 帶來的負面影響(增大了樣式文件),渲染時的 2ms 比芝麻還要小

維護的問題,其實還是指向精確的高性能 reset,如果 reset 恰到好處,樣式問題應該與 reset 無關,如果調試中發現需要往下層追,就說明 reset 不夠好

「不 reset 行嗎?」

「當然不行呀,不 reset 的話,那麼多瀏覽器,保不齐有什麼奇怪的預設樣式呢,前端應該有 1px 的執著,精確還原設計稿」

其實仔細想想,為什麼我們需要 reset?就因為大家都在用?

確實很多 reset 樣式在業務中永遠不會用到(老古董 legendfieldset 以及新的語義化標籤 asidesection 對於純移動頁面是幾乎不需要的),真正有用的常用的可能只是 body {margin: 0; },其它都要麼在用的時候需要全面重寫,要麼永遠用不到

所以幾年前掀起了一場 no reset 運動,後來迎來了 normalize……但答案究竟是什麼?

normalize 的特點

從源碼可以發現 normalize 就像補丁一樣,讓瀏覽器預設樣式更「正常」一些:

/* 1. 樣式補丁,修補瀏覽器差異,使其表現貼近標準 */
/**
 * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
 */
b,
strong {
  font-weight: inherit;
}
/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
b,
strong {
  font-weight: bolder;
}

/* 2. 微量的 reset */
/**
 * Add the correct background and color in IE 9-.
 */
mark {
  background-color: #ff0;
  color: #000;
}
/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
sub {
  bottom: -0.25em;
}
sup {
  top: -0.5em;
}

同樣,通過源碼也能發現它並不是 reset 的替代品:

  • reset 像壓路機,開過去之後路面非常平整

  • normalize 像瀝青,填補路面上的裂縫,小坑

但是,我們需要這層瀝青嗎?就因為 Bootstrap 用了我們就得用?

對於純移動頁面來說,normalize 裡 98% 的樣式都用不著,很巧,有用的幾行可能還是:

/**
 * Remove the margin in all browsers (opinionated).
 */

body {
  margin: 0;
}

當然,Bootstrap 需要同時支持 PC 和移動端,適配大屏小屏,一個框架引入這些兼容代碼自然沒錯,更健壯了

但我們的應用可能真的不需要 normalize,即便需要,可能也只需要取其中真正能用到的 30%,其餘部分應該是根據業務特點,去掉某些醜醜的預設樣式(比如 table),再置入基礎樣式,避免在每個頁面中都去設置這些東西,那麼最後產生的這個 css 就叫——base.css

四。css 三層結構

  • base: 基本樣式

站點級的,最基礎,最通用的樣式,不同風格不同內容的站點可以共用 base 樣式

base 是原子的,不可再分,比如兼容性良好的 flex, clearfix 等等

reset 與 base 並列,作為基本樣式組件,當然,也可以把簡單的 reset 放在 base 層裡

  • common: 通用樣式

模塊級的,自定義的樣式模塊,可以供各個頁面複用

在 base 層基礎上提供更複雜的樣式模塊,比如日曆,popup 等等

  • page: 頁面樣式

頁面級的,不需要複用的樣式

針對具體頁面,添加特有的樣式,比如具體色值,字體,hack 等等

合理的分層能夠有效提高樣式的複用性,可以通過在高層簡單地重寫低層某條樣式規則來改變最終樣式;此外還能提高樣式的可維護性,各層分工明確,新增樣式對號入座,html 中以 class 組合的方式來實現最終樣式

base 層和 common 層應該由很少的人來負責管理維護,不會經常變動,但可以擴展,開發者直接針對 UI 設計稿完成 page 層樣式,實現視覺效果,編寫 page 層樣式時同樣可以按照三層結構來組織,例如:

/* base */
body {
    background-color: #eee;
}
h1 {
    border-bottom: 1px solid #ccc;
}
/* common */
.panel {
    border: 1px solid #ddd;
}
.line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* page */
h1 span {
    border: 1px solid red;
    border-raduis: 3px;
}
.panel .line {
    line-height: 1.5em;
}

五。總結

reset?normalize?需要嗎?不需要嗎?

為業務量身定製的才是最好的,精簡、高效

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論