CSS的浮动和定位布局详细(全)

15,501 阅读17分钟

浮动

浮动介绍

浮动是网页布局中非常重要的一个属性。那么浮动这个属性一开始设计的初衷是为了网页的文字环绕效果,如图所示:

如果我们用之前讲解的内容,来实现上述显示的效果,这是很难实现的!!!

另外之前咱们学习了标签的分类,每类标签都是有它自己的特点,比如块级标签独占一行,哎呀,突然有个idea,如果让两个div在一排内显示,那怎么办,可能有的同学又说了,老师,display属性啊,把他们设置成inline-block。

好吧,同学,如果你能想到这里,证明对咱们的知识点理解的还算透彻,但是呢,你又会发现,如果用你刚刚那种效果展示,如图所示:

仅仅的这点间隙,到底是多大呢,如果我们在一行内计算整个盒模型的宽度的话,是否又计算的精准呢?所以,你意淫出来的想法是不对的。

总结:如果想实现网页中排版布局,比如一行内显示对应的标签元素,可以使用浮动属性。浮动可以实现元素并排。

浮动属性

浮动:css样式表中用float来表示,它有

属性值描述
none表示不浮动,所有之前讲解的HTML标签默认不浮动
left左浮动
right右浮动
inherit继承父元素的浮动属性

看个栗子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>浮动属性用法</title>
	<style type="text/css">
		.left{
			width: 200px;
			height: 200px;
			background-color: red;
			color: #fff;
            /*左浮动*/
             float:left;
			
		}
		.right{
			width: 200px;
			height: 200px;
			background-color: green;
			color: #fff;
            /*右浮动*/
             float:right;
		}
		

	</style>
</head>
<body>
	<div class="left">左边的盒子</div>
	<div class="right">右边的盒子</div>
</body>
</html>

观察.left盒子有收缩现象,并且往左边靠。.right也有收缩现象,往右边靠。

效果模拟展示:

浮动的现象

我们之前说浮动的设计初衷是为了做”文字环绕效果“。那么我们就来看一下如果对盒子设置了浮动,会产生什么现象?

  • 浮动的元素脱离了标准文档流,即脱标
  • 浮动的元素互相贴靠
  • 浮动的元素会产生”字围“效果
  • 浮动元素有收缩效果

标准文档流

文档流指的是元素排版布局过程中,元素会默认自动从左往后,从上往下的流式排列方式。

即不对页面进行任何布局控制时,浏览器默认的HTML布局方式,这种布局方式从左往右,从上往下,有点像流水的效果,我们称为流式布局

脱标

举个栗子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>脱标</title>
	<style type="text/css">
		.box1{
			width: 200px;
			height: 200px;
			background-color: red;
			float: left;
			color: #fff;
		}
		.box2{
			width: 400px;
			height: 400px;
			background-color: green;
			color: #fff;

		}
	</style>
</head>
<body>
	<div class="box1">左青龙</div>
	<div class="box2">右白虎</div>
</body>
</html>

效果:

会发现红色盒子压盖住了黄色的盒子,为什么会出现这种现象呢?

因为:在标准文档流下,左青龙右白虎两个盒子是上下排版,如果对左青龙设置了浮动,那么盒子会脱离了标准文档流,它就不会按照默认的流式排版布局,可以认为这个左青龙盒子浮起来了,不受标准文档流排版布局的约束。那么此时浏览器认为右白虎盒子是标准文档流下的第一个盒子。所以右白虎就渲染到了页面中的第一个位置上。

浮动元素贴靠

看栗子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>浮动元素贴靠</title>
	<style type="text/css">
		.box1{
			width: 100px;
			height: 450px;
			background-color: red;
			float: left;
		}
		.box2{
			width: 200px;
			height: 250px;
			background-color: green;
			float: left;
		}
		.box3{
			width: 300px;
			height: 300px;
			background-color: blue;
			float: left;
		}

	</style>
</head>
<body>
	<div class="box1"></div>
	<div class="box2"></div>
	<div class="box3"></div>

	
</body>
</html>

效果展示:

总结:当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素

字围效果

