position

concept

  1. absolute

  • 脱离原来位置进行定位

  • 相对于最近的有定位的父级进行定位,若没有则相对于文档进行定位

  • 使用场景:鼠标提示:悬浮在上方,鼠标经过出现,鼠标离开消失

  1. relative

  • 保留原来位置进行定位(仍处于标准文档流)

  • 相对于自己原来的位置进行定位

  • 使用场景:给absolute元素做爸爸

  1. fix(广告)

  • 参照浏览器窗口

  • 使用场景:广告窗口,回到顶部按钮

float

1.介紹

让block元素无视float元素,让inline元素像流水一样围绕着float元素实现浮动布局

2.特性

  • 包裹性

  • 高度塌陷

  • 块状化

  • 没有任何margin合并

2.1 包裹性

所谓"包裹性",其实是由"包裹"和"自适应"两部分组成

  1. 包裹。本例中将浮动元素父元素宽度设置为200px,浮动元素的子元素是一个128px宽度的图片,则此时浮动元素宽度表现为"包裹",也就是里面图片的宽度128px

2)自适应性。在浮动子元素的中增加一些文字

此时,浮动元素宽度就自适应父元素的200px宽度,最终的宽度表现也是200px。如下图所示:

2.2 高度塌陷

float属性有一个著名的特性:会让父元素的高度塌陷。如章节2.1中的效果图,父元素div的高度并没有被子元素撑开(粉色区域)。float给div.son施了个障眼法,让该元素的高度塌陷为0了,这样外层div计算高度时,认为div.son的高度为0,相当于div.son的content的高度为0,则div.father认为其没有子元素,所以产生了高度塌陷。后文中将讲述如何解决高度塌陷的问题。

2.3 块状化

块状化的意思是,一旦元素float的属性不为none,则其display计算值就是block或者table

这里的块状化意思是可以像block元素一样设置宽和高,并不是真正的块元素。 因此,没有任何理由出现下面的样式组合:

2.4 没有任何的margin重叠

在这里,我们将.son类增加margin:10px样式,在浏览器中查看实际效果。

我们增加.son类的margin为10px,在浏览器中查看相邻的.son元素的空白区域的高度是20px,可以发现设置了float属性的元素没有任何的margin重叠,这和普通的元素margin重叠不一样。

什么是外边距(margin)重叠 外边距重叠是指两个或多个盒子(可能相邻也可能嵌套)的相邻边界(其间没有任何非空内容、补白、边框)重合在一起而形成一个单一边界

3.float与流体布局

使用float可以通过破坏正常的文档流实现CSS环绕,但是却带来了高度塌陷的问题!然而我们可以利用float破坏正常文档流的特性实现一些常用的布局:

  • 文字环绕变身-中间内容居中,左中右布局

  • 文字环绕的衍生-单侧固定

和文字环绕效果相比,区别就是.girl多了一个margin-left: 70px,同时图片的宽度设置60px,因此不会发生文字环绕的效果。这里,我们也可以不使用margin-left,改用border-left或者padding-left都可以达到改变content box的尺寸,从而实现宽度自适应布局效果。

4.float的克星

4.1 clear属性

如果单从字面上的意思来理解,clear:left应该是清除左浮动,clear:right应该是清除右浮动,实际上,这种说法是有问题的,因为浮动一直还在,并没有清除!只能清除浮动带来的影响

官方对clear属性的解释是:"元素盒子的边不能和前面的浮动元素相邻"。注意这里的"前面的"3个字,也就是clear属性对"后面的"浮动元素是不闻不问的。clear属性只能清除元素的自身,不能影响其他的元素。接着看下面的这个例子:

如上图所示,box1元素为设置了左浮动,已经脱离了正常的文档流,所以box2能够在box1的底层显示。如果想让box2能够换行排列,则只需要在.box2类中增加clear:left样式即可。如下图所示:

4.2 clear属性的不足

clear属性只对块级元素有效,但是::after等伪元素默认都是内联水平,因此,在实际工作中,我们常常使用下面的代码来清除浮动带来的影响:

由于clear:both作用的本质是让自己不和float元素在一行显示,并不是真正意义上的清除浮动,因此float元素有一些不好的特性依然存在,表现在:

  • 如果clear:both元素前面的元素就是float元素,则设置margin-top无效

在本例中,设置.box2中的margin-top没有任何的效果,如下图所示:

  • clear:both后面的元素依旧可能会发生文字环绕现象。

