1. 程式人生 > >css中的流,元素,基本尺寸

css中的流,元素,基本尺寸

流 元素 基本尺寸

流之所以影響整個css世界,是因為它影響了css世界的基石 --HTML

HTML 常見的標籤有雖然標籤種類繁多,但通常我們就把它們分為兩類: 塊級元素(block-level element)和內聯元素(inline element)。

1.塊級元素

1.1 概念相關

“塊級元素”對應的英文是 block-level element,常見的塊級元素有 div,li,table等。

塊級元素和 display:block 不是一個概念

例如塊級元素 li 和 table ,他們的 display 的值分別為 list-item 和 table

塊級元素具有換行性質,也就是一個水平流

上只能單獨顯示一個元素,多個塊級元素則換行顯示;

由於這種 換行性質,理論上塊級元素都可以配合 clear 屬性來清除浮動帶來的影響

.clear:after {
 content: '';
 display: table; // 也可以是 block,或者是 list-item
 clear: both;
} 

實際開發中,display的值要麼是block,要麼是table,並不會使用list-item

1.2 為什麼 list-item會出現專案符號

所有的塊級元素都有一個主盒子,而list-item除了主盒子,還有一個附加盒子

list-item 之所以會出現專案符號(小黑點),是因為生成了一個附加盒子,學名為 “標記盒子”,專門來存放圓點,數字這些專案符號

IE不支援display:list-item 的原因可能就是因為IE無法建立 這個標記盒子的原因。

1.3 display:inline-block

display:inline-block 我們可以把一個這樣的元素分為兩個部分組成,外在的inline內聯盒子,裡面的block塊級盒子組成。這樣,由於外在的外聯盒子,它的呈現方式既可以和文字等元素同為一行,又因為內在的塊級盒子,它可以設定元素的寬高。

於是,按照display的屬性值不同

display 外盒子 內盒子
block block block
inline inline inline
inline-block inline block
table block table
inline-table inline table

外盒子影響著流的走向,內盒子控制元素的基本屬性

2. width/height 作用的具體細節

我們在上面已經說過, width/height等屬性作用在內盒子中,也就是容器盒子中。接下來我們說一下具體的作用細節。

流特性體現在水平方向上,我們來討論width

2.1 width:auto

width的預設值就是auto

  • 充分利用空間 -- div的預設寬度一般都是100%

  • 收縮和包裹

  • 收縮到最小 -- min-content

    當每一列空間都不夠的時候,文字能斷就斷,但中文是隨便斷的,英文單詞不能斷。

  • 超出容器限制

    沒有相關設定的情況下,一般元素不會主動超過父級寬度容器,除非一些特殊情況

    例如:內容而很長的連續英文和數字

    ​ 或者內聯元素被設定了 white-space:nowrap 屬性

在 CSS 世界中,盒子分“內在盒子”和“外在盒子”,顯示也分“內部顯示”和“外部顯示”,同樣地,尺寸也分“內部尺寸”和“外部尺寸”。

上述的width:auto 的四條特性裡面,是預設寬度 100%顯示,是“外部尺寸”,其餘全部是“內部尺寸”。而這唯一的“外部尺寸”,是“流”的精髓所在。

2.2 外部尺寸與流體特性

  1. 正常流寬度。

    當我們在一個容器裡倒入足量的水時,水一定會均勻鋪滿整個容器。

    a {
     display: block;
     width: 100%;
    } 

    預設為inline的a元素display設定為block,本身就是表示寬度鋪滿整個父級,後面的100%寬度就不用再加了。

    作者總結過一套三無準則: 無寬度,無圖片,無浮動。

    其中無寬度的原因就是因為一旦外部尺寸的塊級元素設定了寬度,其流動性就丟失了。

  2. 格式化寬度

    格式化寬度僅出現在“絕對定位模型”中,也就是出現在 position屬性值為 absolute 或 fixed 的元素中。在預設情況下,絕對定位元素的寬度表現是“包裹性”,寬度由內部尺寸決定

    但是有一種情況其寬度是由外部尺寸所決定的,例如:

    div { position: absolute; left: 20px; right: 20px; } 

    假設該元素最近的具有定位特性的祖先元素的寬度是 1000 畫素,則這個元素的寬度是 960(即 1000−20−20)畫素。

2.3 內部尺寸與流體特性

所謂“內部尺寸”,簡單來講就是元素的尺寸由內部的元素決定,而非由外部的容器決定。

如何判斷一個元素是否為內部尺寸呢?

​ 假如這個元素裡面沒有內容,寬度就是 0,那就是應用的“內部尺寸”。