字围效果之前咱们又讲解,就不一一解释了

收缩效果

如图所示:

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>收缩效果</title>
	<style type="text/css">
		.box1{
			float: left;
			background-color: red;
		}
	</style>
</head>
<body>
	<div class="box1">我有收缩功能</div>
</body>
</html>

会发现,在没有给.box1盒子设置浮动之前,.box1的盒子是占据整一行,一旦设置了浮动那么盒子的宽度是内容的宽度。

浮动的破坏性

看个栗子:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>浮动元素的破坏性</title>
	<style type="text/css">
		.father{
			border: 1px solid red;
		}
		.child{
			width: 200px;
			height: 200px;
			float: left;
			background-color: green;
		}
	</style>
</head>
<body>
	<div class="father">
		<div class="child">儿子</div>
	</div>

</body>
</html>

浮动之前与浮动之后效果展示:

由此可见,浮动之后,蓝色的盒子因为脱离了标准文档流,它撑不起父盒子的高度,导致父盒子高度塌陷。如果网页中出现了这种问题,会导致我们整个网页的布局紊乱。我们一定要去解决这种父盒子高度塌陷的问题。

总结:浮动能网页实现排版布局,但是同样也会给网页带来一定的问题(父盒子高度塌陷),只要我们解决了浮动给网页带来的问题,就能对网页进行高效的排版布局。那么下节课知晓。

清除浮动的方式

上节课,我们知道浮动具有破坏性,它能使父盒子高度塌陷、导致页面紊乱。那么在css布局中对于浮动的解决方案有四种:

  • 父盒子设置固定高度
  • 内墙法
  • 伪元素清除法
  • overflow:hidden

父盒子设置固定高度

代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>浮动元素的破坏性</title>
	<style type="text/css">
		.father{
            /*父盒子设置了固定高度*/
			height: 200px;
			border: 1px solid red;
		}
		.child{
			width: 200px;
			height: 200px;
			float: left;
			background-color: green;
		}
	</style>
</head>
<body>
	<div class="father">
		<div class="child">儿子</div>
	</div>

</body>
</html>

虽然,给父盒子设置了固定高度能暂时解决我们的问题,但是它的使用不灵活,如果未来子盒子的高度需求发生了改变(网页的多处地方),那么我们得手动需要更改父盒子的高度。后期不易维护。

应用:网页中盒子固定高度区域,比如固定的导航栏。

缺点:使用不灵活,后期不易维护

内墙法

所谓内墙法,有一个规则:在浮动元素的后面加一个空的块级元素(通常是div),并且该元素设置clear:both;属性。

clear属性,字面意思就是清除,那么both,就是清除浮动元素对我左右两边的影响。

代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>浮动元素的破坏性</title>
	<style type="text/css">
		.father{
			
			border: 1px solid red;
		}
		.child{
			width: 200px;
			height: 200px;
			float: left;
			background-color: green;
		}
		.clearfix{
			clear: both;
		}
	</style>
</head>
<body>
	<div class="father">
		<div class="child">儿子</div>
		<div class="clearfix"></div>
	</div>

</body>
</html>

应用:网页中应用不多,讲解这个,只是为了引导下一个清除浮动的方式,那才是我们重点要掌握的。

缺点:结构冗余

伪元素清除法

上节课说到内墙法,在浮动元素的后面加一个空的块级元素(通常是div),并且该元素设置clear:both;属性。那么正好在css3的属性用法中整好有个选择器也完全符合这个用法,伪元素选择器

伪元素选择器很简单。就像伪类一样,让伪元素添加了选择器,但不是描述特殊的状态,他们允许您为元素的某些部分设置样式。在这里只介绍一个。

语法:

p::after{
    /*p::after{}一定要有content。表示在p元素内部的最后面的添加内容*/
    content:'...'
}

表示在p标签元素的最后面添加样式。咦….,在….的z后面添加样式,这不正好符合了我们的内墙法的用法么。

