掌握這些CSS知識點,Coding如飛!
許多入門學(xué)前端的同學(xué),或是準備面試的同學(xué)都會去死記硬背一些前端知識點,筆者也是這么經(jīng)歷過來的,但卻不推薦這種囫圇吞棗、不求甚解的學(xué)習方式,因為這樣會走很多彎路,屬于“應(yīng)試”學(xué)習,我們更應(yīng)該的是從基礎(chǔ)到復(fù)雜,從表象到原理的角度卻思考學(xué)習,才能熟練掌握技能。
整理了一些在CSS(層疊樣式表)中的知識點,或許你曾看過一些什么“萬字總結(jié)”、“面試必看”,但還是希望更多同學(xué)能夠沉下心來學(xué)習,不僅僅滿足于停留在“API工程師”的層面,多從CSS約定的規(guī)則去解釋現(xiàn)象。
一、width(寬)& height(高)
瀏覽器中,明確了width和height就可以繪制出一塊矩形區(qū)域,也決定(量化)了當前HTML標簽渲染后在屏幕上占據(jù)的有效矩形面積。
1.1 width與height的值
height屬性規(guī)則與width相同。另外max-height、min-height優(yōu)先級大于height,同理max-width和min-width優(yōu)先級大于width。
1.2 height:100%無效
我們有時會在CSS里寫height: 100%,發(fā)現(xiàn)并無效果,如下:
- <div class="block"></div>
- * {
- padding: 0;
- margin: 0;
- border: 0;
- }
- body {
- background-color: green;
- /* height: 100%; */
- border: 5px solid greenyellow;
- }
- .block {
- width: 100%;
- height: 100%;
- background-color: red;
- }
block類 div的高度并未按照我們預(yù)想那樣撐滿全屏高度
高度100%并未鋪滿屏幕
代碼&效果:https://codepen.io/DYBOY/embed/RwoJKRP
block類的父級(包含塊)是body,body在未設(shè)置值的時,height值為auto,body的實際計算高度為內(nèi)容撐開的高度,即為0(可以將上述代碼的border樣式取消注釋,可看到body的高度)
那么子元素block類的高度即等同于0
- body {
- background-color: azure;
- height: auto;
- }
- .block {
- width: 100%;
- height: 0 * 100%; // 0
- background-color: red;
- }
所以此時block類所在的div盒子的高度無效,height為0,即在瀏覽器上無渲染高度 瀏覽器的渲染規(guī)則可理解記憶為:深度優(yōu)先遍歷計算
子元素的相對單位的計算值都是基于父/祖先元素對應(yīng)的屬性值,auto是基于內(nèi)容區(qū)域撐開計算所得。
瀏覽器渲染HTML文檔流,背景色默認為白色,如果文檔中的html、body標簽設(shè)置了背景色,這兩個標簽的背景色實際設(shè)置的是瀏覽器視口的背景色。
二、padding(內(nèi)邊距)& border(邊框)& magin(外邊距)
盒模型可以看作四個“同心矩形”組合而成,如下圖
對于這三個屬性的表現(xiàn)其實并無特別可說明,見上圖可知意。
元素分為行級元素和塊級元素,行級元素的margin和padding的上下值無效。
2.1 百分比單位計算
自己之前一直有個誤區(qū),認為padding、margin的百分比單位的計算基數(shù)是當前元素矩形區(qū)域?qū)捀邅硭?,但是根?jù)包含塊的規(guī)則,他們的計算基數(shù)應(yīng)該是包含塊的width值。
之前團隊里大佬洪巖問:“如何實現(xiàn)一個高度是自適應(yīng)寬度3倍的圖片?”
實現(xiàn)方法1: 利用Chrome瀏覽器最新支持的aspect-ratio屬性,其問題就是C端瀏覽器兼容性不好
- .box {
- aspect-ratio: 1/3; // width/height 寬高比
- }
aspect-ratio效果
實現(xiàn)方法2: 巧用包含塊規(guī)則(padding和width屬性百分比值的計算基數(shù)是包含塊的寬度)+背景圖實現(xiàn)
利用包含塊規(guī)則實現(xiàn)
代碼和演示:https://codepen.io/DYBOY/pen/JjbZgeE
2.2 border-radius百分比和像素
border-radius屬性用于描述邊框圓角半徑,根據(jù)資料如果是百分比單位,則根據(jù)所在**盒子模型的矩形寬和高(包含border和padding)**作為計算基數(shù),border-radius的值描述的是邊框角度所在橢圓的半長軸和半短長軸長度。
border-*-radius屬性的兩個長度或百分比值定義了四分之一橢圓的半徑,該半徑定義了外邊界邊角的形狀(參見下圖)。第一個值為水平半徑,第二個為垂直半徑。如果省略第二個值,則從第一個復(fù)制。如果任一長度為零,則角為正方形,而不是圓角。
水平半徑的百分比是指邊框的寬度,而垂直半徑的百分比是指邊框的高度。
來看下面這個示例:
- <div class="box">1</div>
- <div class="box style1">2</div>
- <div class="box style2">3</div>
- <div class="box style3">4</div>
- * {
- padding: 0;
- margin: 0;
- }
- body {
- background-color: #fff;
- }
- .box {
- position: relative;
- width: 200px;
- height: 200px;
- margin: 10px auto;
- background-color: #00abef;
- border-radius: 100px;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 32px;
- color: #fff;
- }
- .style1 {
- padding: 20px;
- }
- .style2 {
- padding: 20px;
- border-radius: 50%;
- }
- .style3 {
- padding: 20px;
- border-width: 10px;
- box-sizing: border-box;
- }
效果
代碼&演示:https://codepen.io/DYBOY/pen/BaQPaaj
發(fā)現(xiàn)第二個形狀是一個橢圓,其原因是百分比的計算是把所在元素矩形區(qū)域的寬和高作為計算基數(shù),而所在矩形的框高的計算值需要加上padding和border的寬度,所以變成了一個橢圓。那么,是不是把盒模型設(shè)置為IE盒模型就可以避免這個問題了?答案是的,如上代碼的第四個圓形。
- 參考詳細資料:https://www.w3.org/TR/2010/WD-css3-background-20100612/#the-border-radius
利用邊框的橢圓,可以制造平滑的不規(guī)則形狀,例如模仿一個水滴:
運動的水珠
**知識點:**如果沒有設(shè)置border-color,默認邊框顏色為所在元素的文本顏色。
2.3 BFC與margin折疊
BFC是盒模型中在屏幕上渲染展示的矩形區(qū)域,決定了浮動、盒模型渲染交互的區(qū)域。
margin區(qū)域折疊是一個BFC(塊級格式化上下文)的問題,兩個div屬于同一個BFC。父子元素margin-top塌陷,兄弟元素margin重合取較大值。
若想要避免,則需要讓兩個相鄰設(shè)置了margin的元素都變成一個BFC。
創(chuàng)建BFC的常見CSS屬性值?
- 浮動元素,float:left/right/auto
- 定位,position:absolute/fixed
- 展示,display:inline-block/table相關(guān)/flow-root/flex/grid
- flex/grid 的直接子元素為BFC
- table 相關(guān)的比如 table、table-cell、table-caption等
- flow-root最好,無副作用
- 溢出,顯示指明overflow:hidden/auto
- overflow的css計算值不為visiable,也就是指明溢出盒模型交互區(qū)域的處理方式
- html根元素是一個BFC
關(guān)于BFC更詳細的解讀可以參閱:
《可能是最好的BFC解析了...》- https://juejin.cn/post/6960866014384881671
2.3.1 實例&解決方案
2.3.1.1 父子高度塌
父級margin,子級的margin-top無效
高度塌陷
代碼&演示:https://codepen.io/DYBOY/pen/poNxjOP
解決方案:
原因是父子組件的margin-top取最大值,上面例子中父子組件的包含塊都是body,屬于同一個BFC(html標簽)內(nèi)的子元素,因此需要將父/子元素變成BFC(根據(jù)如上的創(chuàng)建BFC的CSS值設(shè)置),那么子元素的margin就會依賴父元素的左上角作為基準點margin偏移。
2.3.1.2 兄弟元素margin取較大值
- <style>
- .box {
- margin: 20px auto;
- background-color: red;
- width: 200px;
- height: 200px;
- }
- </style>
- <div class="box"></div>
- <div class="box"></div>
- <div class="box"></div>
上下相鄰元素的外邊距為20px重合了
解決方案:
想要每兩個盒子的上下邊距為20px*2,則就需要如下處理:
- <style>
- .box-parent {
- overflow: hidden;
- /* display: flow-root; */
- }
- .box {
- margin: 20px auto;
- background-color: red;
- width: 200px;
- height: 200px;
- }
- </style>
- <div class="box-parent">
- <div class="box"></div>
- </div>
- <div class="box-parent">
- <div class="box"></div>
- </div>
- <div class="box-parent">
- <div class="box"></div>
- </div>
推薦解決方案:
由于改變了DOM結(jié)構(gòu),所以不是最好的解決方法,更好的方法就是利用塌陷規(guī)則,增加margin-bottom/margin-top的值,直接計算得到兩塊元素之間的margin,并設(shè)置對應(yīng)值。
三、Containing Block(包含塊)
包含塊內(nèi)容可參閱文章《字節(jié)前端都知道的CSS包含塊規(guī)則》
四、box-sizing(盒模型)
盒子模型包含四部分:外邊距(margin area)、邊框(border area)、內(nèi)邊距(padding area)、內(nèi)容區(qū)(content area),其分布組合如下圖所示。
盒子模型
盒模型有兩種,IE盒模型(border-box)和標準盒模型(content-box),其常用語法如下
- // 默認為標準盒模型
- box-sizing:border-box | content-box
不同的盒模型影響HTML標簽在瀏覽器上實際渲染的屏幕像素面積,該屬性規(guī)定了border和padding屬性值是否占用width和height規(guī)定的內(nèi)容區(qū)。
例如寬度width屬性的值計算規(guī)則如下:
- content-box:width = content width
- border-box:width = content width + padding width + margin width
一言以蔽之,content-box的寬高是規(guī)定內(nèi)容區(qū)寬高,border-box的寬高規(guī)定了content+border+padding三者和的寬高
CSS盒模型
五、position(定位)
關(guān)于定位,必要明確的就是定位的基準點是哪兒?
六、font-size(字號)& line-height(行高)
line-height帶有單位時,計算行高的結(jié)果為line-height高度,line-height規(guī)定的是行高最小的的高度
line-height是相對單位時,line-height具有繼承性,其子元素如果沒有設(shè)置line-height,那么子元素的行高為父元素計算所得的行高值。
line-height值為純數(shù)字時,當前行高會根據(jù)當前文本的 font-size*line-height 計算所得。
七、CSS選擇器
7.1 通用選擇器
- .a.b:(無空格)當a和b在同一標簽類名中同時出現(xiàn)才選擇
- .a .b:(有空格)選擇a的所有后代b
- .a>.b:(>)選擇a的子代b
- .a, .b:(,)a與b樣式相同
- .a+.b:(+)選擇a緊鄰的兄弟b
- .a~.b:(~)有共同父元素,選擇a后的所有b,ab不必緊鄰
7.2 屬性選擇器:
- [attr]:表示帶有以attr命名的屬性的元素。
- [attr=value]:表示帶有以attr命名的屬性,且屬性值為value的元素。
- [attr~=value]:表示帶有以attr命名的屬性的元素,并且該屬性是一個以空格作為分隔符的值列表,其中至少有一個值為value。
- [attr|=value]:表示帶有以attr命名的屬性的元素,屬性值為“value”或是以“value-”為前綴("-"為連字符,Unicode 編碼為 U+002D)開頭。典型的應(yīng)用場景是用來匹配語言簡寫代碼(如 zh-CN,zh-TW 可以用 zh 作為 value)。
- [attr^=value]:表示帶有以attr命名的屬性,且屬性值是以value開頭的元素。
- [attr$=value]:表示帶有以attr命名的屬性,且屬性值是以value結(jié)尾的元素。
- [attr*=value]:表示帶有以attr命名的屬性,且屬性值至少包含一個 value 值的元素。
7.3 偽類選擇器
:root :文檔根元素
八、文本處理
- font-stretch: normal;
- font-kerning: normal;
- text-rendering: optimizeLegibility;
文本是最基礎(chǔ)最重要的功能之一,深入了解文本的渲染布局非常有必要。
關(guān)于文本處理相關(guān)的CSS,知識點較多且深,因此將在后續(xù)文章將詳細解讀,因為文字處理屬于一個需要深入理解的領(lǐng)域,也是一個基礎(chǔ)領(lǐng)域,在大部分的場景我們是不需要關(guān)心,但是如果涉及到精細化展示、兼容性的問題,就不得不涉及到文本渲染原理相關(guān)內(nèi)容。
九、flex布局
- .box {
- display: flex; /* 還可以設(shè)置行內(nèi)元素的 inline-flex */
- flex-direction: row; /* 主軸水平?。簉ow:列(左至右);row-reverse:列(右至左) 主軸豎直!cloumn:行(上至下);column-reverse:行(下至上) */
- flex-wrap: nowrap; /* 一行放不下的時候:nowrap不換行,wrap換行,wrap-reverse換行第一行在下方 */
- /* flex-flow: row nowrap; 是上面兩者的簡寫形式 */
- justify-content: flex-start; /* 定義項目在主軸上的對齊方式 flex-start左側(cè),flex-end右側(cè),center居中,space-between兩端對齊項目間隔相等,space-around項目左右兩側(cè)間距相同 */
- align-items: flex-start; /* 定義項目在縱軸上的對齊方式 flex-start上,flex-end下,center居中,baseline項目中第一行文字對齊,stretch默認值高度未設(shè)置時候?qū)螡M容器高度 */
- }
- .item {
- order: 0; /* 定義項目的排列順序,數(shù)值越小越靠前,默認0 */
- flex-grow: 0; /* 定義剩于空間的放大比例,默認0不放大,如果多個item均為1,則將等分剩于的空間,不同值按照比例分配剩于空間 */
- flex-shrink: 1; /* 定義項目縮小比例,默認為1,空間不足,均等比例縮小,為0則不縮小 */
- flex-basis: auto; /* 定義項目在分配剩于主軸空間之前的主軸占據(jù)的長度,瀏覽器會根據(jù)這個屬性去計算是否有剩于的空間 */
- /* flex: auto; 是flex-grow、flex-shrink和flex-basis的簡寫默認值:0 1 auto */
- align-self: flex-start; /* 設(shè)置單個項目與其他項目不一樣的對齊方式,可覆蓋父容器設(shè)置的align-items,默認auto繼承父元素的align-items值 auto | flex-start | flex-end | center | baseline | stretch */
- }
上述是筆者對flex使用經(jīng)驗的一些精簡總結(jié),另外推薦大家閱讀《Flexbox布局中不為人知的細節(jié) - Alibaba F2E》,從原理層解讀,研讀完非常受用。
十、自定義CSS屬性
example:
- html {
- --theme-color: red;
- --theme-font-size: 16px;
- }
- .example {
- color: var(--theme-color);
- font-size: var(--theme-font-size);
- }
因為是新的屬性規(guī)則,在低版本設(shè)備上可能遇上不兼容情況,因此可以使用查詢特性的@supports()
- @supports(color: var(--theme-color)) {
- // 支持上面的的處理方式則下面的css將生效
- .class-box {
- color: var(--theme-color);
- }
- }
- // 對于selector的支持不好
- @supports not (color: var(--theme-color)) {
- // 不支持上面的的處理方式則下面的css將生效
- .class-box {
- color: red;
- }
- }
兼容性:https://caniuse.com/?search=%40supports
@support文檔:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@supports
總結(jié)
上述講到了十個大的CSS知識點,也是工作開發(fā)過程中經(jīng)常會遇到的細節(jié)問題,把這些知識點/CSS規(guī)則熟記于心,有利于高效率編寫前端樣式!
參考資料&推薦閱讀
《Everything About Auto in CSS》 - https://ishadeed.com/article/auto-css/
《HTML vs Body: How to Set Width and Height for Full Page Size》 - https://www.freecodecamp.org/news/html-page-width-height/
《position - MDN》 - https://developer.mozilla.org/zh-CN/docs/Web/CSS/position