CSS學習5(視覺表現模型)

基本框

CSS假定每個元素都會生成一個或多個矩形框,這稱爲元素框。各元
素框中心有一個內容區(content area)。這個內容區周圍有可選的內邊距、邊框和外邊距。這些項之所以被認爲是可選的,是因爲它們的寬
度可以設置爲0,實際上這就從元素框去除了這些項。
可以用多種屬性設置各外邊距、邊框和內邊距,如margin-left或border-bottom。內容的背景(例如某種顏色或平鋪圖像)也會應用到內邊
距。外邊距通常是透明的,從中可以看到父元素的背景。內邊距不能是負值,但是外邊距可以。

包含塊

每個元素都相對於其包含塊擺放,包含塊就是一個元素的佈局上下文。
對於正常的西方語言文本流中的一個元素,包含塊由最近的塊級祖先框、表單元格或行內塊祖先框的內容邊界(content edge)構成。

正常流

這是指西方語言文本從左向右、從上向下顯示,這也是我們熟悉的傳統HTML文檔的文本佈局,注意,在非西方語言中,流方向可能不同。大多數元素都在正常流中,要讓一個元素不在正常流中,唯一的辦法就是使之成爲浮動或定位元素。這裏我們談論的都是在正常流中的元素。
塊級元素
這是指段落、標題或div之類的元素。這些元素在正常流中時,會在其框之前和之後生成“換行”,所以處於正常流中的塊級元素會垂直襬放。通過聲明display:block,可以讓元素生成塊級框。
行內元素
這是指strong或span之類的元素,這些元素不會在之前或之後生成“行分隔符”,它們是塊級元素的後代。通過聲明display:inline。可以讓元素生成一個行內框。

塊級元素

水平格式化

控制盒模型水平方向的有7個值:margin-left、border-left, padding-left、width、 padding-right、border-right和margin-right。
這7個屬性的值加在一起必須是元素包含塊的寬度,這往往是塊元素的父元素的width值。
關於auto
在這7個屬性中有3個可以設置爲auto:margin-left、width、margin-right。其餘的要不必須是確定的值,要不就是默認值0。
有這麼幾種情況:

  • 3個都不是auto:按CSS的術語來講,這些格式化屬性過分受限,此時總會把margin-right強制爲auto來適應父元素的寬度。
  • 2個不是auto:這個最簡單,剩下的一個是auto的將自動調整到適應父級元素的寬度。
  • 兩個外邊距是auto:他們會自動設置爲相等的長度,導致此元素在其父級元素中居中。
  • 一個外邊距和width是auto:auto的外邊距會減爲0,width自動填充。
  • 3個都是auto:兩個外邊距減爲0,width自動充滿。

注意:由於水平外邊距不會合並,父元素的內邊距、邊距和外邊距可能影響其子元素。
負外邊距
這個是允許的,也只有它是允許爲負值的,這個還有好多用處呢。
百分數
百分數也是可以的,當然還是要遵守加起來爲父元素寬度的限制,這裏爲內外邊距,寬度設置的百分比都是相對父元素來說的。邊框不能是百分數。
替換元素
剛纔說的是非替換塊級元素的水平格式化,替換塊級元素其他的規則都一樣,只有一個例外,當width爲auto 時,元素寬度爲內容的固有寬度。

垂直格式化

一個元素的默認高度由其內容確定,可以對任何塊級元素設置顯式高度。如果內容撐不下,根據元素的overflow屬性用戶代理會做出選擇。
垂直屬性
也是有7個:margin-top、border-top、padding-top、height、 padding-bottom、border-bottom和margin-bottom。
同樣,這7個值的和必須等於其包含塊的height。
同樣有3個值可以是auto,其他的不行。不過上下外邊距設置爲auto也沒有什麼用,因爲會被重置爲0。
百分數高度
父元素的高度如果沒有顯式聲明,那子元素的高度設置爲百分數也會被重置爲auto。
利用上下外邊距auto垂直居中顯然是不可能的。
auto高度的問題
如果塊級正常流元素的高度設置爲auto,而且只有塊級子元素,其默認高度將是從最高塊級子元素的外邊框邊界到最低塊級子元素外邊框邊界
之間的距離。因此,子元素的外邊距會“超出”包含這些子元素的元素(由於垂直合併外邊距)。

