什么是浮动?html
CSS中的一些元素是块级元素,表示它们会自动另起一行。web
举个例子,若是你建立了两个段落,每一个段落都只有一个单词。这两个单词不会靠在一块儿,而是会各自占据一行。浏览器
另外一些元素是行内元素,表示它们和前面的内容位于相同的一行。布局
举个例子,<a>能够出如今另外一个元素中,好比<p>,这不会产生多余的空格或者出现换行。spa
欺骗这种布局模型的一种方式是使用浮动,浮动可让一个元素移到它所在行的某一边,使得其余内容沿着该元素的边缘向下流。3d
一个典型的例子是你想要一张图片和一个段落并排出现,而不是一上一下排列。首先咱们先来建立HTML:code
<img src="http://lorempixum.com/200/200/" /> <p>Lorem ipsum...</p>
单独这段代码并不能实现咱们想要的效果。<p>是一个块级元素,它会独占一行,因此图片和段落是一上一下展示的。 htm
经过让图片向右浮动能够改变这种行为,以下:blog
img { float: right; margin: 20px; }
这样,图片就跑到右边去了,而段落则沿着图片的左边向下流式布局。图片
如今发生了一件有趣的事,当这张图片浮动后,其余的内容就会想办法尽量的包围它。若是咱们resize容器或者浏览器窗口,让它更窄,这段文本就会发生重排(reflow),这样它就永远不可能接触到图片。
盒模型如何工做
也许你已经对上面所讲的知识有了深入的理解。可是,为了彻底掌握浮动,你须要更加深入的理解两个元素如何互相做用。举个例子,若是咱们在段落和图片之间加一个边距会发生什么?
p {margin: 20px;}
可是呢,这么写并不会在图片和段落之间产生额外的空间。实际上,咱们须要给图片加margin:
img {margin: 20px;}
也许你会问为何呢?为何增长<p>的margin不会增长图片和段落的间距呢?
缘由是咱们没有理解<p>的盒模型。
若是如今你对布局产生了一些疑虑,能够试着加一个或者两个border,看看会发生什么。下面给<p>加border:
p {
border: solid 1px black;
}
如你所见,图片实际上位于<p>盒模型的内部!这就能够解释刚才的margin问题。咱们加到<p>上的margin实际上是做用于图片的右侧,这就是为何它不能增长图片和段落之间的距离!
若是咱们想改变这种行为,使得段落不会包围图片,咱们应该让段落向左浮动,并设置一个宽度(若是不设置,<p>的宽度默认是100%,这样就不会和图片紧挨着了,由于若是段落很长,它会跑到下一行)。
img {
float: right;
margin: 20px;
}
p {
float: left;
width: 220px;
margin: 20px;
}
疯狂的浮动规则
如今你知道什么是浮动了,而且知道浮动如何影响相关元素的盒模型。接下来要说的也许不少人都不了解:如何调整浮动元素的位置。
web开发中不少人会给<li>使用浮动。下面来看一个例子:
<ul> <li><img src=""/>1</li> <li><img src=""/>2</li> <li><img src=""/>3</li> <li><img src=""/>4</li> <li><img src=""/>5</li> <li><img src=""/>6</li> <li><img src=""/>7</li> </ul>
全部<li>默认应该是垂直方向上排列的,这就表示<li>是块级元素。即便图片是行内元素,它也会被它的父级块级元素管理。为了解决这个问题,咱们让<li>向左浮动。当一行内的多个<li>被浮动后,它们会产生相似行内元素的流式布局。然而,正如你即将看到的,它们有一些关键的不一样。
li {
float: left;
margin: 4px;
}
如今,若是全部图片的高度相同,就会产生下面的效果。
可是,咱们的图片高度不是同样的,一些是100px,另外一些是150px。这就引发了一些严重的问题!
当我第一次看到这个效果,我蛋疼了。为何图片4跑到右边去了?它不是应该尽量的向左浮动么?若是咱们放弃浮动而使用display:inline,结果会大不同。
li {
display: inline;
}
这个例子中,图片默认是垂直居底(bottom)对齐。这和咱们以前的例子不一样,为了解决对齐问题,咱们添加一行CSS。
img {
vertical-align: top;
}
由此可知,使用display:inline 能够更容易猜到<li>的排列结果。当水平方向没有多余的空间时,下个元素就会另起一行。
浮动为何不能实现这种效果呢?
CSS规范对于浮动行为归纳了9个规则。但问题是,只有规范的做者和那些无聊的人才能理解这些规则。下面摘录了其中一个规则:
“If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.”
对于这些规则,也许你比我理解的更深,但说实话,这些规则让我很是蛋疼。为了简化它,Josh Johnson给出了他的9条规则(注:我以为这位仁兄的9条规则依然很啰嗦,我再给精简一下):
1. 浮动元素的活动区域
仅限于它的父容器元素,不会超出父容器
2. 浮动元素的位置
水平方向:尽量居左或居右,若是它前面还有浮动元素,会跟在它后面,若是超出该行就会换行
垂直方向:尽量的居顶
关于水平方向的位置,须要注意如下几点:
1) 向左浮动的元素不会出如今向右浮动的元素的右侧
关于垂直方向的位置,须要注意如下几点:
1) 浮动元素不会比容器的顶部还高
2) 浮动元素不会比前一个块级元素或浮动元素更高
3) 浮动元素不会比前一个行内元素更高
在布局时,垂直方向的规则比水平方向的优先级更高
总的来讲就是,浮动元素会移到左侧或右侧。除非该元素前面还有一个浮动元素,这时它就会紧挨着前面的元素。
真正让人迷惑的是:浮动元素会尽量的居顶,而且垂直定位规则比水平浮动规则的优先级更高。
在前面的例子中,图片2撑高了该行的高度,因此在放完图片3后,仍然有足够的垂直空间放置图片4。
记住,当你有一个浮动元素(不位于尾行)时,它后面的浮动元素占用的垂直空间必须大于或等于它才会触发换行。
浮动顺序
举个例子,咱们有6张图片的一个列表。
<ul> <li><img src="http://placehold.it/100x100&text=1"/></li> <li><img src="http://placehold.it/100x100&text=2"/></li> <li><img src="http://placehold.it/100x100&text=3"/></li> <li><img src="http://placehold.it/100x100&text=4"/></li> <li><img src="http://placehold.it/100x100&text=5"/></li> <li><img src="http://placehold.it/100x100&text=6"/></li> </ul>
若是咱们向左浮动图片,它们就会按照原来的顺序排列。但若是向右浮动呢?
能够发现,第一张图片占据了最右的位置。相似的,换行后,第四张图也占据了最右的位置。这就是为何你不多看到导航栏的列表项会向右浮动的缘由。
清除浮动
使用浮动能够方便的实现一些布局,好比建立n栏内容。可是呢,一旦使用浮动就会影响文档正常的流式布局。好比,刚才那个例子中,咱们想在列表下方加上一个段落。
这个结果也许不是你想要的。这里的解决方法是使用 clear 属性,它的做用是清除该元素某侧的浮动。好比,咱们对第二个列表项使用clear:left
ul li:nth-child(2) {
clear: left;
}
这段代码告诉浏览器第二项的顶部必须比它前面的浮动元素的底部更低。若是全部列表项是向右浮动的,则须要使用clear: right
加上段落文本再看
很明显这依然不是咱们想要的效果,解决方法是给段落使用clear,这会使得段落出如今浮动元素的下方而不是与它们相邻。
p {
clear: both;
}
其实这里咱们只须要清除左侧的浮动便可,可是当一个开发者为了确保清除了全部浮动,clear:both是很经常使用的一种方法。
浮动的问题和clearfix
当一个元素只包含浮动元素时,该容器元素会出现高度重叠(和高度为0的效果同样,即高度的顶边和底边重叠)。为了演示这个现象,咱们仍是使用刚才的例子,只是给列表加一个背景色。
ul {
background: gray;
}
若是列表项没有浮动,能够看到整个列表都是灰色的,而列表项则是从上到下排列。
如今咱们浮动全部列表项,这时<ul>只包含浮动的元素,因此它的高度重叠了,新手确定会好奇背景色到底哪去了.
解决这个问题有好几种方法,最简单的一种是直接给容器元素设置高度。
ul {
height: 300px;
}
这样背景色又回来了。可是,这种方法经常不能让咱们满意,由于当咱们须要容器的高度和内容自适应时,这种方法彻底无效。若是咱们再加上三个列表项,这个高度又不够了。
召唤clearfix
如今该轮到clearfix登场了,它经过clear属性解决了高度重叠的问题。
咱们经常会建立一个空元素(一般是div),它和浮动元素同级,而后给它设置class为“clearfix”。回到CSS,咱们加上这样一行样式:
.clearfix {
clear: both;
}
这样就解决了高度的问题。
说下原理:咱们知道当元素只包含浮动元素时,高度发生重叠(效果和高度为0同样),这时该元素有了一个子元素,即便它是个空元素,但它没有浮动,并且还清除了全部浮动,因此这个空元素会出如今全部元素的下方,从而撑起了容器的高度,因而height:auto恢复正常了。
这种方法的缺点是,HTML中多了一个额外的元素,不符合语义化的思想。
新的解决方法是使用 overflow 属性,若是你设值为hidden 或 auto,也能够解决高度重叠的问题。
ul {
overflow: auto;
}
这种方法更简单也更优雅,可是还有个问题要说下,若是容器元素必须设置为overflow: visible,你又该怎么办呢?
方法是首先使用 :before 和 :after 在元素内建立一些不浮动的东西,但实际上你并不但愿出现任何多余的东西,因此咱们设置一个空字符串,可是要设置display:table,这样就建立了一个匿名单元格(是否是想起了<td></td>?),最后使用老办法,清除浮动。
为了兼容老版本的IE,使用它特有的zoom:1清除浮动。
/* For modern browsers */
.cf:before,
.cf:after {
content:"";
display:table;
}
.cf:after {
clear:both;
}
/* For IE 6/7 (trigger hasLayout) */
.cf {
zoom:1;
}