はじめに:
CSS の位置決めの問題について話すときは、まず小さな問題を見てみましょう:
既知の幅 (例: 100px) div ボックス、水平方向の中央揃え、左右の辺が塗りつぶされるそれぞれ div ボックスを使用し、左右の div は適応的です。
効果は以下のようになります:
この問題の難しさは主にブラウザの幅が不明であり、両側の div はアダプティブです.
最初の実装方法は CSS3 calc の新しい属性を使用することであり、実装コードは次のとおりです:
body { margin: 0; padding: 0; font-size:0;}.left_div { background-color: #62FF09; /*calc是css3属性可以动态计算,兼容不同浏览器的类型需要加识别的前缀,非常重要的是要有空格*/ width: -webkit-calc(50% - 50px); width: calc(50%-50px); height: 200px;}.mid_div { width: 100px; height: 200px; margin-left: -50px; background-color: #20FFDA; margin:0 auto;}.right_div { background-color: #FFF81B; height: 200px; width: -webkit-calc(50% - 50px);}div{display:inline-block;}
2 番目の実装方法は、display 属性を使用してすべての div ボックスはテーブルのセルの属性を持ちます
コードは次のとおりです:
* { padding: 0; margin: 0;}.left_div, .mid_div, .right_div { height: 200px; display: table-cell;}.left_div { width: 50%; background: #369;}.mid_div { //非IE识别的属性,(>=IE8) min-width: 100px; width: 100px; background: #697;}.right_div { width: 50%; background: #126;}
ここで問題を解決します 主なアイデアは、すべての div がセルであるため、中間の幅を決定した後、50% を使用して作成することです。左と右のセルは残りの幅を均等に分割します
ボックス モデルは、IE ボックス モデルと非 IE ボックス モデルに分かれています: 下の図を見てください (Wikipedia より):
より上の図から、IE ボックス モデルと非 IE ボックス モデルの違いは主に、計算される要素の幅と高さが異なることがわかります。
コードの一部を見てください:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>box-html</title> <style type="text/css"> *{margin:0;padding:0;} #body-box{ width:700px; height:500px; background-color:#FF00FF; /*overflow:hidden;*/ } .box-style{ width:500px; height:300px; border:10px dashed black; background-color:red; margin:10px 0 0 20px; padding: 10px 10px 10px 10px; } </style></head><body> <div id="body-box"> <div class="box-style">你好帅呀</div> </div></body></html>
結果は次のとおりです:
明らかに問題が見つかりました。つまり、子要素の margin-top が親要素に作用します。要素。
親要素に overflow:hidden 属性を追加すると、結果は正常です。
以下に示すように:
これはなぜですか?
オーバーフロー スタイル値が非可視の場合、CSS 2.1 仕様で定義されたブロック フォーマット コンテキストが実際に作成されます。それを作成した要素は、正確な高さを取得するために内部要素の位置が再計算されます。このように、親コンテナにはフローティング要素の高さも含まれます。この用語はあまりにも曖昧であったため、CSS 3 ドラフトではルート フローという用語に変更されました。その名前が示すように、このレイアウト フローは独立しており、外部要素には影響しません。実際、この機能は初期の IE の hasLayout 機能に非常に似ています。
テスト後、IE8 以降のブラウザのパフォーマンスは、Chrome および Firefox ブラウザのパフォーマンスと同じです。ただし、IE7 以下のブラウザでは、この属性を設定しなくても通常の効果を表示できます。以下に示すように:
明らかな問題の 1 つは、IE8 (IE8 を含む) より上のブラウザーの背景色はボーダー + パディング + コンテンツであり、IE8 (含まれていない) はパディング + コンテンツであることです。
別の例を見てみましょう。コードは次のとおりです:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>TestBox</title> <style type="text/css"> body{margin:0;} .item1{ width:200px; height:300px; border:2px solid #f73bd6; padding:100px 0 0 0; } .item2{ width:150px; height:200px; margin:150px 0 0 0; border:2px solid #f73bd6; } </style></head><body> <div class="item1"> <div class="item2"></div> </div></body></html>
IE 以外のブラウザ (IE8 以上でも同じ効果があります) でのテストの結果は次のとおりです:
The IE7での効果は以下の通り:
<= IE6で表示される効果は以下の通り(デフォルトで親ボックスが開きます):
IE8でのdivの最小(最大)幅と高さについて(>=) 4 つの属性 min-height、maxheight、min-width、および max-width は、上記のブラウザーと非 IE ブラウザーの両方に実装されます。
次のコードを見てください:
<style type="text/css"> *{margin:0;padding:0;} div{ width:300px; height:200px; background-color:#9feb3d; } body{ border:5px solid #eb3dda; background-color:#3d3deb; } </style><body> <div> <ul> <li>你是第1个</li> <li>你是第2个</li> <li>你是第3个</li> <li>你是第4个</li> <li>你是第5个</li> </ul> </div></body>
そして、コードのレンダリングは次のとおりです:
上記から、body は次のとおりであることがわかります。特別な div (ボックス)。その背景色は余白まで広がります。
配置と位置に関する他の特別な CSS ルールが使用されない場合の、さまざまな要素の配置ルール。
float 属性は、要素がどの方向に浮動するかを定義します。歴史的に、このプロパティは常に画像に適用され、テキストが画像の周りを回り込むようにしていましたが、CSS では任意の要素をフローティングにすることができます。フローティング要素は、要素のタイプに関係なくブロック レベルのボックスを作成し、その幅はコンテンツの幅によって決まります。次のコードを見てください:
<body> <span class="test-float1">你好吧</span> <span class="test-float2">我是还是吧</span></body>
test-float1および.test-float2にそれぞれスタイルを適用します。コードは次のとおりです。
上記のコードから、inline 要素である span には元々 width 属性と height 属性がありませんが、inline 要素で float 属性が使用されると、要素
には幅と高さの属性があります。🎜注: 🎜🎜 🎜 🎜 行上に浮動要素用のスペースがほとんどない場合、要素は次の行にジャンプし、特定の行に十分なスペースができるまでこのプロセスが続きます。 🎜
浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样。
看下面的一段代码:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>TestFloat</title> <style type="text/css"> body{ margin:0; } .item1, .item2, .item3, .item4{ width:200px; height:100px; background-color:#d8f73b; margin:10px 0 0 0; } .item1{ float:right; } .item2{ /*float:left;*/ } </style></head><body> <div id="body-div"> <div class="item1">item1</div> <div class="item2">item2</div> <div class="item3">item3</div> <div class="item4">item4</div> </div></body></html>
这个时候看到页面的结果有一个很明显的bug,如下图:
可以很明显的看到在浮动的item1和item2有一个间隔没有在一条水平线上。
这个时候就回到了我们开头的问题,我们给父级的div盒子添加overflow属性触发父级div的BFC。代码如下:
<style type="text/css"> body{ margin:0; } //触发父级元素的BFC #body-div{ overflow:hidden; } .item1, .item2, .item3, .item4{ width:200px; height:100px; background-color:#d8f73b; margin:10px 0 0 0; } .item1{ float:right; } .item2{ /*float:left;*/ } </style>
效果如下图:
有关BFC的定义:
BFC(W3C CSS 2.1 规范中的一个概念)就是所谓的Block formatting contexts (块级格式化上下文)。创建了 BFC的元素就是一个独立的盒子,里面的子元素不会在布局上影响外面的元素,反之亦然,同时BFC仍然属于文档中的普通流。
那么怎么触发BFC呢?
注意:
display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是 display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。
fieldset 元素在www.w3.org里目前没有任何有关这个触发行为的信息,直到HTML5标准里才出现。有些浏览器bugs(Webkit,Mozilla)提到过这个触发行为,但是没有任何官方声明。实际上,即使fieldset在大多数的浏览器上都能创建新的块级格式化上下文,开发者也不应该把这当做是理所当然的。CSS 2.1没有定义哪种属性适用于表单控件,也没有定义如何使用CSS来给它们添加样式。用户代理可能会给这些属性应用CSS属性,建议开发者们把这种支持当做实验性质的,更高版本的CSS可能会进一步规范这个。
BFC的特性:
1)块级格式化上下文会阻止外边距叠加当两个相邻的块框在同一个块级格式化上下文中时,它们之间垂直方向的外边距会发生叠加。换句话说,如果这两个相邻的块框不属于同一个块级格式化上下文,那么它们的外边距就不会叠加。2)块级格式化上下文不会重叠浮动元素根据规定,一个块级格式化上下文的边框不能和它里面的元素的外边距重叠。这就意味着浏览器将会给块级格式化上下文创建隐式的外边距来阻止它和浮动元 素的外边距叠加。由于这个原因,当给一个挨着浮动的块级格式化上下文添加负的外边距时将会不起作用(Webkit和IE6在这点上有一个问题——可以看这 个测试用例)。3)块级格式化上下文通常可以包含浮动触发了BFC的话,就不会被float元素覆盖,当子元素全部浮动的时候也能够正确地包含了
深入研究浮动:
来看下面的一段代码:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> body{margin:0;} #body-div{ background-color:#ffff99; border:1px solid #111111; padding:5px; } #body-div div{ padding:10px; margin:15px; background-color:#90baff; } #body-div p{ border:5px dashed #111111; background-color:#ff90ba; } .item1{ border:5px dashed #111111; /*float:left;*/ } .item2{ border:5px dashed #f73b4d; } .item3{ border:5px dashed #0000CD; } </style></head><body> <div id="body-div"> <div class="item1">Box-1</div> <div class="item2">Box-2</div> <div class="item3">Box-3</div> <p>让我们更详细地看看浮动和清理。假设希望让一个图片浮动到文本块的左边,并且希望这幅图片和文本包含在另一个具有背景颜色和边框的元素中。您可能编写下面的代码:让我们更详细地看看浮动和清理。假设希望让一个图片浮动到文本块的左边,并且希望这幅图片和文本包含在另一个具有背景颜色和边框的元素中。您可能编写下面的代码:让我们更详细地看看浮动和清理。假设希望让一个图片浮动到文本块的左边,并且希望这幅图片和文本包含在另一个具有背景颜色和边框的元素中。您可能编写下面的代码:</p> </div></body></html>
显示效果如下图:
.item1{ border:5px dashed #111111; float:left; }
效果如下图:
可以看到标准流中的Box-2的文字在围绕着Box-1排列,而此时的Box-1的宽度不再伸展,而是能容纳下内容的最小宽度。因为此时的Box-1已经脱离了标准流,标准流中的Box-2会顶到原来Box-1的位置(也就是Box-2的左边框和Box-1的左边框重合)此时Box-2的文字会围绕着Box-1排列。
.item2{ border:5px dashed #f73b4d; float:left; }
效果如下图:
这是很容易看出Box-3和Box-1的左边框重合。Box-3的文字围绕Box-2,并且Box-1和Box-2之间的空白是两者之间的margin产生的。
.item3{ border:5px dashed #0000CD; float:left; }
效果如下图:
这个时候可以很明显的看出三个浮动的盒子(都脱离文档流)都被P标签的盒子所包围,并且被文字环绕。
.item3{ border:5px dashed #0000CD; float:right; }
效果如下图:
这个时候当我把浏览器窗口的宽度逐渐的缩小到不能容纳三个div宽度的时候,会有什么效果呢?如下图:
注意:
这种效果我只在IE浏览器(<=IE8的浏览器中出现更怪异的情况)里面测试的时候可以小到让Box-3换行。
在mac下得chrome,firefox和safari当窗口缩小到一定的宽度的时候,就无法在缩小宽度。无法出现Box-3被挤到下一行的情况。
如下图:
这时如果我们设置item2右浮动item3左浮动当我缩小浏览器窗口的时候,会出现如下的情况(mac下chrome和safari中仍旧是之上的情况,缩小到一定宽度无法再缩小)。
由此我们可以得出一个结论:
当浮动的元素在一行无法显示完全时,元素会按照普通流的顺序(Dom排列顺序)被挤到下一行。
增加Box-1的高度,当缩小浏览器的宽度的时候,会出现如下的现象:
主要是因为这个时候Box-3的边缘被Box-1的边缘卡住的缘故。
如下图红色的地方会有三个margin值:
使用CSS属性Clear,它有三个值left,right,both。
如我们取消p元素左右两侧的浮动:
代码如下:
#body-div p{ border:5px dashed #111111; background-color:#ff90ba; clear:both; }
效果如下:
当然浮动对父级元素也会带来影响,比如说伟大的“塌陷”,看代码:
<style type="text/css"> body{margin:0;} #body-div{ background-color:#ffff99; border:1px solid #111111; padding:5px; } #body-div div{ padding:10px; margin:15px; background-color:#90baff; } #body-div p{ border:5px dashed #111111; background-color:#ff90ba; clear:both; } .item1{ border:5px dashed #111111; float:left; height:30px; } .item2{ border:5px dashed #f73b4d; float:left; } .item3{ border:5px dashed #0000CD; float:left; } </style>
效果如下图:
所有子元素的浮动不会将父级元素的高度撑开。
那么怎么解决这个问题呢?
一个很古老的办法就是在所有子元素的末尾添加一个空的div,并且设置它的clear:both。看代码如下:
#body-div .clear-float{ clear:both; border:0; padding:0; margin:0; }
效果如下:
其实我在IE各版本浏览器和非IE浏览器中测试的效果都是如上面的效果可意很容易的发现父级的div盒子并没有被完全的撑开。
不过有大神已经研究出了clearfix的写法,可以达到最合理的效果,主要目的就是触发父级盒子自身的BFC。
版本一:
.clearfix:after { content: "\200B"; display: block; height: 0; clear: both; } .clearfix { *zoom: 1;/*IE/7/6*/ }
content:”\200B”;这个参数,Unicode字符里有一个“零宽度空格”,即 U+200B,代替原来的“.”,可以缩减代码量。而且不再使用visibility:hidden。
版本二:
.clearfix:before, .clearfix:after { content: ""; display: table;}.clearfix:after { clear: both;}.clearfix {*zoom: 1; /*IE/7/6 */}
经过测试在IE的各个版本的浏览器中和非IE浏览器都能够正常的得到结果。
做认为对的事情,如果可能是错的,那就做认为自己承受得起的事情! 个人主页 · 我的文章 · 3 ·