不過,如果塊級元素有上內邊距或下內邊距,或者有上邊框或下邊框,其高度則是從其最高子元素的上外邊距邊界到其最低子元素的下外邊距邊界之間的距離。
合併垂直外邊距
垂直格式化的另一個重要方面是垂直相鄰外邊距的合併。這種合併行爲只應用於外邊距。如果元素有內邊距和邊框,它們的垂直外邊距絕對不會合並。
負外邊距
這個在垂直方向上也是允許的,重疊的時候,如果垂直外邊距都設置爲負值,瀏覽器會取兩個外邊距絕對值的最大值。如果一個正外邊距與一個負外邊距合併,會從正外邊距減去這個負外邊距的絕對值。

行內元素

除了塊級元素,最常見的就是行內元素了。通過爲行內元素設置框屬性,可以進入到一個更有意思的領域。非替換元素和替換元素在內聯內容方面的處理稍有不同,討論行內元素的構造時我們將分別進行討論。

一些概念

匿名文本
匿名文本(anonymous text)是指所有未包含在行內元素中的字符串。因此,在標記(p) I’m (em)so(/em) happy!(/p)中,序列“I’m”和 “happy!”都是匿名文本。注意,空格也是匿名文本的一部分,因爲空格與其他字符一樣都是正常的字符。
em框
em框在字體中定義,也稱爲字符框(character box)。實際的字形可能比其em框更高或更矮。在CSS 中,font-size的值確定了各個em框的高度。
內容區
在非替換元素中,內容區可能有兩種,CSS2.1規範允許用戶代理選擇其中任意一種。內容區可以是元素中各字符的em框串在一 起構成的框,也可以是由元素中字符字形描述的框。
在替換元素中,內容區就是元素的固有高度再加上可能有的外邊距、邊框或內邊距。
行間距
行間距(leading)是font-size值和line-height值之差。這個差實際上要分爲兩半,分別應用到內容區的頂部和底部。行間距只應用於非替換元素。
行內框
這個框通過向內容區增加行間距來描述。對於非替換元素,元素行內框的高度剛好等於line-height的值。對於替換元素,元素行內框的高度則恰好等於內容區的高度,因爲行間距不應用到替換元素。
行框
這是包含該行中出現的行內框的最高點和最低點的最小框。換句話說,行框的上邊界要位於最高行內框的上邊界,而行框的底邊要放在最低行內框的下邊界。
還有幾點要格外注意:

  • 內容區類似於一個塊級元素的內容框。
  • 行內元素的背景應用於內容區及所有內邊距。
  • 行內元素的邊框要包圍內容區及所有內邊距和邊框。
  • 非替換元素的內邊距、邊框和外邊距對行內元素或其生成的框沒有垂直效果,也就是說,它們不會影響元素行內框的高度(也不會影響包含該元素的行框的高度)。
  • 替換元素的外邊距和邊框確實會影響該元素行內框的高度,相應地,也可能影響包含該元素的行框的高度。
  • line-height實際上隻影響行內元素和其他行內內容,而不影響塊級元素,至少不會直接影響塊級元素。也可以爲一個塊級元素設置line-height值,但是這個值只是應用到塊級元素的內聯內容時纔會有視覺影響。

對於一個行框,其高度確定的基本步驟如下:

  1. 按以下步驟確定行中各元素行內框的高度: 得到各行內非替換元素及不屬於後代行內元素的所有文本的font-size值和line-height值,再將line-height減去font-size,這就 得到了框的行間距。這個行間距除以2,將其一半分別應用到em框的頂部和底部。 得到各替換元素的height、margin-top、margin-bottom, padding-top、 padding-bottom, border-top-width和border-bottomwidth值,把它們加在一起。
  2. 對於各內容區,確定它在整行基線的上方和下方分別超出多少。這個任務並不容易:你必須知道各元素及匿名文本各部分的基線的位置, 還要知道該行本身基線的位置,然後把它們對齊。另外,對於替換元素,要將其底邊放在整行的基線上。
  3. 對於指定了vertical-align值的元素,確定其垂直偏移量。由此可知該元素的行內框要向上或向下移動多遠,並改變元素在基線上方或下 方超出的距離。
  4. 既然已經知道了所有行內框會放在哪裏,再來計算最後的行框高度。爲此,只需將基線與最高行內框頂端之間的距離加上基線與最低行內 框底端之間的距離。

行內非替換元素

我們來看看如果行中只包含非替換元素(或匿名文本)將如何構造。

