《css世界》筆記
何爲“流”?
“流”是CSS世界中的基本定位和佈局機制;
CSS世界構建的基石是HTML, html最具代表性的兩個基石塊級元素<div>, 內聯元素<span>。
流體佈局: 就是利用元素“流”的特性實現的各類佈局效果,因爲“流”本身具有自適應特性。
流體佈局是自適應佈局(凡是具有自適應特性的佈局統稱)的一種實現,例如表格佈局設置爲100%以後是自適應的,但他不是流體佈局(表格和流不是一路的)
注意: “流”的特性對<table>不起作用
“流”如何影響CSS?
- css的基石是html,只要讓html默認表現符合“流”,整個css世界就被“流”統治
- 特殊佈局與“流”的破壞
- 流向的改變,文檔流默認是從左到右從上到下,這個流向是可以改變的
流、元素和基本尺寸
一、塊級元素
<div>、<li>、<table>
“塊級元素”和“display: block”的元素不是一個概念;
div是display:block;
li是display: list-item;
table是display: table;
之所以都是塊級元素,是因爲他們符合塊級元素的基本特性
特性:一個水平流上只能單獨顯示一個元素,多個塊級元素換行顯示。所以可以通過僞元素+塊級元素配合清除浮動
二、爲什麼display:inline-block既可以一行顯示也可以設置width/height?
css裏每個元素都有兩個盒子: 外在盒子(控制一行顯示還是換行)和容器盒子(負責寬高,內容呈現等)
根據display的屬性值不同, 元素的盒子組成如下:
display:block; 外在的“塊級盒子” + 內在的“塊級容器盒子”
display: inline-block; 外在的“內聯盒子” + 內在的“塊級容器盒子”
display: inline; 外在的“內聯盒子” + 內在的“內聯容器盒子”
綜上:display: inline-block的元素,外在盒子控制一行顯示,內在容器盒子可以設置寬高。
三、width/height的作用細節
由上得知:元素都由外在盒子和容器盒子組成,容器盒子負責寬高,內容等的呈現。所以我們css裏設置的width/height實際上都是作用在內在容器盒子上的。
width:默認值是auto時,元素有以下4個特性:
- 充分利用空間;<div><p>元素的寬度默認是100%於父級容器。
對應的是width/height: -webkit-fill-available
- 收縮和包裹;元素設爲浮動,絕對定位,inline-block, table時,表現爲包裹性
對應的是css3裏的width: fit-content
- 收縮到最小;元素超過容器寬度時,這個時候元素的尺寸由內部元素決定,因爲元素有自己的最小寬度,例如漢字因爲可以任意處斷行,此時就是一個漢字的寬度。英文單詞不能斷,所以最小寬度就是一個英文單詞的寬度。
對應的是css3裏width: min-content
- 超出容器限制;設置了white-space:nowrap屬性後,或者是很長的英文數字會超出容器限制;否則默認情況下都不會主動超過父級容器。
width: max-content時,表現爲外部容器的最終寬度就是內部元素的最大值。超過一屏的滾動展示
外部尺寸與流體特性
外部尺寸:元素尺寸由外部容器決定。
以上特性中的第一條: <div>寬度默認100%顯示就是外部尺寸,其他全都是內部尺寸;這個也是“流”精髓;
“外部尺寸”的塊級元素一旦設置了寬度,流動性就消失了。(所謂流動性是margin/border/padding/content區域自動分配水平空間的機制)
內部尺寸與流體特性
內部尺寸: 元素尺寸由內部元素決定。
- 包裹性:元素尺寸由內部決定,但不會超過父容器,除非父容器小於元素的首選最小寬度。
如上:按鈕是inlint-block元素,按鈕的寬度由內容決定,超過父容器寬度時,自動換行顯示
2. 首選最小長度:即上面的收縮到最小;
table-layout: auto的元素中,每一列寬度都不夠時,漢字可以隨便斷,英文單詞不能。於是第一行被斷成這樣子
3.最大寬度:有包裹性或者設置了white-space:nowrap屬性的元素,最大寬度是內部連續內聯盒子的寬度
如果僅有包裹性,容器最大寬度不會超過頁面寬度,即不會出現滾動條,自動換行
width: 指定具體值的時候 width: 200px
由前面知道,width是作用在內部容器盒子的。內部容器盒子實際上包含:content-box, padding-box, border-box, margin-box(css盒模型)
css2.1規範中指出,contentbox是環繞着width和height的矩形;
指定具體寬度後會有的影響:
- 流動性消失;
- 實際效果跟預期不一致;
解決辦法:
1. 寬度分離
css中,width屬性不跟影響寬度的padding, border甚至margin屬性共存。
好處是:避免了計算, 利於維護
避免以下寫法
.box {
width: 100px;
padding: 10px;
border: 1px solid #eee;
}
採用以下寫法,width獨佔一層標籤,內部利用流動性自適應展示
.wrapper {
width: 100px;
}
.box {
padding: 10px;
border: 1px solid #eee;
}
2. 改變box-sizing屬性值,改變width/height的作用細節
流的破壞
流的破壞之float
追根溯源,float的起源就是爲了實現文字環繞效果;因爲最初帶寬就那麼一點點的時候我們能做的也就是展示文字及零星圖片而已
float的特性:
- 包裹性
- 塊狀化並格式化上下文
- 破壞文檔流
- 沒有任何margin合併
float的作用機制:
行框盒子: 每一行就是一個行框盒子,每個行框盒子又是由一個一個內聯盒子組成的;如下:
在頁面中,由幾行展示就有幾個行框盒子,如下:兩個行框盒子
- 會讓父元素高度塌陷(初衷就是爲了實現文字環繞效果)
- 行框盒子區域限制(如果行框盒子和浮動元素的垂直高度有重疊,則行框盒子在正常定位狀態下只會跟隨浮動元素,不會發生重疊)
圖片高度爲100px,float:left, 文字部分高度100以內的跟隨浮動元素,超過100的開始重疊發生環繞
要想實現一欄定寬的兩欄佈局,可以左側定寬left浮動,右側margin-left:定寬 ,實現自適應
3. float定位參考的是“行框盒子”;比如right浮動時,如果當前行框盒子滿了,就會顯示到行框盒子下面
流的保護之clear
clear—專門解決float高度塌陷等問題的屬性;
clear:none| right | left | both;
設置了clear屬性的元素盒子的邊不能和前面的浮動元素相鄰
所以,設置了clear後,浮動依然存在,並沒有清除;
只是設置了clear的元素分別會具有以下特點;
- none: 默認值,左右都可浮動
- left: 左側抗浮動
- right:右側抗浮動
- both: 兩側抗浮動
clear屬性只對塊級元素生效;這就是通過僞元素清楚浮動時需要設置display屬性值的原因
clear只是一定程度上消除浮動的影響,浮動元素的一些不好的特性依然存在;如下:(例如行框盒子區域限制特性)
完美去除浮動影響:
BFC: 塊級格式化上下文
如果一個元素有BFC,內部子元素無論怎麼翻江倒海,都不會影響外部元素;也不會受到外部元素的影響。像是一個“結界”;
觸發BFC的條件:
- html根元素
- float不是none
- overflow的值是auto, scroll, hidden
- display的值是table-cell, table-caption, inline-block
- position不是relative, static
此時實現一欄定寬的兩欄佈局,就可以左側float定寬浮動,右側爲BFC;就算不知道左側寬度時,也可以實現。
如果要兩欄之間隔開10px距離,可以左側添加margin-right, border-right,padding-right,右側border-left, padding-left爲10px;右側使用margin-left的話,需要10px+左側定寬。
綜上:清除浮動最好的方法就是overflow:hidden
流的破壞之定位
position: absolute
absolute能力比float霸道, 當兩者同時存在時,float沒有任何效果,當前兩個也沒理由同時存在;
特性跟float差不多:
- 破壞文檔流
- 塊狀化並格式化上下文
- 包裹性
absolute的的自適應性最大寬度往往不是由父元素決定的,而是由包含塊決定的。
何爲包含塊?
元素用來定位和計算的框;
根元素<html>:也叫初始包含塊,尺寸等同於瀏覽器可視窗口的大小;
position是relative或者static的元素:包含塊是最近的塊容器的content box;
position是absolute的元素:第一個position不是static的祖先元素的padding box;
position是fixed的元素:包含塊是初始包含塊
absolute元素的寬度自適應相對於包含塊來表現:
有一個有趣的例子https://demo.cssworld.cn/6/5-1.php
實現一個刪除圖標,鼠標懸浮顯示“刪除”小提示;通過after,before僞元素實現提示文字和小箭頭的展示,通過圖標設置relative屬性實現精確的定位;
會出現的問題是,圖標寬度很小,不足兩個字的寬度,於是“刪除”兩個字換行顯示。
解決辦法,設置white-space: nowrap;讓寬度表現從“包裹性”變成“最大可用寬度”。
absolute無依賴絕對定位:
元素只設置了position:absolute,沒有設置top等屬性;
它是脫離css文檔流的相對定位特性;
通過這個特性可以實現表單輸入提示,具有可維護性強的特性;
見https://demo.cssworld.cn/6/5-6.php
通過absolute和margin實現提示信息的定位。
absolute設置top/bottom, left/right來定位:
如果left, right同時設置爲0,那麼定位元素在水平方向依然就有流的特性,即padding,content, border自動分配;垂直方向也如此
利用這個特性可是設置絕對定位元素水平垂直居中;即四個方向定位設置爲0, 指定寬度後margin設置爲auto
absolute元素的height:
絕對定位元素的height設置爲100%和inherit時實際計算是完全不同的。
100%: 相對於包含塊計算高度。
inherit: 相對於父元素計算高度,繼承父元素的高度值。
無依賴absolute也可能受到text-align的影響:
前提是定位元素前有個內聯元素(內聯元素有個幽靈空白節點),內聯元素的位置被text-align影響,此時後面的absolute定位元素在無依賴定位時,默認就在這個幽靈空白節點後面
absolute和overflow
包含塊及其父元素的的overflow屬性才能影響到absolute的溢出處理。
overflow溢出採用的是content-box爲邊界;
position: relative
相對定位,定位的位置相對於自身進行偏移
relative定位是相對於它的包含塊(父級元素)的content-box來計算的。
relative定位不會影響它之外的元素的顯示位置;
例如,原本一個正常文檔流的排版,div設置relative並top: -20px; 那麼div跟他後面的元素之間會有一個20px的空白。其後的元素位置不會受到影響。這一點跟margin不同。
relative可以決定absolute的位置計算,所以relative要遵循最小影響範圍原則,便於代碼擴展和維護。
position:fixed
該定位的包含塊是初始包含塊,也就是<html>;
fixed的裁剪需要使用clip屬性,因爲它的包含塊是html。
clip屬性值爲定位元素上,右,下,左四個方向要裁剪掉的距離。