代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>浮动元素的破坏性</title>
	<style type="text/css">
		.father{
			border: 1px solid red;
		}
		.child{
			width: 200px;
			height: 200px;
			float: left;
			background-color: green;
		}
		.cleafix:after{
			content:'.';
			display: block;
			clear: both;
			overflow: hidden;
			height: 0;
		}
		
	</style>
</head>
<body>
	<div class="father clearfix">
		<div class="child">儿子</div>
	</div>

</body>
</html>

分别对编写的伪元素清除法一一解释:

.clearfix:after{
    content:'.';
    display: block;
    clear: both;
    overflow: hidden;
    height: 0;
}
  • content:'.';表示给.clearfix元素内部最后添加一个内容,该内容为行内元素。
  • display:block;设置该元素为块级元素,符合内墙法的需求。
  • clear:both;清除浮动的方法。必须要写
  • overflow:hidden;height:0;如果用display:none;,那么就不能满足该元素是块级元素了。overflow:hidden;表示隐藏元素,与display:none;不同的是,前者隐藏元素,该元素占位置,而后者不占位置。

overflow:hidden

CSS属性overflow定义一个元素的内容太大而无法适应盒子的时候该做什么。它是overflow-x和overflow-y的简写属性

属性值描述
visible默认值。内容不会被修剪,会呈现在元素框之外
hidden内容会被修剪,并且其余内容不可见
scroll内容会被修剪,浏览器会显示滚动条以便查看其余内容
auto由浏览器定夺,如果内容被修剪,就会显示滚动条
inherit规定从父元素继承overflow属性的值

代码演示分别看效果:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>overflow属性的用法</title>
	<style type="text/css">
		.box{
			width: 300px;
			height: 300px;
			border: 1px solid red;
			overflow: hidden;
		}
	</style>
</head>
<body>
	<div class="box">
		小学生优秀作文《当领导的好处》
		爸爸当上领导后,从来不敢多说话,生怕给别人带来压力。
		上个月,下属小李叔叔到我家来玩,爸爸随口说了句:“家里没空调,比较热,见笑了。”
		第二天,小李叔叔就带着师傅给我家安装了5匹的大空调!说什么也不肯收钱。
		上个星期,爸爸看到老张伯伯在办公室吃午饭,菜中有煎鱼,随口说了句:“哎呦,真香!”
		当天晚上,老张伯伯给我家送了一箱鲜鱼来。
		有一天晚上,我跟爸爸遛弯儿,路上碰到单位的小王叔叔和他媳妇逛街,爸爸随口称赞道:“哎呦,小王,你媳妇真漂亮!”
		第二天晚上,妈妈不在家,突然听到有人敲门。打开门一看,小王叔叔的媳妇站在门口,见到爸爸就满脸微笑说:“领导,我们家小王说嫂子不在家,让我来陪陪你!”
		当领导真好,怪不得这么多人喜欢当领导!
	</div>
</body>
</html>

效果展示:

滚动效果

设置overflow:scroll;

效果显示:

overflow属性不仅仅有以上效果,那么当一个元素设置了overflow:hidden|auto|scroll属性之后,它会形成一个BFC区域,我们叫做它为块级格式化上下文。BFC只是一个规则。它对浮动定位都很重要。浮动定位和清除浮动只会应用于同一个BFC的元素。

浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。

总结:只要我们让父盒子形成BFC的区域,那么它就会清除区域中浮动元素带来的影响。

代码如下:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>浮动元素的破坏性</title>
	<style type="text/css">
		.father{
			overflow: hidden;
			border: 1px solid red;
		}
		.child{
			width: 200px;
			height: 200px;
			float: left;
			background-color: green;
		}
		
	</style>
</head>
<body>
	<div class="father">
		<div class="child">儿子</div>
	</div>

</body>
</html>

深入理解BFC

了解BFC前先一了解一下Box和Formatting Context

(1)B: BOX即盒子,页面的基本构成元素。分为 inline 、 block 和 inline-block三种类型的BOX

(2)FC: Formatting Context是W3C的规范中的一种概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

常见的 Formatting Context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)

BFC 定义

​ BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

BFC布局规则

1.内部的Box会在垂直方向,一个接一个地放置。

2.Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

3.每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

