# 置換和非置換元素
>原作者:doyoe
原文鏈接:http://blog.doyoe.com/2015/03/15/css/%E7%BD%AE%E6%8D%A2%E5%92%8C%E9%9D%9E%E7%BD%AE%E6%8D%A2%E5%85%83%E7%B4%A0/
## 先進一個題外話
在面試一個 `重構`(各大公司的叫法可能不太一樣)時,我喜歡從一個點開始問,然后一直延展下去成為一條線,甚至是一個面,直到問到不會的地方,然后又換另外一個點。
>例如:我可能會說,能簡單聊聊 `行內級元素` 和 `塊級元素` 的區別嗎。
一般這時,候選人都會說到 `行內級元素` 不會換新行,而 `塊級元素` 會格式化為塊狀,即換行。但也有些遺憾的方面(如:[混淆了塊元素和塊級元素,行內元素和行內級元素](http://www.hmoore.net/jaya1992/fe-notes/86789)),當然這看起來似乎不是特別重要。
>這時我會繼續問,`行內元素` 能夠定義寬度和高度嗎?
不少候選人會說:**不能**
>我會繼續問,說幾個你熟悉的 `行內元素` 吧
于是 `span`, `strong`, `em`, `ins`… 答案我還是比較滿意的。
>我仍然會繼續,`img` 是行內元素么?
候選人這時通常會遲疑一下,可能意識到我接下來想問啥了,但還是會回答:**是**
>于是我會說,那 `img` 能定義寬度和高度么?
有的候選人這時會猶豫,因為如果回答是,就會推翻他之前說的 `行內元素不能定義寬高`,如果回答不是,似乎又和他所熟知的經驗不一致。但通常最后還是會回答:**能**
>那我就又得問,你之前不是說 `行內元素不能定義寬高` 嗎?為什么 `img` 可以?
到這里,候選人基本上不知道要怎么回答好了,最后可能會告訴我,**因為 `img` 是特殊元素**
當然,雖然這么回答也不能說是錯誤的,但基本上也能知道候選人對這條線的基礎的掌握程度了。
但我希望聽到的答案是通過解釋置換元素相關的概念從而給出答案。
## 什么是置換元素?
一個 `內容` 不受CSS視覺格式化模型控制,CSS渲染模型并不考慮對此內容的渲染,且元素本身一般擁有固有尺寸(寬度,高度,寬高比)的元素,被稱之為置換元素。
## 什么是非置換元素?
w3c并沒有給出明確的非置換元素的解釋,但能確定的是除置換元素之外,所有的元素都是非置換元素。
## 行內級置換和非置換元素的寬度定義
對于行內級非置換元素,寬度設置是不適用的。
對于行內級置換元素來說,其寬度的設置需遵循以下幾點:
- 若寬高的計算值都為 `auto` 且元素有固有寬度,則 `width` 的使用值為該固有寬度;
> 典型的例子是:擁有默認寬高的 `input` 當寬度的計算值為auto時,則寬度使用值為其默認的固有寬度
- 若寬度的計算值為 `auto` 且元素有固有寬度,則 `width` 的使用值為該固有寬度;
> 例子同上
- 若寬度的計算值為 `auto` 且高度有 `非auto` 的計算值,并且元素有固有寬高比,則 `width` 的使用值為 `高度使用值 * 固有寬高比`;
>典型的例子:`img` 當只定義了其高度值時,其寬度將會根據固有寬高比進行等比設置
- 除此之外,當 `width` 的計算值為 `auto` 時,則寬度的使用值為 `300px`
> 典型的例子:比如iframe, canvas
其它類型的置換元素,其寬度的定義都參照行內置換元素的定義。
## 行內級置換和非置換元素的高度定義
對于行內級非置換元素,高度設置是不適用的。
對于行內級置換元素來說,其高度的設置需遵循以下幾點:
- 若寬高的計算值都為 `auto` 且元素有固有高度,則 `height` 的使用值為該固有高度;
- 若高度的計算值為 `auto` 且元素有固有高度,則 `height` 的使用值為該固有高度;
- 若高度的計算值為 `auto` 且寬度有 `非auto` 的計算值,并且元素有固有寬高比,則 `height` 的使用值為:`寬度使用值 / 固有寬高比`;
- 若高度的計算值為 `auto` 且上述條件完全不符,則 `height` 的使用值 `不能大于150px`,且寬度不能大于長方形高度的2倍。
其它類型的置換元素,其高度的定義都參照行內置換元素的定義。