“內部尺寸”有下面 3 種表現形式:

  1. 包裹性。

    “包裹性”,除了“包裹”,還有“自適應性”。“自適應性”是區分後面兩種尺寸表現很重要的一點。自適應,指的是元素尺寸由內部元素決定。

    按鈕就是 CSS 世界中極具代表性的 inline-block 元素,可謂展示“包裹性”最好的例子,具體表現為:按鈕文字越多寬度越寬(內部尺寸特性),但如果文字足夠多,則會在容器的寬度處自動換行(自適應特性)。

    “包裹性”對實際開發的作用

    請看這個需求:頁面某個模組的文字內容是動態的,可能是幾個字,也可能是一句話。然 後,希望文字少的時候居中顯示,文字超過一行的時候居左顯示。該如何實現?

  2. 首選最小寬度

    在 CSS 世界中,圖片和文字的權重要遠大於佈局,因此,CSS 的設計者顯然是不會讓圖文在 width:auto 時寬度變成 0 的,此時所表現的寬度就是“首選最小寬度”。

    • 漢字最小寬度是每個字的寬度

    • 英文最小寬度是由連續的英文字元單元決定,終止於空格,短橫線及其他非字母符號

      想讓英文字元和中文一樣一個字元為最小寬度,可以使用css中的 word-break:break-all 屬性

    • 類似圖片這樣的替換元素的最小寬度就是該元素內容本身的寬度

  3. 最大寬度

    最大寬度就是元素可以有的最大寬度。

    如果內部沒有塊級元素或者塊級元素沒有設定寬度值,則“最大寬度”實際上是最大的連續內聯盒子的寬度。

2.4 width 值作用的細節

對於一個元素,我們設定其寬度為 100px,如下:div { width: 100px; } 請問,100px 的寬度是如何作用到這個元素上的?

width 是作用在“內在盒子”上的,實際上,這個內在盒子是由很多部分組成 --- 盒子模型

盒子模型

我們的這個“內在盒子”又被分成了 4 個盒子,分別是 content box、padding box、border box和 margin box

“margin 的背景永遠是透明的”,因此不可能作為 backgound-clip 或 backgroundorigin屬性值出現。margin 一旦設定具體寬度和高度值,其本身的尺寸是不會因 margin值變化而變化的。

width寬度作用在content盒子上

假設一個盒子的css如下:

div { width: 100px; padding: 20px; border: 20px solid; } 

那麼它的寬度就變成了 100 + 20x2 + 20x2 = 180 px 了

合情合理,但是這種機制會導致以下問題:

  1. 流動性丟失
  2. 與現實世界表現不一致的困擾

有沒有什麼辦法能避免這種盒子計算而導致的錯位問題呢,方法之一就是採用書寫方式約束,使用“寬度分離原則”

2.4 CSS流體佈局下的寬度分原則

所謂“寬度分離原則”,就是 CSS 中的 width 屬性不與影響寬度的 padding/border(有時候包括 margin)屬性共存

如何實現?

分離,width 獨立佔用一層標籤,而padding、border、margin 利用流動性在內部自適應呈現。

例子:

這裡有一個div盒子

  • 常規佈局

    .box {
     width: 100px;
     border: 1px solid;
    } 

    此時寬度為102畫素,我們現在希望元素內邊框有20畫素的留白,我們一般會想到的解決辦法是加padding的值

    .box {
     width: 100px;
     padding: 20px;
     border: 1px solid;
    } 

    ok 此時有了留白,但是我們發現寬度變成了 102 + 40 = 142px, 我們常規的會使用減少寬度來實現我們的要求

    .box {
     width: 60px; // 通過計算,減去 40 畫素
     padding: 20px;
     border: 1px solid;
    } 

    要求實現了,但是如果我們是通過計算,才能達到我們想要的,以後的除錯會有更多的麻煩。

  • 寬度分離

    .father {
     width: 102px;
    }
    .son {
     border: 1px solid;
     padding: 20px;
    } 

    巢狀一層標籤,父元素定寬,子元素因為 width 使用的是預設值 auto,所以會如水流般自動填滿父級容器。

    寬度還是 102 畫素,子元素的 content box 自動變成了 60 畫素,和上面反例的表現一樣。

    也就是說,使用“寬度分離”後,咱們不需要燒腦子去計算了,而且頁面結構反而更穩固。

    這個做法的唯一缺點就是要多巢狀一層html標籤,和對開發者極高的css要求水平。

    針對這中情況,有沒有即無需計算,又不用額外的套用標籤而實現呢? ----> box-sizing

2.5 改變width/height 作用細節的 box-sizing