在本例中,设置clean:both来阻止浮动对后面元素的影响,但是最后的错位效果依然发生了(可以设置.father的字体大小为0,然后设置p标签的字体大小解决错误的问题)。

由此可见,clear:both只能在一定程度上消除浮动的影响,要想完美去除浮动元素的影响,借助其他的手段——BFC

5.CSS世界的结界——BFC

5.1 BFC的定义

BFC全称block formatting contextt,中文为块级格式化上下文。BFC的表现原则为:如果一个元素具有BFC,那么它的内部子元素再怎么翻江倒海,都不会影响外部的元素。因此,BFC元素是不可能发生margin重叠的,另外,BFC元素也可以用来清除浮动的影响。

那么满足什么条件才会有BFC呢?只要满足下面任意一个条件就会触发BFC:

  • html根元素;

  • float的值不为none;

  • overflow的值为auto、scroll或者hidden;

  • display的值为table-cell、table-caption和inline-block中的任何一个;

  • position的值不为relative和static; 触发BFC后,就不需要使用clear:both属性去清除浮动的影响。

5.1 BFC的作用

  • 清除margin重叠

在这种情况下,出现了margin重叠的效果。如下图所示:

利用BFC能消除margin重叠,谨记:只有当元素在同一个BFC中时,垂直方向上的margin才会collapse。如果它们属于不同的BFC,则不会有margin重叠。因此我们可以再建立一个BFC去阻止margin重叠的发生。所以为了让他们的margin变成20px,我们只需要用div,建立一个BFC,令p元素处于不同BFC即可。请看例子:

  • 清除高度塌陷的问题 在上面的章节中,如果子元素设置浮动属性,则父元素就会出现高度塌陷的问题。在这里,我们可以借助BFC消除高度塌陷的问题了,请看下面的这个例子:

从下图中可以看到,设置overflow:hidden样式后就产生了BFC,根据BFC的表现规则,内部元素的样式不会影响外部元素的样式,因此没有出现高度塌陷的问题。

  • 自适应布局(阻止文本换行)

如果我们给.girl元素设置具有BFC特性的属性,如:overflow: hidden就可以实现更健壮、更智能的自适应布局。

这里的.girl元素为了不和浮动元素产生任何交集,顺着浮动边缘形成自己的封闭上下文。

普通元素在设置了overflow:hidden后,会自动填满容器中除了浮动元素意外的剩余空间,形成自适应效果,这种自适应布局和纯流体布局相比:

  • 自适应内容由于封闭而更加健壮,容错性更强;

  • 自适应内容能够填满除浮动元素以外区域,不需要关心浮动元素宽度。

absolute

1.absolute的特性

1.包裹性

在本例中,son1与son的唯一区别是son1的position设置为static。 .father元素的宽度设置为200px,img元素是一个128px宽度的图片,则此时绝对定位元素宽度表现为"包裹性",其宽度也就是里面图片的宽度128px。

由于绝对定位元素宽度表现为"包裹性",因此,下面的CSS写法就是多余的:

2.高度塌陷

基于上图,父元素div的高度并没有被子元素撑开(粉色区域),这种效果可以称为"高度塌陷"。导致高度塌陷的原因是因为浮动元素脱离了正常的文档流,则div.father认为其没有子元素,所以产生了高度塌陷。

如果在.father元素增加子元素,如下:

从图中明显看出文字被图片遮盖了,这一点和float不同。因为,float元素本身仍处于文档流中,文字会环绕着float元素,不会被遮蔽,而设置了absolute的图片元素出现了层级关系,已经脱离了正常的文档流了,从父元素的视点看,图片已经完全消失不见了,因此从最左边开始显示文字,而absolute的层级高,所以图片遮盖了文字。

3.块状化

块状化的意思是,一旦元素position的属性为absolute或者fixed,则其display计算值就是block或者table。

2.absolute流体与相对特性

1.absolute的相对特性

在介绍absolute的相对特性之前,先抛出以下问题: 如果一个元素的定位属性设置成了:position: absolute后,没有设置left/top/right/bottom,并且其祖先元素全部都是非定位元素,请问它将在哪里显示?

包括我自己,在深入了解absolute的特性之前,认为该元素是在浏览器窗口的左上方显示,其实这是对absolute绝对定位属性错误的认识。因此,很多人在使用absolute定位属性的时候,必定先要设置父元素position: relative,同时设置绝对定位元素的left/top/right/bottom,甚至还要设置绝对定位元素层级z-index,实际上,该元素还是在当前的位置。我们拿下面的这个例子验证:

如下图所示,.box元素还是在当前的位置显示,而不是在浏览器窗口的左上方显示:

实际上,absolute是一个相对比较独立的CSS属性,它的样式和行为表现不依赖其他的CSS属性就可以完成。因此,如果元素设置了定位属性为absolute绝对定位,并且没有设置left/top/right/bottom,那么可以将这种定位属性称为“无依赖绝对定位”,其本质就是"相对定位",特点仅仅是脱离文档流,不占据任何CSS流的尺寸空间了。

  1. 各类图标定位

我们以慕课网首页上的课程列表举例:

核心CSS代码如下所示:

完全不需要借助top/right/bottom/left和position: relative的帮助就可以搞定小图标的布局啦。相比使用position:relative和right/top的布局方式,这种布局方式的优点是:

维护成本低。如果后面想删除这个图片,只需要将图标对应的html和css代码删除掉就可以了,不会影响其他的元素 健壮性高。如果图片变大或者文字变长,我们不需要修改小图标的css代码,仍然定位效果良好。

再举一个在实际开发中用的比较多的一个例子,如下图所示,在一段文字的前面有一个图标:

  1. 校验提示错误

在实际开发中,我们有很多表单校验,当校验不通过的时候,会有一些错误提示给用户,如下图所示:

通常,错误提示可以放到input框的下面,但是当出现错误提示的时候,下面的内容会整体下移,当错误提示消失的时候,下面的内容又会整体上移,用户体验不好。还有一种做法是放到input框的右侧显示,但是在默认状态下部容器设置了水平居中, 宽度不大,如果再出现错误提示信息,就会出现容器的宽度不够的问题。此时,我们同样可以借助:"无依赖定位",直接给错误提示信息增加一个CSS类,如下所示:

无论将input框的宽度变大或者变小,提示信息都会跟着input框。相比使用position:relative和right/top的布局方式,这种方法代码量更少、容错性更高、维护成本更低。

2.absolute的流体特性

只有absolute遇到left/top/right/bottom属性的时候,absolute元素才真正变成绝对定位元素。如果用户给absolute至少指定了left/right中的一个,则水平方向的相对特性丢失,垂直方向上继续保持相对特性;如果用户给absolute至少指定了top/bottom中的一个,则保持水平方向上的相对特性,垂直方向上的相对特性丢失。例如:

此时,元素水平方向相对特性丢失,具有了绝对定位特性,而垂直方向的定位依然保持了相对特性。

以上面的这个例子举例,当只有left或者right属性的时候,由于包裹性,此时div的宽度是0。但是,如果同时设置left:0;right:0的时候,宽度表现为"格式化宽度",宽度自适应于.box包含快的content-box,换句话说,如果包含快的content-box宽度发生变化,则.box的宽度也会跟着一起变。举个例子:

如果.box的包含块是根元素,则上面的代码可以让.box元素正好完全覆盖浏览器的可视窗口,同时,如果改变浏览器窗口的大小,.box的大小会随着浏览器的大小自动变化。因此,对于设置了对立定位属性的绝对定位属性,无论设置padding还是margin,其占据的空间一直不变,变化的就是content-box,这就是典型的流体表现特性。流体特性的具体用法在后面会介绍到。

3.absolute与其他属性

1.absolute与text-align

利用text-align可以控制绝对定位元素的位置,实现主窗口右侧的"返回顶部"以及"反馈"等布局的效果。效果图如下:

本例中,利用:before伪元素,在其前面插入一个空格(2002),然后设置text-align: right,则空格对齐主结构的右侧边缘,后面的固定定位元素(同绝对定位元素)由于"无依赖定位"特性,左边缘正好就是主结构的右边缘,自然就跑到主结构的外面显示了,这种布局在实际开发中用处非常大.

2.absolute与clip

在实际开发过程中,很多时候我们为了更好的SEO和无障碍识别,都会将页面中的一些元素隐藏,例如隐藏下面代码中的本网站名字这几个字:

为了隐藏上面的文字,有以下几种方案可以供我们选择:

  • 使用display:none或者visibility:hidden。缺点:屏幕阅读设备会忽略这些文字;

  • 使用text-align缩进。缺点:如果缩进过大到屏幕之外,屏幕阅读设备也是不会读取的;

  • 使用color: transparent。原生IE8浏览器器并不支持,并且还是能够选中文本。 借助absolute和clip(关于clip用法不熟悉的同学可以自己百度下,很简单,注:clip只对绝对定位和固定定位的元素生效)这两个属性,能够同时满足视觉上隐藏- 和屏幕阅读设备能够读取的要求,核心代码如下:

3.absolute之margin:auto居中

在实际工作开发中,可能我们用的最多的是下面的方式来实现元素的水平垂直居中效果,核心代码如下:

此方法有一个不足之处就是需要提前知道元素的尺寸,否则无法控制margin负值的大小。

如果不知道元素的尺寸,可以使用transform: translate(-50%, -50%)代替margin负值,然而这种方法存在一定的兼容性问题,IE9(-ms-), IE10+以及其他现代浏览器才支持,在一定的场景下会导致微信闪退的问题。

在介绍下另外一种方法前,我们首先熟悉下margin: auto的填充规则:

  • 如果一侧定值,一侧auto,则auto为剩余空间大小;

  • 如果两侧都是auto,则平分剩余空间。

因此,利用绝对定位absolute元素的流体特性和margin: auto的自动分配特性能够实现水平垂直居中的效果,核心代码如下:

这种方法兼用性好,并且需要提前知道元素的尺寸,减少了依赖,后期维护改动的地方少.

relative

在本例中,使用.element1.element2两个CSS类达到的效果不一样,使用margin负值改变元素的位置后,后面元素的位置跟着变化,而使用position: relativetop负值改变元素的位置,后面元素的位置并没有发生改变。其实,这个例子说明了relative定位的两大特性:

1)相对自身。使用relative定位的元素,其相对的是自身进行偏移。 2)无侵入性。使用relative定位的元素,可以理解为产生了"幻影",其真身依然在原来的位置上,所以并不会影响页面中其他的元素的布局。本例中,使用relative这几个字依然在原来的位置上,而使用margin这几个字则偏移了原来的位置。

1 relative的限制作用

1 relative对absolute的限制作用

我们知道,absolute定位的是其第一个祖先元素定位属性不为static属性,如果没有relative或者fixed定位的情况下,给absolute添加top/left、right/bottom等属性可以发生偏移,如下:

时,absolute元素就会迅速定位到局里浏览器左侧10像素,顶部10像素的地方。但是如果给父元素添加position: relative之后,则absolute的偏移能力被父元素限制住了,如下图所示:

2 relative对overflow的限制作用

在这个例子中,.box的宽和高都是50px,而.son元素的宽和高都是100px,虽然.box元素设置了overflow:hidden,但依然限制不了.son元素的大小,其宽和高都是100px,而当.box设置了定位属性relative后,.son元素的宽和高乖乖的变成了50px。如下图所示:

3 relative对层级z-index的限制作用

下面抛出一个问题,如果设置了对立属性top/bottom、left/right的相对定位元素和绝对定位元素,它们是如何表现的?

在CSS深入理解之absolute定位这篇文章中,我们知道绝对定位元素表现的是拉伸特性,从而可以保持流体特性,但是相对定位却是"你死我活"的状态,也就是说,只有一个方向的属性会生效,当top/bottom元素同时使用的时候,top生效,当left/bottom同时使用的时候,left生效。请看下面的这个例子

虽然同时设置了top/bottom对立属性,但是生效的却是top,如下图所示:

因此,下面有些代码没有必要:

2 相对定位relative的使用原则-最小化

虽然relative定位很好用,并且使用的频率很高,但是根据张鑫旭大神总结的布局实践原则,最好基于以下原则为好:

尽量避免使用relative,如果要定位某些元素,看能否使用"无依赖的绝对定位"实现; 如果使用场景受限,一定要使用relative,则务必使relative最小化。

比如,我们想在某个模块的右上角定位一个图标,如果让你去布局实现的话,你该如何布局呢?十有八九会如下面的方式实现:

但是,我们可以采用"relative的最小化使用原则"的方式实现,其代码如下面的方式实现:

那么,基于"relative的最小化使用原则"的房还是实现有什么好处呢?原因及好处如下: relative定位元素的层叠水平提高了(敬请期待后续的文章),如果其子元素越多,则影响的范围越广,从项目和可维护性的角度来看,如果后期不需要这个小图标了,我们可以大胆地干调relative单元的元素即可,其他的元素则不需要任何的修改,然后放心的去陪妹子了。但是,如果relative在最外层的容器上,你敢删除吗?你敢放心的去陪妹子吗?难道你不怕影响其他的元素吗?所以你应该只会删除小图标,而不会删除的relative属性的。然后你的项目代码越来越臃肿,很多无用代码,看起来非常糟糕😰。这么一分析,你可知道"relative最小化使用原则"的好处了吧~

Last updated