【从0到1学Web前端】CSS定位问题一(盒模型,浮动,BFC) 分类: HTML+CSS 2015-05-27 22:24 813人阅读 评论(1) 收藏

引子:

在谈到css定位问题的时候先来看一个小问题:css

已知宽度(假如:100px)div框,水平居中,左右两百年的分别使用div框填充.且左右div自适应.html

效果以下图:
这里写图片描述css3

这个问题的难点主要是浏览器宽度未知,且两边div自适应宽度.web

第一种实现方法,是借助css3的新属性calc,实现代码以下:chrome

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;}

第二种实现方式就是借助与display属性,将全部的div框具备table的单元格的属性.
代码以下:浏览器

* {
    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%使左右的单元格平分剩下的宽度.markdown


1.盒模型

盒模型又分IE盒模型和非IE盒模型:
看下面的一张图(来自维基百科):布局

这里写图片描述
由上面的图能够知道IE和非IE盒模型的区别主要是计算元素的宽度和高度不同。测试

  1. IE浏览器: margin-left+width+margin-right
  2. 非IE浏览器:margin-left+border-left+padding-left+width+padding-right+border-right+margin-right

看一段代码:spa

<!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属性时,结果正常。

以下图:
这里写图片描述

这是为何呢?

overflow 样式值为 非 visilbe 时,其实是建立了 CSS 2.1 规范定义的 Block Formatting Contexts。建立了它的元素,会从新计算其内部元素位置,从而得到确切高度。这样父容器也就包含了浮动元素高度。这个名词过于晦涩,在 CSS 3 草案中被变动为名词 Root Flow,顾名思义,是建立了一个新的根布局流,这个布局流是独立的,不影响其外部元素的。实际上,这个特性与 早期 IE 的 hasLayout 特性十分类似。

通过测试在IE8以上的浏览器表现与chrome和firefox浏览器表现效果相同。可是在IE7如下浏览器不用设置这个属性就能够表现正常的效果。以下图:

这里写图片描述

很明显发现的一个问题就是IE8(包括IE8)以上浏览器的background-color是border+padding+content.而IE8(不包括)是padding+content

再来看一个示例,代码以下:

<!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也一样的效果)中测试的结果以下:

这里写图片描述

在IE7中的效果以下图:
这里写图片描述

在<=IE6之下显示的效果以下(默认会将父级框撑开):

这里写图片描述

关于div的最小(最大)宽度和高度在IE8(>=)之上和非IE浏览器上都实现了min-height,maxheight,min-width,max-width这四个属性。

关于body的问题:

看下面一段代码:

<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(盒子)。它的background-color会延伸到margin。

标准流的概念:

在不使用其余的与排列和定位相关的特殊CSS规则时,各类元素的排列规则。


2.浮动

float 属性定义元素在哪一个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素均可以浮动。浮动元素会生成一个块级框,而不论它自己是何种元素,且浮动元素的宽度是根据内容的宽度肯定的。

看下面的一段代码:

<body>
    <span class="test-float1">你好吧</span>
    <span class="test-float2">我是仍是吧</span>
</body>

而后分别对.test-float1和.test-float2应用样式,代码以下:

*{padding:0;margin:0px;}
        span{ background-color:#f73bd6; margin:0 0 0 10px; }
        .test-float1{ float:left; height:100px; width:20px; }
        .test-float2{ /*float:left;*/ height:100px; width:20px; }

效果以下:

这里写图片描述

由上面的代码咱们能够得出一个结论,span做为一个行内元素原本是没有width和height属性的,可是当对行内元素使用float属性后,该元素具备了width和height属性

注意:

假如在一行之上只有极少的空间可供浮动元素,那么这个元素会跳至下一行,这个过程会持续到某一行拥有足够的空间为止。

浮动的框能够向左或向右移动,直到它的外边缘碰到包含框或另外一个浮动框的边框为止。因为浮动框不在文档的普通流中,因此文档的普通流中的块框表现得就像浮动框不存在同样。

看下面的一段代码:

<!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呢?

  1. float 除了none之外的值
  2. overflow 除了visible 之外的值(hidden,auto,scroll )
  3. display (table-cell,table-caption,inline-block)
  4. position(absolute,fixed)
  5. fieldset元素

注意:

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>

显示效果以下图:

这里写图片描述

2.1为Box-1设置浮动

.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排列。

2.2为Box-2设置浮动

.item2{ border:5px dashed #f73b4d; float:left; }

效果以下图:

这里写图片描述

这是很容易看出Box-3和Box-1的左边框重合。Box-3的文字围绕Box-2,而且Box-1和Box-2之间的空白是二者之间的margin产生的。

2.3为Box-3设置浮动

.item3{ border:5px dashed #0000CD; float:left; }

效果以下图:

这里写图片描述

这个时候能够很明显的看出三个浮动的盒子(都脱离文档流)都被P标签的盒子所包围,而且被文字环绕。

2.4设置Box-3浮动的方向

.item3{ border:5px dashed #0000CD; float:right; }

效果以下图:

这里写图片描述

这个时候当我把浏览器窗口的宽度逐渐的缩小到不能容纳三个div宽度的时候,会有什么效果呢?以下图:

这里写图片描述

注意:

这种效果我只在IE浏览器(<=IE8的浏览器中出现更怪异的状况)里面测试的时候能够小到让Box-3换行。

在mac下得chrome,firefox和safari当窗口缩小到必定的宽度的时候,就没法在缩小宽度。没法出现Box-3被挤到下一行的状况。

以下图:

这里写图片描述

这时若是咱们设置item2右浮动item3左浮动当我缩小浏览器窗口的时候,会出现以下的状况(mac下chrome和safari中仍旧是之上的状况,缩小到必定宽度没法再缩小)。

这里写图片描述

由此咱们能够得出一个结论:

当浮动的元素在一行没法显示彻底时,元素会按照普通流的顺序(Dom排列顺序)被挤到下一行。

2.5浮动的边界

增长Box-1的高度,当缩小浏览器的宽度的时候,会出现以下的现象:

这里写图片描述

主要是由于这个时候Box-3的边缘被Box-1的边缘卡住的缘故。

以下图红色的地方会有三个margin值:

这里写图片描述

2.6取消浮动的影响

使用CSS属性Clear,它有三个值left,right,both。

如咱们取消p元素左右两侧的浮动:

代码以下:

#body-div p{ border:5px dashed #111111; background-color:#ff90ba; clear:both; }

效果以下:
这里写图片描述

2.7浮动的影响

固然浮动对父级元素也会带来影响,好比说伟大的“塌陷”,看代码:

<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浏览器都可以正常的获得结果。

这里写图片描述

推荐阅读:

清除浮动:

http://mp.weixin.qq.com/s?__biz=MjM5MzMyNzg0MA==&mid=205433384&idx=2&sn=dbee05fdab1039a1bfa8d5e3dbbec76b&scene=5#rd

深刻理解BFC:

http://www.cnblogs.com/v10258/p/3530290.html

相关文章
相关标签/搜索