4.BFC的区域不会与float 元素重叠。

5.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

6.计算BFC的高度时,浮动元素也参与计算

那些元素会生成BFC

1.根元素

2.float属性不为none

3.position为absolute或fixed

4.display为inline-block

5.overflow不为visible

3.定位

定位是一个相当复杂的话题,在去深入理解定位之前,我们先来聊一下之前我们的标准文档流下的布局。

首先,

  • 盒模型,元素的内容宽高、padding、border以及margin
  • 元素的分类:块级元素、行内元素、行内块元素之间的区别。
  • 盒模型的margin,垂直方向上会出现外边距合并的问题

好了,定位的整个想法是允许我们覆盖上述描述的基本标准文档流的行为,以产生有趣的效果。

有个设想。如果你想稍微改变布局中一些盒子的位置,使它们的默认布局流的位置稍微有点古怪,不舒服的感觉呢?定位是你的工具。或者,如果您想要创建一个浮动在页面其他部分顶部的UI元素,并且/或者始终停留在浏览器窗口内的相同位置,无论页面滚动多少?(网页中的小广告,就是靠这个完成的)定位使这种布局工作成为可能。

有许多不同类型的定位,你可以对HTML元素产生效果,要想使某个元素上进行定位,我们使用position属性。

css position属性用于指定一个元素在文档中的定位方式。toprightbottomleft属性则决定了该元素的最终位置。

属性值描述
static默认。静态定位, 指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 toprightbottomleft 和 z-index 属性无效。
relative相对定位。 元素先放置在未添加定位时的位置,在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)
absolute绝对定位。不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并
fixed固定定位。 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变

静态定位

静态定位意味着“元素默认显示文档流的位置”。没有任何变化。

代码演示:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>静态定位</title>
	<style type="text/css">
		.positioned{
			position: static;
			background-color: red;
		}
	</style>
</head>
<body>
	<p class="positioned">我是静态定位的元素</p>
	
</body>
</html>

效果显示:

相对定位

相对定位的元素是在文档中的正常位置的偏移,但是不会影响其他元素的偏移。

举个例子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>相对定位</title>
	<style type="text/css">
		div{
			width: 200px;
			height: 300px;
		}
		.box1{
			background-color: red;
		}
		.box2{
			position: relative;
			top: 30px;
			left: 40px;
			background-color: green;
		}
		.box3{
			background-color: blue;
		}
	</style>
</head>
<body>
	<div class="box1">盒子1</div>
	<div class="box2">盒子2</div>
	<div class="box3">盒子3</div>
</body>
</html>

效果展示:

咦,很酷是嘛?好吧这个结果可能不是你所期待的———为什么它移动到底部和右边呢,我们不是指定顶部和左边么?听起来不合逻辑,但这只是相对定位工作的方式———你需要考虑一个看不见的力,推动定位的盒子的一侧,移动它相反的方向。所以,如果您制定了top:30px;一个里推动框的顶部,使它向下移动30px。

其实说白了,我们得找一个参考的位置,然后进行定位,那么相对定位是以自身原来的位置进行定位的。

总结:

参考点

以自身原来的位置进行定位,可以使用top,left,right,bottom对元素进行偏移

现象

  1. 不脱离标准文档流,单独设置盒子相对定位之后,如果不用top,left,right,bottom对元素进行偏移,那么与普通的盒子没什么区别。
  2. 有压盖现象。用top,left,right,bottom对元素进行偏移之后,明显定位的元素的层级高于没有定位的元素

应用

相对定位的盒子,一般用于子绝父相布局模式的参考。下节课知晓

绝对定位

相对定位的元素并没有脱离标准文档流,而绝对定位的元素则脱离了文档流。在标准文档流中,如果一个盒子设置了绝对定位,那么该元素不占据空间。并且绝对定位元素相对于最近的非static祖先元素定位。当这样的祖先元素不存在时,则相对于根元素页面的左上角进行定位。

