CSS

CSS

本文內容部分引用自 front-end-interview-handbook

CSS 選擇器的優先級是如何計算的?

瀏覽器通過優先級規則,判斷元素展示哪些樣式。優先級通過 4 個維度指標確定,我們假定以a、b、c、d命名,分別代表以下含義:

  1. a表示是否使用內聯樣式(inline style)。如果使用,a爲 1,否則爲 0。
  2. b表示 ID 選擇器的數量。
  3. c表示類選擇器、屬性選擇器和僞類選擇器數量之和。
  4. d表示標籤(類型)選擇器和僞元素選擇器之和。

優先級的結果並非通過以上四個值生成一個得分,而是每個值分開比較。a、b、c、d權重從左到右,依次減小。判斷優先級時,從左到右,一一比較,直到比較出最大值,即可停止。所以,如果b的值不同,那麼cd不管多大,都不會對結果產生影響。比如0,1,0,0的優先級高於0,0,10,10

當出現優先級相等的情況時,最晚出現的樣式規則會被採納。如果你在樣式表裏寫了相同的規則(無論是在該文件內部還是其它樣式文件中),那麼最後出現的(在文件底部的)樣式優先級更高,因此會被採納。

在寫樣式時,我會使用較低的優先級,這樣這些樣式可以輕易地覆蓋掉。尤其對寫 UI 組件的時候更爲重要,這樣使用者就不需要通過非常複雜的優先級規則或使用!important的方式,去覆蓋組件的樣式了。

參考

重置(resetting)CSS 和 標準化(normalizing)CSS 的區別是什麼?你會選擇哪種方式,爲什麼?

  • 重置(Resetting): 重置意味着除去所有的瀏覽器默認樣式。對於頁面所有的元素,像marginpaddingfont-size這些樣式全部置成一樣。你將必須重新定義各種元素的樣式。
  • 標準化(Normalizing): 標準化沒有去掉所有的默認樣式,而是保留了有用的一部分,同時還糾正了一些常見錯誤。

當需要實現非常個性化的網頁設計時,我會選擇重置的方式,因爲我要寫很多自定義的樣式以滿足設計需求,這時候就不再需要標準化的默認樣式了。

參考

請闡述Float定位的工作原理。

浮動(float)是 CSS 定位屬性。浮動元素從網頁的正常流動中移出,但是保持了部分的流動性,會影響其他元素的定位(比如文字會圍繞着浮動元素)。這一點與絕對定位不同,絕對定位的元素完全從文檔流中脫離。

CSS 的clear屬性通過使用leftrightboth,讓該元素向下移動(清除浮動)到浮動元素下面。

如果父元素只包含浮動元素,那麼該父元素的高度將塌縮爲 0。我們可以通過清除(clear)從浮動元素後到父元素關閉前之間的浮動來修復這個問題。

有一種 hack 的方法,是自定義一個.clearfix類,利用僞元素選擇器::after清除浮動。另外還有一些方法,比如添加空的<div></div>和設置浮動元素父元素的overflow屬性。與這些方法不同的是,clearfix方法,只需要給父元素添加一個類,定義如下:

.clearfix::after {
  content: '';
  display: block;
  clear: both;
}

值得一提的是,把父元素屬性設置爲overflow: autooverflow: hidden,會使其內部的子元素形成塊格式化上下文(Block Formatting Context),並且父元素會擴張自己,使其能夠包圍它的子元素。

參考

請闡述z-index屬性,並說明如何形成層疊上下文(stacking context)。

CSS 中的z-index屬性控制重疊元素的垂直疊加順序。z-index只能影響position值不是static的元素。

沒有定義z-index的值時,元素按照它們出現在 DOM 中的順序堆疊(層級越低,出現位置越靠上)。非靜態定位的元素(及其子元素)將始終覆蓋靜態定位(static)的元素,而不管 HTML 層次結構如何。