box-sizing 被直譯為“盒尺寸”,實際上,其更準確的叫法應該是“盒尺寸的作用細節”,或者說得更通俗一點,叫“width 作用的細節”,也就是說,box-sizing 屬性的作用是改變 width 的作用細節

正常情況下width作用在盒模型中的四個盒子中的content盒子上,box-sizing的作用就是可以把width作用的盒子變成其他的幾個盒子上,有以下幾種寫法

.box1 { box-sizing: content-box; } /* 預設值 */
.box2 { box-sizing: padding-box; } /* Firefox 曾經支援 */
.box3 { box-sizing: border-box; } /* 全線支援 */
.box4 { box-sizing: margin-box; } /* 從未支援過 */ 

.box3 { box-sizing: border-box; }來說,就是把原來的寬度作用物件從content-box轉到了border-box

.box {
 width: 100px;
 box-sizing: border-box;
}   
此時這個盒子的寬度是100px

.box {
 width: 100px;
 box-sizing: border-box;
 border: 1px solid;
} 
這事的寬度還是100px

2.6 height: auto 和 height: 100%

寬度稀缺,高度無限,所以在css中高度較寬度更簡單純潔

height: auto

所有的元素盒子在頁面中表現的每個有多高,加在一起,就是最終的高度值

height: 100%

height 和 width 還有一個比較明顯的區別就是對百分比單位的支援。對於 width 屬性,就算父元素 width 為 auto,其百分比值也是支援的,但是對於 height 屬性,如果父元素height 為 auto,只要子元素在文件流中,其百分比值完全就被忽略了。

對於普通文件流中的元素,百分比高度值要想起作用,其父級必須有一個可以生效的高度值。

為何父級沒有具體高度值的時候,height:100%會無效?

如果包含塊的高度沒有顯式指定(即高度由內容決定),並且該元素不是絕對定位,則計算值為auto。一句話總結就是:因為解釋成了 auto。要知道,auto 和百分比計算,肯定是算 不了的。

如何讓元素支援 height:100%效果

  1. 設定顯式的高度值。這個沒什麼好說的,例如,設定 height:600px,或者可以生效的百分比值高度。

    html, body {
     height: 100%;
    } 
  2. 使用絕對定位。

    div {
     height: 100%;
     position: absolute;
    } 

    此時的 height:100%就會有計算值,即使祖先元素的 height 計算為 auto 也是如此。

    絕對定位元素的百分比計算和非絕對定位元素的百分比計算是有區別的:

    絕對定位的寬高百分比計算是相對於 padding box 的

    非絕對定位元素則是相對於 content box 計算的

3. min-width/max-width和min-height/max-height

3.1為流體而生的 min-width/max-width

網頁寬度在 1200~1400 畫素自適應,既滿足大屏的大氣,又滿足筆記本的良好顯示

.container {
 min-width: 1200px;
 max-width: 1400px;
} 

無須 width 設定,直接使用 min-width/max-width

再比如一個圖片的盒子寬度已定:

img {
 max-width: 100%;
 height: auto!important;
} 

height:auto 是必需的,否則,如果原始圖片有設定 height,max-width 生效的時候,圖片就會被水平壓縮。強制 height 為 auto 可以確保寬度不超出的同時使圖片保持原來的比例。但這樣也會有體驗上的問題,那就是在載入時圖片佔據高度會從 0 變成計算高度,圖文會有明顯的瀑布式下落。

3.2 與眾不同的初始值

width/height 的預設值是 auto,而 min-width/max-width 和 min-heigh/max-height 的初始值則要複雜些

max-width 和 max-height 的初始值是 none

min-width 和 min-height 的初始值是 auto

3.3 超越!important,超越最大

超越!important

min-width/max-width 和 min-height/max-height 屬性間,以及與width 和 height 之間有一套相互覆蓋的規則。這套規則用一句比較通俗的話概括就是:超越!important,超越最大。

<img src="1.jpg" style="width:480px!important;">
img { max-width: 256px; }

以上程式碼作用後,img的寬度為 max-width的寬度 -- 256px,style、!important 通通靠邊站!因為 max-width 會覆蓋 width。

超越最大

.container {
 min-width: 1400px;
 max-width: 1200px;
 } 

最小寬度居然比最大寬度設定得還大, 最後誰會生效?

遵循“超越最大”規則(注意不是“後來居上”規則),min-width 活下來,max-width 被忽略,於是,.container 元素表現為至少 1400 畫素寬

3.4 任意高度元素的展開收起動畫技術

“展開收起”效果是網頁中比較常見的一種互動形式,通常的做法是控制 display 屬性值在 none 和其他值之間切換