建立框
首先,對於行內非替換元素或匿名文本某一部分,font-size值確定了內容區的高度。如果一個行內元素font-size爲15px,則內容區的高度爲 15像素,因爲元素中所有em框的高度都是15像素。
下面再來考慮元素的line-height值,以及它與font-size值之差。如果一個行內非替換元素的font-size爲15px,line-height爲21px,則相差6 像素。用戶代理將這6像素一分爲二,將其一半分別應用到內容區的頂部和底部,這就得到了行內框。
假如,font-size爲24px,line-height爲12px。line-height和font-size之差是-12px,將其除2來確定半間距(-6px),再把這個半間距分別增加到內容區的頂部和底部,就得到了行內框。由於這裏增加的都是負數,所以最後行內框高度爲12像素。12像素高的行內框在元素內容區(24像素高)中垂直居中,所以行內框實際上小於內容區。 那麼行框也就可能小於內容區了,那就意味着內容會重疊到相鄰行。

垂直對齊
vertical-align各個關鍵字值的效果描述如下:

  • top:將元素行內框的頂端與包含該元素的行框的頂端對齊。
  • bottom:將元素行內框的底端與包含該元素的行框的底端對齊。
  • text-top:將元素行內框的頂端與父元素內容區的頂端對齊。
  • text-bottom:將元素行內框的底端與父元素內容區的底端對齊。
  • middle:將元素行內框的垂直中點與父元素基線上0.5ex處的一點對齊。
  • super:將元素的內容區和行內框上移。上移的距離未指定,可能因用戶代理的不同而不同。
  • sub:與super相同,只不過元素會下移而不是上移。
  • percentage:將元素上移或下移一定距離。這個距離由相對於元素line-height值指定的一個百分數確定。

管理line-height
在前幾節中我們已經瞭解到,改變一個行內元素的line-height可能導致文本行相互重疊。不過,在所有情況下,這種修改都是針對單個元素的,所以,如何以一種更一般的方式影響元素的line-height而避免內容重疊呢?
一種方法是對font-size有改變的元素結合使用em單位。

<p>
Not only does this paragraph have "normal" text, but it also<br>
contains a line in which <span>some big text </span> is found.<br>
This large text helps illustrate our point.
</p>
p {
  font-size: 14px;
  line-height: 1em; 
}
p span {
  font-size: 250%;
  line-height: 1em; 
}

或者使用line-height數值值會被直接繼承而不是計算繼承的特性。

p {fpnt-size: 14px; line-height: 1;}
p spanfont-size: 250%;}

基線與行高
各行框的具體高度取決於其組成元素相互之間如何對齊。這種對齊往往很大程度上依賴於基線落在各元素(或匿名文本各部分)中的哪個位置,因爲這個位置確定了其行內框如何擺放。基線在各em框中的位置對於不同的字體是不同的。這個信息內裏在字體文件中,除非直接編輯字體文件,否則無法修改。

縮放行高
設置line-height的最好辦法是使用一個原始數字值。之所以說這種方法最好,是因爲這個數會成爲縮放因子,而該因子是一個繼承值而非計算值。假設你希望一個文檔中所有元素的line-height都是其font-size的1.5倍,可以如下聲明:

body {line-height: 1.5;}

縮放因子1.5在元素間逐層傳遞,在各層上,這個因子都作爲一個乘數與各元素的font-size相乘。

增加框屬性
內邊距,外邊距和邊框都可以應用於行內非替換元素,行內元素的這些方面根本不會影響行框的高度。

對於邊框來說:
行內元素的邊框邊界由font-size而不是line-height控制。換句話說,如果一個span元素的font-size爲12px,line-height爲36px,其內容區就是12px高,邊框將包圍該內容區。

對於內邊距來說:
左右內邊距是有作用的。
上下內邊距是會影響到元素行內框的高度,如果有邊框的話會看到邊框外擴了,有背景的話背景也會變大。但是行框的高度是不會改變的,行間距自然也不變。

對於外邊距來說:
左右外邊距是有作用的。
上下外邊距根本不會應用別想了。

要注意的是:
儘管內邊距和外邊距(以及邊框)不影響行高,但是它們確實能影響一個元素內容的佈局,可能將文本推離其左右兩端。實際上,如果左、右外邊距爲負,可能會把文本拉近行內元素,甚至導致重疊。上下內邊距過大的話背景和邊框會擴到另一行。
這個例子可以試試:

<p>
    <span>Not only does this paragraph have "normal" text, but it also</span><br>
    <span>contains a line in which some big text is found.</span>
    <span>This <a href="www.baidu.com">Baidu</a> large text helps illustrate our point.</span>
</p>
span{
  border:1px solid red;
  line-height:1;
  padding:4px;
  margin:4px;
  background-color: rgba(255,1,1,0.5);
}

行內替換元素