層疊上下文是包含一組圖層的元素。 在一組層疊上下文中,其子元素的z-index值是相對於該父元素而不是 document root 設置的。每個層疊上下文完全獨立於它的兄弟元素。如果元素 B 位於元素 A 之上,則即使元素 A 的子元素 C 具有比元素 B 更高的z-index值,元素 C 也永遠不會在元素 B 之上.

每個層疊上下文是自包含的:當元素的內容發生層疊後,整個該元素將會在父層疊上下文中按順序進行層疊。少數 CSS 屬性會觸發一個新的層疊上下文,例如opacity小於 1,filter不是nonetransform不是none

參考

請闡述塊格式化上下文(Block Formatting Context)及其工作原理。

塊格式上下文(BFC)是 Web 頁面的可視化 CSS 渲染的部分,是塊級盒佈局發生的區域,也是浮動元素與其他元素交互的區域。

一個 HTML 盒(Box)滿足以下任意一條,會創建塊格式化上下文:

  • float的值不是none.
  • position的值不是staticrelative.
  • display的值是table-celltable-captioninline-blockflex、或inline-flex
  • overflow的值不是visible

在 BFC 中,每個盒的左外邊緣都與其包含的塊的左邊緣相接。

兩個相鄰的塊級盒在垂直方向上的邊距會發生合併(collapse)。更多內容請參考邊距合併(margin collapsing)

參考

有哪些清除浮動的技術,都適用哪些情況?

  • div方法:<div style="clear:both;"></div>
  • Clearfix 方法:上文使用.clearfix類已經提到。
  • overflow: autooverflow: hidden方法:上文已經提到。

在大型項目中,我會使用 Clearfix 方法,在需要的地方使用.clearfix。設置overflow: hidden的方法可能使其子元素顯示不完整,當子元素的高度大於父元素時。

請解釋什麼是雪碧圖(css sprites),以及如何實現?

雪碧圖是把多張圖片整合到一張上的圖片。它被運用在衆多使用了很多小圖標的網站上(Gmail 在使用)。實現方法:

  1. 使用生成器將多張圖片打包成一張雪碧圖,併爲其生成合適的 CSS。
  2. 每張圖片都有相應的 CSS 類,該類定義了background-imagebackground-positionbackground-size屬性。
  3. 使用圖片時,將相應的類添加到你的元素中。

好處:

  • 減少加載多張圖片的 HTTP 請求數(一張雪碧圖只需要一個請求)。但是對於 HTTP2 而言,加載多張圖片不再是問題。
  • 提前加載資源,防止在需要時纔在開始下載引發的問題,比如只出現在:hover僞類中的圖片,不會出現閃爍。
參考

如何解決不同瀏覽器的樣式兼容性問題?

  • 在確定問題原因和有問題的瀏覽器後,使用單獨的樣式表,僅供出現問題的瀏覽器加載。這種方法需要使用服務器端渲染。
  • 使用已經處理好此類問題的庫,比如 Bootstrap。
  • 使用 autoprefixer 自動生成 CSS 屬性前綴。
  • 使用 Reset CSS 或 Normalize.css。

如何爲功能受限的瀏覽器提供頁面? 使用什麼樣的技術和流程?

  • 優雅的降級:爲現代瀏覽器構建應用,同時確保它在舊版瀏覽器中正常運行。
  • Progressive enhancement - The practice of building an application for a base level of user experience, but adding functional enhancements when a browser supports it.
  • 漸進式增強:構建基於用戶體驗的應用,但在瀏覽器支持時添加新增功能。
  • 利用 caniuse.com 檢查特性支持。
  • 使用 autoprefixer 自動生成 CSS 屬性前綴。
  • 使用 Modernizr進行特性檢測。

有什麼不同的方式可以隱藏內容(使其僅適用於屏幕閱讀器)?

這些方法與可訪問性(a11y)有關。

  • visibility: hidden:元素仍然在頁面流中,並佔用空間。
  • width: 0; height: 0:使元素不佔用屏幕上的任何空間,導致不顯示它。
  • position: absolute; left: -99999px: 將它置於屏幕之外。
  • text-indent: -9999px:這隻適用於block元素中的文本。
  • Metadata: 例如通過使用 Schema.org,RDF 和 JSON-LD。
  • WAI-ARIA:如何增加網頁可訪問性的 W3C 技術規範。

即使 WAI-ARIA 是理想的解決方案,我也會採用絕對定位方法,因爲它具有最少的注意事項,適用於大多數元素,而且使用起來非常簡單。

參考

除了screen,你還能說出一個 @media 屬性的例子嗎?

  • all

    適用於所有設備。
  • print

    爲了加載合適的文檔到當前使用的可視窗口. 需要提前諮詢 paged media(媒體屏幕尺寸), 以滿足個別設備網頁尺寸不匹配等問題。
  • screen

    主要適用於彩色的電腦屏幕
  • speech

    解析speech這個合成器. 注意: CSS2已經有一個相似的媒體類型叫aural.

    https://developer.mozilla.org/zh-CN/docs/Web/CSS/@media

編寫高效的 CSS 應該注意什麼?

首先,瀏覽器從最右邊的選擇器,即關鍵選擇器(key selector),向左依次匹配。根據關鍵選擇器,瀏覽器從 DOM 中篩選出元素,然後向上遍歷被選元素的父元素,判斷是否匹配。選擇器匹配語句鏈越短,瀏覽器的匹配速度越快。避免使用標籤和通用選擇器作爲關鍵選擇器,因爲它們會匹配大量的元素,瀏覽器必須要進行大量的工作,去判斷這些元素的父元素們是否匹配。

BEM (Block Element Modifier) methodology recommends that everything has a single class, and, where you need hierarchy, that gets baked into the name of the class as well, this naturally makes the selector efficient and easy to override.
BEM (Block Element Modifier)原則上建議爲獨立的 CSS 類命名,並且在需要層級關係時,將關係也體現在命名中,這自然會使選擇器高效且易於覆蓋。

搞清楚哪些 CSS 屬性會觸發重新佈局(reflow)、重繪(repaint)和合成(compositing)。在寫樣式時,避免觸發重新佈局的可能。

參考

使用 CSS 預處理的優缺點分別是什麼?

優點:

  • 提高 CSS 可維護性。
  • 易於編寫嵌套選擇器。
  • 引入變量,增添主題功能。可以在不同的項目中共享主題文件。
  • 通過混合(Mixins)生成重複的 CSS。
  • Splitting your code into multiple files. CSS files can be split up too but doing so will require a HTTP request to download each CSS file.
  • 將代碼分割成多個文件。不進行預處理的 CSS,雖然也可以分割成多個文件,但需要建立多個 HTTP 請求加載這些文件。

缺點:

  • 需要預處理工具。
  • 重新編譯的時間可能會很慢。

對於你使用過的 CSS 預處理,說說喜歡和不喜歡的地方?

喜歡:

  • 絕大部分優點上題以及提過。
  • Less 用 JavaScript 實現,與 NodeJS 高度結合。

Dislikes:

  • 我通過node-sass使用 Sass,它用 C ++ 編寫的 LibSass 綁定。在 Node 版本切換時,我必須經常重新編譯。
  • Less 中,變量名稱以@作爲前綴,容易與 CSS 關鍵字混淆,如@media@import@font-face

如何實現一個使用非標準字體的網頁設計?

使用@font-face併爲不同的font-weight定義font-family

解釋瀏覽器如何確定哪些元素與 CSS 選擇器匹配。

這部分與上面關於編寫高效的 CSS 有關。瀏覽器從最右邊的選擇器(關鍵選擇器)根據關鍵選擇器,瀏覽器從 DOM 中篩選出元素,然後向上遍歷被選元素的父元素,判斷是否匹配。選擇器匹配語句鏈越短,瀏覽器的匹配速度越快。

例如,對於形如p span的選擇器,瀏覽器首先找到所有<span>元素,並遍歷它的父元素直到根元素以找到<p>元素。對於特定的<span>,只要找到一個<p>,就知道'<span>`已經匹配並停止繼續匹配。

參考

描述僞元素及其用途。

CSS 僞元素是添加到選擇器的關鍵字,去選擇元素的特定部分。它們可以用於裝飾(:first-line:first-letter)或將元素添加到標記中(與 content:...組合),而不必修改標記(:before:after)。

  • :first-line:first-letter可以用來修飾文字。
  • 上面提到的.clearfix方法中,使用clear: both來添加不佔空間的元素。
  • 使用:beforeafter展示提示中的三角箭頭。鼓勵關注點分離,因爲三角被視爲樣式的一部分,而不是真正的 DOM。如果不使用額外的 HTML 元素,只用 CSS 樣式繪製三角形是不太可能的。
參考

說說你對盒模型的理解,以及如何告知瀏覽器使用不同的盒模型渲染布局。

CSS 盒模型描述了以文檔樹中的元素而生成的矩形框,並根據排版模式進行佈局。每個盒子都有一個內容區域(例如文本,圖像等)以及周圍可選的paddingbordermargin區域。

CSS 盒模型負責計算:

  • 塊級元素佔用多少空間。
  • 邊框是否重疊,邊距是否合併。
  • 盒子的尺寸。

盒模型有以下規則:

  • 塊級元素的大小由widthheightpaddingbordermargin決定。
  • 如果沒有指定height,則塊級元素的高度等於其包含子元素的內容高度加上padding(除非有浮動元素,請參閱下文)。
  • 如果沒有指定width,則非浮動塊級元素的寬度等於其父元素的寬度減去父元素的padding
  • 元素的height是由內容的height來計算的。
  • 元素的width是由內容的width來計算的。
  • 默認情況下,paddingborder不是元素widthheight的組成部分。
參考

* { box-sizing: border-box; }會產生怎樣的效果?

  • 元素默認應用了box-sizing: content-box,元素的寬高只會決定內容(content)的大小。
  • box-sizing: border-box改變計算元素widthheight的方式,borderpadding的大小也將計算在內。
  • 元素的height = 內容(content)的高度 + 垂直方向的padding + 垂直方向border的寬度
  • 元素的width = 內容(content)的寬度 + 水平方向的padding + 水平方向border的寬度

display的屬性值都有哪些?

  • none, block, inline, inline-block, table, table-row, table-cell, list-item.

TODO

inlineinline-block有什麼區別?

我把block也加入其中,爲了獲得更好的比較。

block inline-block inline
大小 填充其父容器的寬度。 取決於內容。 取決於內容。
定位 從新的一行開始,並且不允許旁邊有 HTML 元素(除非是float 與其他內容一起流動,並允許旁邊有其他元素。 與其他內容一起流動,並允許旁邊有其他元素。
能否設置widthheight 不能。 設置會被忽略。
可以使用vertical-align對齊 不可以 可以 可以
邊距(margin)和填充(padding) 各個方向都存在 各個方向都存在 只有水平方向存在。垂直方向會被忽略。 儘管borderpaddingcontent周圍,但垂直方向上的空間取決於'line-height'
浮動(float) - - 就像一個block元素,可以設置垂直邊距和填充。

relativefixedabsolutestatic四種定位有什麼區別?

經過定位的元素,其position屬性值必然是relativeabsolutefixedsticky

  • static:默認定位屬性值。該關鍵字指定元素使用正常的佈局行爲,即元素在文檔常規流中當前的佈局位置。此時 top, right, bottom, left 和 z-index 屬性無效。
  • relative:該關鍵字下,元素先放置在未添加定位時的位置,再在不改變頁面佈局的前提下調整元素位置(因此會在此元素未添加定位時所在位置留下空白)。
  • absolute:不爲元素預留空間,通過指定元素相對於最近的非 static 定位祖先元素的偏移,來確定元素位置。絕對定位的元素可以設置外邊距(margins),且不會與其他邊距合併。
  • fixed:不爲元素預留空間,而是通過指定元素相對於屏幕視口(viewport)的位置來指定元素位置。元素的位置在屏幕滾動時不會改變。打印時,元素會出現在的每頁的固定位置。fixed 屬性會創建新的層疊上下文。當元素祖先的 transform 屬性非 none 時,容器由視口改爲該祖先。
  • sticky:盒位置根據正常流計算(這稱爲正常流動中的位置),然後相對於該元素在流中的 flow root(BFC)和 containing block(最近的塊級祖先元素)定位。在所有情況下(即便被定位元素爲 table 時),該元素定位均不對後續元素造成影響。當元素 B 被粘性定位時,後續元素的位置仍按照 B 未定位時的位置來確定。position: stickytable 元素的效果與 position: relative 相同。
參考

你使用過哪些現有的 CSS 框架?你是如何改進它們的?

  • Bootstrap: 更新週期緩慢。Bootstrap 4 已經處於 alpha 版本將近兩年了。添加了在頁面中廣泛使用的微調按鈕組件。
  • Semantic UI:源代碼結構使得自定義主題很難理解。非常規主題系統的使用體驗很差。外部庫的路徑需要硬編碼(hard code)配置。變量重新賦值沒有 Bootstrap 設計得好。
  • Bulma: 需要很多非語義的類和標記,顯得很多餘。不向後兼容,以至於升級版本後,會破壞應用的正常運行。

你瞭解 CSS Flexbox 和 Grid 嗎?

瞭解。Flexbox 主要用於一維佈局,而 Grid 則用於二維佈局。

Flexbox 解決了 CSS 中的許多常見問題,例如容器中元素的垂直居中,粘性定位(sticky)的頁腳等。Bootstrap 和 Bulma 基於 Flexbox,這是創建佈局的推薦方式。我之前曾使用過 Flexbox,但在使用flex-grow時遇到了一些瀏覽器不兼容問題(Safari),我必須使用inline-blocks和手動計算百分比寬度,來重寫我的代碼,這種體驗不是很好。

Grid 創建基於柵格的佈局,是迄今爲止最直觀的方法(最好是!),但目前瀏覽器支持並不廣泛。

參考

請解釋在編寫網站時,響應式與移動優先的區別。

TODO

響應式設計與自適應設計有何不同?

響應式設計和自適應設計都以提高不同設備間的用戶體驗爲目標,根據視窗大小、分辨率、使用環境和控制方式等參數進行優化調整。

響應式設計的適應性原則:網站應該憑藉一份代碼,在各種設備上都有良好的顯示和使用效果。響應式網站通過使用媒體查詢,自適應柵格和響應式圖片,基於多種因素進行變化,創造出優良的用戶體驗。就像一個球通過膨脹和收縮,來適應不同大小的籃圈。

自適應設計更像是漸進式增強的現代解釋。與響應式設計單一地去適配不同,自適應設計通過檢測設備和其他特徵,從早已定義好的一系列視窗大小和其他特性中,選出最恰當的功能和佈局。與使用一個球去穿過各種的籃筐不同,自適應設計允許使用多個球,然後根據不同的籃筐大小,去選擇最合適的一個。

參考

你有沒有使用過視網膜分辨率的圖形?當中使用什麼技術?

我傾向於使用更高分辨率的圖形(顯示尺寸的兩倍)來處理視網膜顯示。更好的方法是使用媒體查詢,像@media only screen and (min-device-pixel-ratio: 2) { ... },然後改變background-image

對於圖標類的圖形,我會儘可能使用 svg 和圖標字體,因爲它們在任何分辨率下,都能被渲染得十分清晰。

還有一種方法是,在檢查了window.devicePixelRatio的值後,利用 JavaScript 將<img>src屬性修改,用更高分辨率的版本進行替換。

參考

什麼情況下,用translate()而不用絕對定位?什麼時候,情況相反。

translate()transform的一個值。改變transformopacity不會觸發瀏覽器重新佈局(reflow)或重繪(repaint),只會觸發複合(compositions)。而改變絕對定位會觸發重新佈局,進而觸發重繪和複合。transform使瀏覽器爲元素創建一個 GPU 圖層,但改變絕對定位會使用到 CPU。 因此translate()更高效,可以縮短平滑動畫的繪製時間。

當使用translate()時,元素仍然佔據其原始空間(有點像position:relative),這與改變絕對定位不同。

參考

其他答案

行內元素、塊級元素區別

行內元素:和其他元素都在一行上,高度、行高及外邊距和內邊距都不可改變,文字圖片的寬度不可改變,只能容納文本或者其他行內元素;其中img是行元素

塊級元素:總是在新行上開始,高度、行高及外邊距和內邊距都可控制,可以容納內斂元素和其他元素;行元素轉換爲塊級元素方式:display:block;

一邊固定寬度一邊寬度自適應

可以使用flex佈局 複製下面的HTML和CSS代碼 用瀏覽器打開可以看到效果

<div class="wrap">
  <div class="div1"></div>
  <div class="div2"></div>
</div>

.wrap {
  display: flex;
  justify-content: space-between;
}
.div1 {
  min-width: 200px;
}
.div2 {
  width: 100%;
  background: #e6e6e6;
}
html,
body,
div {
  height: 100%;
  margin: 0;
}

水平垂直居中的方式

flex

// 父容器
display: flex;
justify-content: center;
align-items: center;

position

// 父容器
position: relative;

// 子容器
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;

position+transform

// 父容器
position: relative;

// 子容器
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

table-cell

<div class="box">
    <div class="content">
        <div class="inner"></div>
    </div>
</div>

html, body {
    height: 100%;
    width: 100%;
    margin: 0;
}
.box {
    display: table;
    height: 100%;
    width: 100%;
}
.content {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}
.inner {
    background-color: #000;
    display: inline-block;
    width: 200px;
    height: 200px;
}

回到頂部

display:none、visibile:hidden、opacity:0的區別

是否隱藏 是否在文檔中佔用空間 是否會觸發事件
display: none
visibile: hidden
opacity: 0

回到頂部

CSS中link和@import的區別

  • link屬於HTML標籤,而@import是CSS提供的
  • 頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
  • import只在IE5以上才能識別,而link是HTML標籤,無兼容問題
  • link方式的樣式的權重 高於@import的權重

回到頂部

如何用css實現瀑布流佈局

利用column-count和break-inside這兩個CSS3屬性即可,複製如下代碼即可察看效果

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body {
            margin: 0;
        }
        .waterfall-container {
            /*分幾列*/
            column-count: 2;
            width: 100%;
            /* 列間距 */
            column-gap: 10px;
        }

        .waterfall-item {
            break-inside: avoid;
            width: 100%;
            height: 100px;
            margin-bottom: 10px;
            background: #ddd;
            column-gap: 0;
            text-align: center;
            color: #fff;
            font-size: 40px;
        }
    </style>
</head>
<body>
    <div class="waterfall-container">
        <div class="waterfall-item" style="height: 100px">1</div>
        <div class="waterfall-item" style="height: 300px">2</div>
        <div class="waterfall-item" style="height: 400px">3</div>
        <div class="waterfall-item" style="height: 100px">4</div>
        <div class="waterfall-item" style="height: 300px">5</div>
        <div class="waterfall-item" style="height: 600px">6</div>
        <div class="waterfall-item" style="height: 400px">7</div>
        <div class="waterfall-item" style="height: 300px">8</div>
        <div class="waterfall-item" style="height: 700px">9</div>
        <div class="waterfall-item" style="height: 100px">10</div>
    </div>
</body>
</html>

回到頂部

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章