傳統實現可以使用 jQuery 的 slideUp()/slideDown()方法

第一反應就是使用 height + overflow:hidden 實現。但是,很多時候,我們展開的元素內容是動態的,換句話說高度是不固定的,因此,height 使用的值是預設的 auto

因此,下面程式碼呈現的效果也是生硬地展開和收起:

.element {
 height: 0;
 overflow: hidden;
 transition: height .25s;
}
.element.active {
 height: auto; /* 沒有 transition 效果,只是生硬地展開 */
} 

auto 是個關鍵字值,並非數值,正如 height:100%的 100%無法和 auto 相計算一樣,從 0px 到 auto 也是無法計算的,因此無法形成過渡或動畫效果。

我們可以使用max-height來解決這一問題

.element {
 max-height: 0;
 overflow: hidden;
 transition: max-height .25s;
}
.element.active {
 max-height: 666px; /* 一個足夠大的最大高度值 */
} 

展開後我的高度只要比max-height小,那麼元素的高度就是height的計算高度,一個高度不定的任意元素的展開動畫效果就能實現了。

注意: max-height值在保證比height大的情況下儘可能和的小

因為max-height可能會影響動畫的時間, 比方說,我們展開的元素高度是 100 畫素,而 max-height 是 1000 畫素,假如一個動畫1000ms,則前 900 ms 我們是看不到收起效果的,因為max-height 從 1000 畫素到 100 畫素變化這段時間,元素不會有區域被隱藏,會給人動畫延遲 900 ms 的感覺

4. 內聯元素

4.1 哪些是內聯元素

從定義:

內聯元素的內聯指的是外在盒子,外在盒子表現為inline的元素都是內聯元素。

inline-block 和 inline-table 都是“內聯元素”,因為它們的 “外在盒子”都是內聯盒子。自然 display:inline 的元素也是“內聯元素”,那麼, 按鈕元素是內聯元素,因為其 display 預設值是 inline-block;img圖片元素也是內聯 元素,因為其 display 預設值是 inline 等。

從表現看:

就行為表現來看,“內聯元素”的典型特徵就是可以和文字在一行顯示。

浮動元素貌似也是可以和文字在一個水平上顯示的,但是浮動已經脫離文件流,不屬於內聯元素。

4.2 內聯世界深入的基礎—內聯盒模型 (import)

<p>這是一行普通的文字,這裡有個 <em>em</em> 標籤。</p>

看似普通,實際上包含了很多術語和概念,或者換種通俗的說法,包含了很多種盒子。

  1. 內容區域

    內容區域指一種圍繞文字看不見的盒子,其大小僅受字元本身特性控制,本質上是一個字元盒子(character box);但是有些元素,如圖片這樣的替換元素,其內容顯然不是文字,不存在字元盒子之類的,因此,對於這些元素,內容區域可以看成元素自身。

    這是一行普通的文字,這裡有個 <em>em</em> 標籤。

    以上程式碼表現的區域,可以理解為內容區域。

  2. 內聯盒子

    如果外部含內聯標籤等),則屬於“內聯盒子”;如果是個光禿禿的文字,則屬於“匿名內聯盒子”

  3. 行框盒子(line box)

    每一行就是一個“行框盒子”(實線框標註),每個“行框盒子”又是由一個一個“內聯盒子” 組成的。

  4. 包含盒子/包含塊(containing box)

    <p>標籤就是一個“包含盒子”(實線框標註),此盒子由一行一行的“行框盒子”組成。

4.3 幽靈空白節點

在 HTML5 文件宣告中,內聯元素的所有解析和渲染表現就如同每個行框盒子的前面有一個“空白節點”一樣。這個“空白節點”永遠透明,不佔據任何寬度,看不見也無法通過指令碼獲取,就好像幽靈一樣,但又確確實實地存在,表現如同文字節點一樣,因此,我稱之為“幽靈空白節點”

<style>
  div {
    background-color: #cd0000;
  }
  span {
    display: inline-block;
  }
</style>
<body>
  <div><span></span></div>
</body>

瀏覽器開啟上述程式碼,發現div的高度不是0,原因就在於幽靈空白節點。

“幽靈空白節點”實際上也是一個盒子,不過是個假想盒,名叫“strut”,中文直譯為“支柱”,是一個存在於每個“行框盒子”前面,同時具有該元素的字型和行高屬性的 0 寬度的內聯盒。

Each line box starts with a zero-width inline box with the element’s font and line height properties. We call that imaginary box a “strut”.

內容總結與 張鑫旭大神 -- 《css世界》