一般認爲行內替換元素(如圖像)有固有的高度和寬度。有固有高度的替換元素可能導致行框比正常要高。這不會改變行中任何元素的line-height值,包括替換元素本身。相反,只是會讓行框的高度恰好能包含替換元素(以及所有框屬性)。換句話說,會用替換元素整體(包括內容、外邊距、邊距和內邊距)來定義元素的行內框。

<p>
    Not only does this paragraph have "normal" text, but it also<br>
    contains a line in which  is found.<br>
    This <img src="img/marker_red.png" alt="test image"> large text helps illustrate our point.
</p>
p {
  font-size: 15px;
  line-height: 18px; 
}
p img {
  height: 30px;
  margin: 0;
  padding: 0;
  border: none; 
}

這個例子裏line-height是18px,img的height是30px。所以img的行內框是30px。行框的高度也因此被撐高了。儘管是這樣,但不論是段落還是圖像本身的line-height的有效值並沒有因此改變。line-height對圖像的行內框沒有任何影響。
然而行內替換元素還是需要line-height來作爲一個垂直對齊時的基準。vertical-align的百分數值要相對於元素的line-height來計算。

p img {
   vertical-align: 50%;
}

比如剛纔的例子再加一個這個,那img就會往上升18*50%px。
還有就是替換元素會繼承這個line-height,它本身或它的後代有可能會用到這個值。
增加框屬性
在行內替換元素上應用框屬性是確實會影響到行框的高度的。因爲不同於行內非替換元素,它們會作爲替換元素行內框的一部分。
甚至是外邊距都會被包含在元素的行內框中,負的外邊距也有用哦,會減少替換元素的行內框。
替換元素和基線
默認地,行內替換元素位於基線上,如果向替換元素增加下內邊距、外邊距或邊框,內容區會上移。替換元素並沒有自己的基線,所以相對來講最好的辦法是將其行內框的底端與基線對齊。因此,實際上是下外邊距邊界與基線對齊。

改變元素顯示

比如將a標籤改爲塊顯示,將li改爲行內顯示等,使用display屬性,我們可以將元素的顯示角色改變。不過要注意的是,你改變的只是元素的顯示角色,而不是其本質。換句話說,讓一個段落生成行內框並不會把這個段落真正變成一個行內元素。因此,儘管鏈接可以放在一個段落中,但是鏈接卻不建議包圍段落。
行內塊元素
看上去display:inline-block是一個混合產物,實際上也確實如此。
行內塊元素作爲一個行內框與其他元素和內容相關。換句話說,它就像圖像一樣放在一個文本行中,實際上,行內塊元素會作爲替換元素放在行中。這說明,行內塊元素的底端默認地位於文本行的基線上,而且內部沒有行分隔符。在行內塊元素內部,會像塊級元素一樣設置內容的格式。就像所有塊級或行內替換元素一樣,行內塊元素也有屬性width和height,如果比周圍內容高,這些屬性會使行高增加。下面的例子可以用作對比:

<div>
    This text is the content of a block-level level element. Within this
    block-level element is another block-level element.<p>Look, it's a
    block-level paragraph.</p> Here's the rest of the DIV, which is still block-level.
</div>
<div>
    This text is the content of a block-level level element. Within this
    block-level element is an inline element.<p>Look, it's an inline
    paragraph.</p> Here's the rest of the DIV, which is still block-level.
</div>
<div>
    This text is the content of a block-level level element. Within this
    block-level element is an inline-block element.<p>Look, it's an inline block
    paragraph.</p> Here's the rest of the DIV, which is still block-level.
</div>
div {
  margin: 1em 0;
  border: 1px solid;
}
p {
  border: 1px dotted;
}
div:nth-child(1) p {
  display: block;
  width: 6em;
  text-align: center;
}
div:nth-child(2) p {
  display: inline;
  width: 6em;
  text-align: center;}
div:nth-child(3) p {
  display: inline-block;
  width: 6em;
  text-align: center;
}

有時行內塊元素很有用,例如:如果有5個超鏈接,你希望它們在一個工具條中寬度相等。爲了讓它們分別佔其父元素寬度的20%,但是仍保持其爲行內元素,可以聲明如下:

#navbar a {display: inline-block; width: 20%;}

計算值
display也是有計算值噠,如果元素是浮動元素或定位元素,display的計算值可以改變。如果爲一個根元素聲明display值,計算值也可以改變。實際上,display、
position和float值會以很有意思的方式相互影響。

發佈了128 篇原創文章 · 獲贊 6 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章