举个栗子:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>绝对定位</title>
	<style type="text/css">
		div{
			width: 200px;
			height: 300px;
			border: 3px solid #ff6700;
		}
		.box1{
			position: absolute;
			left: 50px;
			background-color: red;
		}
		.box2{
			background-color: green;
		}
		.box3{
			background-color: blue;
		}
	</style>
</head>
<body>
	<div class="box1">One</div>
	<div class="box2">Two</div>
	<div class="box3">Three</div>
</body>
</html>

效果展示:

绝对定位元素相对于最近的非static祖先元素定位,这句话怎么理解呢?举个栗子吧

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>相对定位</title>
	<style type="text/css">
		body{
			border: 1px solid #000;
		}
		.grandfather{
			position: relative;
			border: 3px solid #237D7C;
		}
		.father{
			position: relative;
			top: 50px;
			left: 50px;
			border: 3px solid purple;
		}
		.box1,.box2,.box3{
			width: 200px;
			height: 300px;
			border: 3px solid #ff6700;
		}
		.box1{
			position: absolute;
			left: 50px;
			background-color: red;
		}
		.box2{
			background-color: green;
		}
		.box3{
			background-color: blue;
		}
	</style>
</head>
<body>
	<div class="grandfather">
		<div class="father">
			<div class="box1">One</div>
			<div class="box2">Two</div>
			<div class="box3">Three</div>
		</div>
	</div>
</body>
</html>

效果显示:

绝对定位的盒子是以最近的非static定位的父元素进行定位,为了演示此效果。特意将网页结构层次增多,并且区分跟body页面左上角的位置,将紫色边框的父元素进行了位置调整,并且将.father.grandfather元素同时设置了相对定位。来完成此效果。

总结:

参考点

相对于最近的非static祖先元素定位,如果没有非static祖先元素,那么以页面左上角进行定位。

现象

  1. 脱离了标准文档流,不在页面中占位置
  2. 层级提高,做网页压盖效果

应用

网页中常见的布局方案:子绝父相

注意:子绝父绝,子绝父固,都是以最近的非static父辈元素作为参考点。父绝子绝,子绝父固,没有实战意义,布局网站的时候不会出现父绝子绝。

因为绝对定位脱离标准流,影响页面的布局。

相反父相子绝在我们页面布局中,是常用的布局方案。因为父亲设置相对定位,不脱离标准流,子元素设置绝对定位,仅仅的是在当前父辈元素内调整该元素的位置。

固定定位

它跟绝对定位基本相似,只有一个主要区别:绝对定位固定元素是相对于html根元素或其最近的定位祖先元素,而固定定位固定元素则是相对于浏览器视口本身。这意味着你可以创建固定的有用的网页效果,比如固定导航栏、回到顶部按钮,小广告等。

让我们举个例子来说明上面的意思。

html:

<div class="outer">
    <p>
        某女买了一件1000块的衣服。我质疑有点贵。

        她说:“贵?我跟你说,这件衣服原价2000块,打了五折之后便宜一半,就等于我赚了1000块!虽然我花出去1000块,但同时我又赚回来了1000块,所以这件衣服相当于是白送,免费。你懂个屁! ”

        我被她的经济数学头脑震惊得久久说不出话来……
    </p>
    <p>
        国家全面放开生育二胎的政策春风送暖,某机关一张姓女公务员前些天终于怀上二胎了,又一次升级为准妈妈。

        老公让她赶紧跟领导说一下,争取减点工作量,好好保胎。

        午饭时,她在食堂恰好碰见领导,难掩一脸的兴奋汇报:“头儿,我刚怀上小二了”!

        周围突然安静下来了。领导楞了半天回过神来,憋出了一句:“你老公知道了吗?”

        她脑抽地答了一句:“是他让我找你的”……

        食堂里瞬间鸦雀无声!
        此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!此处省略5000字!!
    </p>
    <div class="box" id="one">One</div>
</div>

css:

.box {
    background: red;
    width: 100px;
    height: 100px;
    margin: 20px;
    color: white;
}
#one {
    position: fixed;
    top: 80px;
    left: 10px;
}
.outer {
    width: 500px;
    height: 300px;
    overflow: scroll;
    padding-left: 150px;
}

效果显示: