1. CSS選擇器及其優先級
!important > 行內樣式 > id選擇器 > 類/偽類/屬性選擇器 > 標簽/偽元素選擇器 > 子/后臺選擇器 > *通配符
2. 重排和重繪是什么?瀏覽器的渲染機制是什么?
重排(回流):當增加或刪除dom節點,或者給元素修改寬高時,會改變頁面布局,那么就會重新構造dom樹,然后再次渲染。
重繪:計算好盒模型的位置,大小和其他一些屬性之后,瀏覽器就會根據每個盒模型的特性進行繪制。
瀏覽器的渲染機制:當dom的大小,位置發生改變時進行重排,當dom的樣式如color、background-color
改變時進行重繪。
3. display有哪些屬性值
屬性值 | 作用 |
---|---|
none | 元素不顯示,并且會從文檔流中移除 |
block | 塊類型,默認寬度為父元素寬度,可設置寬高,換行顯示 |
inline | 行內元素類型,默認寬度為內容寬度,不可設置寬高,同行顯示 |
inline-block | 默認寬度為內容寬度,可設置寬高,同行顯示 |
table | 此元素會作為塊級表格來顯示,子元素可設置display:table-row、table-cell 等 |
flex | flex布局 |
grid | 網格布局 |
inherit | 規定應該從父元素繼承display屬性的值 |
網格布局筆記:網格布局
表格布局可以看下面代碼:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {padding: 0;margin: 0;}.table {display: table; /* 表格 */width: 800px;height: 500px;margin: 20px auto;border: 3px solid #000;}.row {display: table-row; /* 表格行 */}.cell {display: table-cell; /* 表格單元 */border: 1px solid #000;}</style>
</head><body><div class="table"><div class="row"><div class="cell">1</div><div class="cell">2</div><div class="cell">3</div></div><div class="row"><div class="cell">4</div><div class="cell">5</div><div class="cell">6</div></div></div>
</body></html>
結果如下:
4. display的block、inline和inline-block的區別
block
:獨占一行,寬度繼承至父盒子,多個元素會另起一行,可設置寬高以及margin
和padding
屬性。
inline
:元素不會獨占一行,寬度、高度由內容撐開,不可設置寬高,但可以設置水平方向的margin
和padding
。
inline-block
:行內塊,將對象設置為inline對象,但對象的內容作為block對象呈現,也就是說內容排列在一行內顯示,但是可以設置寬高。
5. 隱藏的元素的方法有哪些
- display: none
- visibility: hidden
- opacity: 0
- position: absolute 移到可視區之外
- z-index: 負值 定位的前提下,使其他元素蓋住該元素,以此實現隱藏
- transform:scale(0, 0) 將元素縮放為0,來實現元素的隱藏,元素仍占據位置。
6. link和@import的區別
兩者都是外部引用css的方式,他們的區別如下:
- 功能上:link是XHTML標簽,除了加載CSS外,還可以定義RSS等其他事務,@import屬于CSS范疇,只能加載CSS
- 效果上:link引用CSS時,在頁面載入時同時加載;@import需要頁面網頁完全載入以后加載
- 兼容性上:link是XHTML標簽,沒有兼容性問題;@import是CSS2.1提出的,低版本瀏覽器不支持
- js支持上:link支持使用js控制dom去改變樣式;而@import不支持
7. transition和animation的區別
- transition是過渡屬性,強調過渡,它的實現需要觸發一個事件(比如鼠標移動上去,焦點,點擊等)才執行動畫,類似于flash的補間動畫,設置一個開始關鍵幀,一個結束關鍵幀
- animation是動畫屬性,它的實現不需要觸發事件,設定好時間之后可以自己執行,且可以循環一個動畫,它也類似于flash的補間動畫,但是它可以設置多個關鍵幀(用@keyframe定義)完成動畫。
8. display:none和visibility:hidden的區別
- 渲染樹上:display:none會讓元素從渲染樹中消失,渲染時不會占據任何空間,visibility:hidden會占據空間,只是不可見
- 是否是繼承屬性:display是非繼承屬性,子孫節點會隨父節點消失,修改顯示子孫節點的屬性也無法顯示,而visibility是繼承屬性,子孫節點消失是因為子孫節點從父節點繼承了hidden,通過設置子孫節點visibility:visible可以讓子孫節點顯示。
- 重排與重繪:修改常規文檔流的display通常會造成文檔的重排,但是修改visibility只會造成重繪
- 讀屏器:如果使用讀屏器,設置display:none的內容不會被讀取,而visibility:hidden可以被讀取
9. li與li之間有看不見的空白間隔是什么原因引起的?如何解決?
li原本是塊級標簽,如下圖
但當li設置為行內塊元素或行元素時,li標簽與li標簽之間會有看不見的空隙,如下圖:
原因:當元素是行內元素/行內塊元素排版時,瀏覽器會將元素之間的空白符,如空格,換行,tab等渲染成一個空格處理,上圖的換行就被渲染成了空格,因此會有上面的結果。
解決方案:
- li設置為float:left,缺點:很多容器是不適合設置浮動,并且浮動會將display變為block。
- 將所有li寫在一行,比較簡單粗暴的方法,但是代碼會不太美觀
- ul內的字符尺寸設置為0,缺點:可能會影響到其他字符,其他字符需要額外重新設置font-size
- 設置ul的字符間隔letter-spacing: -8px,缺點跟上條一樣
10. 什么是物理像素、邏輯像素、像素密度,為什么移動端開發要用到@2x、@3x的圖片
物理像素(physical pixel):又叫設備像素,是顯示屏幕上的實際物理點,它是顯示設備的最小可控制單元,我們常說的1920×1080像素分辨率就是用的物理像素。
邏輯像素(device independent pixel):又叫設備獨立像素,與設備無關的邏輯像素,代表可以通過程序控制使用的虛擬像素,是一個總體概念,包含了css像素。
邏輯像素就是在物理像素的基礎上人為定義的一層邏輯像素,舉個例子,一個屏幕的物理像素是2560×1440,但是我們可以人為的定義定義這個屏幕就是1280×720,所以1個邏輯像素就用4個設備像素顯示。
傳統的pc屏幕,1個邏輯像素就等于1個物理像素,但是市面上有很多高清屏幕,比如蘋果的Retina屏幕,高清就是因為這種屏幕1個邏輯像素點使用多個物理像素顯示,所以高清屏的畫質就更加銳利,沒有顆粒感,顯示效果出眾。
像素密度通常使用dpr(設備像素比device pixel ratio)來表示,dpr = 物理像素 / 邏輯像素,傳統的pc屏幕dpr是1,像上面所的蘋果Retina高清屏幕dpr是2。簡單來說,設備像素比dpr的意義在于規定設備以多少個物理像素來顯示1px的css像素。
@2x、@3x在移動端開發中,不同設備有不同的dpr,為了確保在不同設備上顯示的圖像保持一致的視覺效果,引入了倍圖的概念,其中@2x和@3x是兩個常見的倍圖標識。
為什么Retina上使用@1x的圖片會模糊?
舉個例子,一張375px*200px
的一倍位圖,其擁有375*200=75000
個位圖像素,如果我們在常規pc屏(dpr=1)上看這張圖,將會以375*200=75000
個物理像素來顯示,因此在pc上顯示的清晰度不變。那么,如果在Retina屏(dpr=2)上預覽這張圖片,將會以375*200*4=300000
個物理像素來顯示這張圖片,而實際上這張一倍位圖轉換成物理像素只有375*200=75000
個有效物理像素,不足以填充300000
個物理像素,因此剩下的300000-75000=225000
個物理像素將采用就近取色的填充的方法來顯示圖片,這也是造成圖片模糊的原因,下面這張圖片解釋的十分形象:
因此使用375px*200px
的二倍圖,在Retina(dpr=2)屏上會轉換為375*200*4=300000
個物理像素來正常填充300000
個物理像素,才不會出現圖片模糊的情況。
瀏覽器打開控制臺,輸入:devicePixelRatio
后回車,可以查看當前屏幕的dpr。
11. 談談你對CSSSprites的理解
CSSSprites精靈圖,將一個頁面涉及到的所有圖片都包含到一張大圖中去,然后利用CSS的background-image,background-repeat,background-position
屬性進行背景定位。
優點:
- 性能方面:能夠很好的減少網頁的http請求,從而大大提高了頁面的性能,這是最大的優點。
- 存儲方面:能減少圖片的字節,把3張圖片合成1張圖片的字節總是小于這3張圖片的字節總和。
缺點:
- 設計方面:在圖片合并時,要把多張圖片有序、合理的合并成一張圖片,還要留好足夠的空間,防止板塊內出現不必要的背景,相對麻煩
- 程序猿開發方面:雪碧圖在開發的時候相對來說麻煩,需要借助photoshop或其他工具來對每個背景單元測量其準確的位置
- 維護方面:維護就更麻煩了,頁面背景有少許改動就要改這整個合并的圖片,很容易影響無需改動的地方,如果在原來的地方放不下,就只能往下加圖片,這樣圖片的字節增加了,還要改動css。
12. CSS優化和提高性能的方法有哪些?
加載性能
- css單一樣式:舉個例子,當需要使用下邊距和左邊距的時候,推薦使用
margin-bottom:10px;margin-left:10px;
,而不是margin: 0 0 10px 10px
,因為前者執行效率會更高。 - 減少使用
@import
,建議使用link
標簽,因為link標簽引入css資源時,會在頁面加載時一起加載,而@import
需要等待頁面加載完成后再進行加載,也就是說link是并行加載的,而@import是串行加載的,因此使用link加載性能更好。 - css壓縮:將寫好的css進行打包壓縮,可以減小文件體積。
選擇器性能
- 如果規則擁有ID選擇器作為其關鍵選擇器(選擇器的最后面的部分為關鍵選擇器,即用來匹配目標元素的部分),則不要為規則增加其他標簽,這樣就能過濾掉無法規則,樣式系統就不會浪費時間去匹配它們了
- 避免使用通配符*規則,因為
*{}
計算次數驚人,只對需要用到的元素進行選擇就行 - 盡量少的去對標簽進行選擇,而是用class,使用標簽計算量太大了
- 了解哪些屬性是可以通過繼承而來的,然后避免對這些屬性重復指定規則
渲染性能
- 慎重使用高性能屬性:浮動、定位
- 盡量減少頁面的重排和重繪
- 去除空規則,減少css文檔體積
- 不使用@import,它會影響css的加載速度
- 合理使用雪碧圖
可維護性、健壯性
- 將具有相同屬性的樣式抽離出來,整合并通過class在頁面中使用,提高css的可維護性
- 樣式與內容分離,將css代碼定義到外部css中
13. CSS預處理用過嗎
如less,sass,它們為css增加了一些編程特性,可以在css中使用變量,簡單的邏輯程序等。層級,混入mixin,變量,循環,函數等對編寫以及開發ui組件都極為方便
優點:
- 結構清晰,便于擴展
- 可以輕松實現多重繼承
- 完美兼容css代碼,可以用在老項目中
- 可以很方便的屏蔽瀏覽器私有語法的差異
14. 談談你對媒體查詢的理解
媒體查詢(media queries)是一種css3的技術,用于根據設備的特性和屬性來應用不同的樣式規則,通過媒體查詢,可以使網頁在不同的設備上或不同的瀏覽器條件下采用不同的樣式表,從而實現響應式設計,提供更好的用戶體驗。
link元素中使用css媒體查詢
當視口寬度小于等于800px時應用的樣式
<link ref="stylesheet" media="(max-width: 800px)" href="example.css"/>
樣式表中使用css媒體查詢
-
媒體類型(media type):指定樣式規則適用的設備類型,如all:適用于所有設備,screen:適用于屏幕(電腦、平板、手機等),print:適用于打印機和打印機預覽,speech:適用于語音設備(屏幕閱讀器等),默認是all
@media screen {/* 樣式規則適用于屏幕設備 *//* ... */ }
-
媒體特性(media feature):包括視口寬度、設備寬度、分辨率等,用于根據設備屬性應用樣式。
@media screen and (max-width: 600px) {/* 當視口寬度小于等于600px時應用的樣式 *//* ... */ }
-
邏輯運算符:可以使用邏輯運算符如
and or not
來組合多個媒體查詢條件@media (min-width: 600px) and (max-width: 1200px) {/* 當視口寬度在600px~1200px的范圍內應用的樣式 *//* ... */ }
15. 常用頁面布局的代碼實現
1. 兩欄布局
一般的兩欄布局指的是左邊一欄寬度固定,右邊一欄寬度自適應。
實現方法1:利用浮動,左邊盒子設置寬度,并設置向左浮動,右邊盒子使用margin-left左邊盒子寬度,寬度設不用設置,因為block盒子默認寬度為auto自動撐滿父盒子
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;}.left {/* 核心代碼 */float: left;width: 100px;height: 100%;background-color: tomato;}.right {/* 核心代碼 */margin-left: 100px;height: 100%;background-color: gold;}
</style>
<body><div class="outer"><div class="left"></div><div class="right"></div></div>
</body>
結果如下:
實現方法2:使用flex布局,左側固定寬度,右側設置flex:1
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;/* 核心代碼 */display: flex;}.left {width: 100px;height: 100%;background-color: tomato;}.right {/* 核心代碼 */flex: 1;height: 100%;background-color: gold;}
</style>
實現方法3:利用浮動,左側寬度固定,并左浮動,右側設置overflow:hidden,這樣右邊就觸發了BFC,BFC的區域不會與浮動元素發生重疊,所以兩側就不會發生重疊
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;}.left {float: left;width: 100px;height: 100%;background-color: tomato;}.right {overflow: hidden;height: 100%;background-color: gold;}
</style>
實現方法4:父盒子相對定位,左側盒子絕對定位并固定寬度,右側盒子margin-left左側盒子寬度
或者左側盒子固定寬度,右側盒子絕對定位,并left:左側盒子寬度。
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;position: relative;}.left {position: absolute;width: 100px;height: 100%;background-color: tomato;}.right {margin-left: 100px;height: 100%;background-color: gold;}
</style>
2. 三欄布局(圣杯布局)
三欄布局,又叫圣杯布局,一般指的是頁面中一共有三欄,左右兩欄寬度固定,中間自適應的布局。
方法1:flex布局
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;display: flex;}.left {width: 100px;height: 100%;background-color: tomato;}.right {width: 100px;height: 100%;background-color: gold;}.center {flex: 1;height: 100%;background-color: black;}
</style>
<body><div class="outer"><div class="left"></div><div class="center"></div><div class="right"></div></div>
</body>
方法2:定位,外部盒子設置左右盒子寬度的padding并設置相對定位,左右盒子設置絕對定位,左盒子定位在左,右盒子定位在右
或者外部盒子不設padding,中間盒子設置margin
<style>* {margin: 0;padding: 0;}.outer {height: 100vh;padding: 0 100px;position: relative;}.left {position: absolute;top: 0;left: 0;width: 100px;height: 100%;background-color: tomato;}.right {position: absolute;top: 0;right: 0;width: 100px;height: 100%;background-color: gold;}.center {width: 100%;height: 100%;background-color: black;}
</style>
16. 談談你對BFC的理解,以及如何創建BFC
BFC容器通常是指“塊級格式化上下文容器(Block Formatting Context Container)”,它是CSS中用來管理和控制元素在頁面上布局和排列的一種機制,它會形成獨立的渲染區域,從而使內部元素的渲染不會影響到外界。
下面我們通過例子來簡單理解一下什么叫做內部元素不會影響到外界
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>bfc容器</title><style>img {/* float: left; */}/* .bfc {overflow: hidden;} */</style>
</head>
<body><div class="outer bfc"><img src="./img.png" alt=""><p>這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本這是一段文本</p></div>
</body>
</html>
運行如上代碼可以看到:
我們如何實現文字圍繞圖片渲染呢?
我們可以使用浮動來實現,浮動產生的目的最初就是為了做文字環繞效果,浮動的元素會壓住標準流的盒子,和定位比較像,但是浮動和定位有區別,浮動的元素不會壓住標準流的文字,圖片,而固定定位、決定定位會壓住標準流的所有內容,包括文字及圖片
下面我們來試試浮動的效果:我們取消上述代碼的浮動注釋,得到下面效果:
但是我們打開開發者工具查看頁面元素,會發現一個問題,父盒子的高度并沒有被子元素img撐開,如下圖:
也就是說子元素img高度已經在父盒子外面了,這就是上面所說的內部元素影響到外界,造成這種情況的原因是:對子元素設置浮動后,它脫離了父元素的文檔流,因此父元素高度并不會受這個子元素的影響,這就是常說的高度塌陷問題,我們可以使用BFC容器來解決此問題,下面我們取消上面代碼中bfc類的注釋,再看看結果如下:
可以看到高度塌陷問題得到解決,內部元素將不會影響到父元素以外的元素,它只會影響父元素。
下面我們詳細介紹BFC。
BFC除了擁有內部元素不會影響到外部元素特性,還有許多其他實用的特性,下面匯總了BFC的所有特性:
- BFC是獨立的容器,容器內部的元素不會影響到外部元素
- BFC區域不會與浮動的容器發生重疊
- BFC和文檔流的排列方式一致,垂直方向上,自上而下排列
形成BFC的條件:
-
元素設置overflow:overflow不是visible的值,如hidden,auto,scroll。上面代碼的bfc類就是用的hidden
-
元素設置浮動:float除了none以外的值
-
元素設置定位:position設置absolute或者fixed
-
元素設置display:flex,inline-block,table-cell等
BFC的作用:
-
解決高度塌陷問題(也可以說是清除浮動):在對子元素設置浮動后,父元素會發生高度塌陷,也就是父元素的高度不會被這個設置了浮動的元素撐開。
-
解決margin的重疊問題:由于BFC是一個獨立的區域,內部的元素和外部的元素互不影響,將兩個元素變成兩個BFC,就解決了margin重疊問題。
-
創建自適應的兩欄布局:左邊盒子寬度固定,右邊盒子設置
overflow:hidden
使盒子變成bfc盒子,bfc的區域不會與浮動元素發生重疊,所以兩側不會發生重疊,實現了自適應兩欄布局。.left {width: 100px;height: 200px;background: tomato;float: left; } .right {height: 300px;background: gold;overflow: hidden; } <div class="left"></div> <div class="right"></div>
17. 什么是margin重疊問題?以及如何解決margin重疊問題
兩個塊級元素的上外邊距和下外邊距可能會合并(重疊)為一個外邊距,其大小會取其中外邊距值大的那個(如果兩個邊距都為正值的話),這種結果就是外邊距重疊。另外,margin重疊只會出現在垂直方向上。
需要注意的是:浮動和絕對定位這種脫離文檔流的元素的外邊距不會折疊。
計算原則:
-
如果兩者都是正數,那么就取最大值
-
如果是一正一負,就會取正值減去負值的絕對值
-
兩個都是負值時,用0減去兩個中絕對值大的那個
解決辦法:
對于折疊的情況,主要有兩種:
-
兄弟盒子間重疊(經實測,下面方式只有在兩個margin都為正值時才生效,存在負值不生效)
-
底部元素變成行內盒子:
display:inline-block
【也就是底部盒子變bfc】 -
底部元素設置浮動:
float: left
除了none
【也就是底部盒子變bfc】 -
底部元素設置絕對或固定定位:
position: absolute/fixed
【也就是底部盒子變成bfc】綜上所述,只要把底部盒子變成bfc即可。
-
-
父子盒子間重疊
- 父盒子加入:
overflow: hidden
【即父盒子變bfc】 - 父盒子變成行內盒子:
display: inline-block
【即父盒子變bfc】 - 父盒子增加邊框:
border: 1px solid transparent
- 子盒子變成行內盒子:
display: inline-block
【即子盒子變bfc】 - 子盒子設置定位:
position: absolute/fixed
【即子盒子變bfc】 - 子盒子設置浮動:
float: left
除none
均可【即子盒子變bfc】
- 父盒子加入:
18. absolute與fixed定位的共同點和區別有哪些
共同點:
-
都使文檔脫離文檔流不再占據文檔物理空間
-
都改變行內元素的呈現方式,將
display
自動設置為inline-block
-
覆蓋非定位文檔元素
不同點:
- absolute與fixed的根元素不同,absolute的根元素可以設置,fixed根元素固定為瀏覽器。
- 在有滾動條的頁面,absolute會跟著父元素進行移動,而fixed始終固定在頁面的具體位置。
19. 談談你對sticky定位的理解
粘性定位通俗來說,它就是相對定位relative和固定定位fixed的結合體,在最近可滾動容器沒有觸發滑動之前,sticky盒子的表現為相對定位relative【第一階段】,但當最近可滾動容器觸發滾動,父元素出現在最近可滾動容器的可視區并且滾動距離達到粘性定位sticky的要求時(比如top: 100px),sticky盒子的表現為固定定位fixed【第二階段】,接著滾動,當sticky盒子的父元素消失在最近可滾動容器的可視區時,sticky盒子會重新表現為相對定位relative【第三階段】,也就是說它不再固定,會隨著父元素消失在最近可滾動容器的可視區。
結合上面的描述,我們可以總結粘性定位的位置受兩個東西的影響:
- 父元素:父盒子不在最近可滾動容器可視區時,sticky盒子始終表現為相對定位。
- 最近可滾動的容器:設置sticky時使用的top、left等屬性是相對的就是可滾動的容器,只要容器的overflow不是visible【容器不設置overflow就默認是visible】那么容器就是可滾動容器,如果盒子的祖先們沒找到可滾動容器,那么body就作為可滾動容器,因為body是默認可滾動的。
下面我們結合代碼來理解:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>margin重疊問題</title><style>* {padding: 0;margin: 0;}.parent {width: 400px;height: 600px;background-color: tomato;overflow: visible;}.sticky {width: 200px;height: 200px;background-color: gold;/* 粘性定位 */position: sticky;top: 0px;}.box-top,.box-bot {width: 400px;background-color: pink;}.box-top {height: 200px;}.box-bot {height: 1000px;}</style>
</head><body><div class="box-top"></div><div class="parent"><div class="sticky">吸頂盒子</div></div><div class="box-bot"></div>
</body></html>
sticky失效情況有:
- 未指定top、right、bottom或left其中的一個
- 父元素的高度小于sticky元素
- 沒有找準sticky元素需要參考的最近可滾動元素
- 如果參考的可滾動元素是body,那么父元素的overflow必須是visible,不能是其他任意值
參考博客:position:sticky失效問題剖析
參考視頻:[粘性定位](