第6章 流的破坏与保护
# 第6章 流的破坏与保护
# 魔鬼属性float
# float
的本质与特性
float
浮动属性让父元素高度坍塌的原因就是为了实现文字环绕效果。
float
自身特性:
- 包裹性;
- 块状化并格式化上下文;
- 破坏文档流;
- 没有任何
margin
合并。
包裹性,由包裹和自适应性两部分组成。
- 包裹。浮动元素父元素宽度
200px
,子元素是一个宽度128px
宽度的图片,则此时浮动元素宽度表现为包裹,就是里面图片的宽度128px
。
- 自适应性。
块状化,元素一旦float
的属性值不为none
,则其display
计算值为block
或table
。text-align
对浮动元素无效。
设定值 | 计算值 |
---|---|
inline | block |
inline-block | block |
inline-table | table |
table-row | block |
table-row-group | block |
table-column | block |
table-columngroup | block |
table-cell | block |
table-caption | block |
table-header-group | block |
table-footer-group | block |
# float
的作用机制
文字环绕效果是由两个特性(父级高度坍塌和行框盒子区域限制)共同作用的结果,定高只能解决父级元素高度坍塌带来的影响,但是对行框盒子区域限制没有任何效果,结果导致的问题是浮动元素垂直区域一旦超出高度范围,或下面元素margin-top
负值上偏移,就很容易使后面的元素发生“环绕效果”。
# float
更深入的作用机制
浮动元素和内联元素在一行显示。
- 浮动锚点是
float
元素所在的流中的一个点,这个点本身并不浮动。其作用是产生行框盒子,因为浮动锚点表现如同一个空的内联元素,有内联元自然就有行框盒子。 - 浮动参考指的是浮动元素对齐参考的实体。
float
元素的浮动参考是行框盒子,也就是float
元素在当前行框盒子内定位。
# float
与流体布局
See the Pen 中间内容居中的左中右布局 by whjin (@whjin) on CodePen.
# float
的天然克星clear
# 什么是clear
属性
clear
专门用来处理float
属性带来的高度坍塌等问题。
clear: none | left | right | both
none
:默认值,左右浮动left
:左侧抗浮动right
:右侧抗浮动both
:两侧抗浮动
实际应用中只使用clear:both;
即可。
# 成事不足败事有余的clear
clear
属性只有块级元素才有效,而:after
等伪元素默认都是内联水平,这就是伪元素清除浮动影响时需要设置display
属性值的原因。
clear:both
的作用本质是让自身不与float
元素在一行显示,并不是真正意义上的清除浮动。
- 如果
clear:both;
元素前面的元素就是float
元素,则margin-top
负值即使设成-9999px
,也没有效果。 clear:both;
后面的元素依旧可能发生文字环绕的现象。
# CSS世界的结界——BFC
# BFC的定义
BFC称为块级格式化上下文。BFC元素不可能发生margin
重叠,margin
重叠会影响外面的元素;BFC元素也可以用来清除浮动的影响,如果不清楚,子元素浮动则会父元素高度坍塌,必然会影响后面元素布局和定位。
何时会触发BFC,常见情况如下:
html
根元素;overflow
的值为auto
、scroll
或hidden
;display
的值为table-cell
、table-caption
和inline-block
中的任何一个;float
的值不为none
;position
的值不为relative
和static
。
只要元素符合上面任意一个条件,就无须使用clear:both;
属性去清除浮动的影响。
# BFC与流体布局
BFC的表现原则:具有BFC特性的元素的子元素不会受到外部元素的影响,也不会影响外部元素。普通流体元素在设置了overflow:hidden;
后,会自动填满容器中除了浮动元素以外的剩余空间,形成自适应布局效果。
img {
float: left;
margin-right: 10px;
}
.content {
overflow: hidden;
}
基于BFC特性的自适应布局有如下优点:
- 自适应内容由于封闭更加健壮,容错性更强。内部设置
clear:both;
不会与float
元素相互干扰而导致错位。 - 自适应内容自动填充浮动以外区域,无需关心浮动元素宽度,可以整站大规模应用。
.left {
float: left;
}
.right {
float: right;
}
.bfc {
overflow: hidden;
}
float:left;
。浮动元素本身BFC化,然而浮动元素具有破坏性和包裹性,失去了元素本身的流体自适应性,因此无法用来实现自动填满容器的自适应布局。position:absolute;
。脱离文档流,不容易操作。overflow:hidden;
块状元素的流体特性保存得很好,加上BFC的独立区域特性,而且从IE7开始就支持,兼容性很好。唯一的问题是容器盒子外的元素可能会被隐藏掉。display:inline-block;
display:table-cell
display:table-row
display:table-caption
总结上面的自适应布局设置,最佳实践如下:
overflow: auto/hidden;
,适用于IE7及以上版本浏览器;display: inline-block;
,适应于IE6和IE7;display: table-cell;
,适用于IE8及以上版本浏览器。
IE7及以上版本浏览器适配的自适应解决方案:
- 借助
overflow
属性,如下:
.lbf-content {
overflow: hidden;
}
- 融合
display: table-cell;
和display: inline-block;
,如下:
.lbf-content {
display: table-cell;
width: 9999px;
}
display: table-cell;
元素内连续英文字符无法换行的问题:
.word-break {
display: table;
width: 100%;
table-layout: fixed;
word-break: break-all;
}
# 最佳结界overflow
要彻底清除浮动的影响,最适合的属性是
overflow
。overflow:hidden;
声明不会影响元素原先的流体特性或宽度表现。
# overflow
裁剪界线border box
当子元素内容超出容器宽度高度限制的时候,剪裁的边界是border box
的内边缘,而非padding box
的内边缘。
在实际项目开发时,要尽量避免滚动条容器设置padding-bottom
值。
# 了解overflow-x
和overflow-y
IE8以上浏览器,overflow
增加了两个属性,overflow-x
和overflow-y
,分别表示单独控制水平或垂直方向上的剪裁规则。
支持的属性值和overflow
属性一模一样:
visible
:默认值hidden
:剪裁scroll
:滚动条auto
不会出现一个方向溢出剪裁或滚动,另一个方向内容溢出显示的效果。
# overflow
与滚动条
浏览器的滚动条:
- 默认滚动条来自
html
,而不是body
标签。去除页面默认滚动条:
html {
overflow: hidden;
}
在PC端,滚动条高度可以使用document.documentElement.scrollTop
获取,但是在移动端,需要使用document.body.scrollTop
获取。
2. 滚动条会占用容器的可用高度或宽度。
让页面滚动条不发生晃动的技巧
html {
overflow-y: scroll;
}
:root {
overflow-y: auto;
overflow-x: hidden;
}
:root body {
position: absolute;
}
body {
width: 100%;
overflow: hidden;
}
滚动条自定义效果:
- 整体部分:
::-webkit-scrollbar
- 两端按钮:
::-webkit-scrollbar-button
- 外层轨道:
::-webkit-scrollbar-track
- 内层轨道:
::-webkit-scrollbar-track-piece
- 滚动滑块:
::-webkit-scrollbar-thumb
- 边角:
::-webkit-scrollbar-corner
::-webkit-scrollbar { /*血槽宽度*/
width: 8px;
height: 8px;
}
::-webkit-scrollbar-thumb { /*拖动条*/
background-color: rgba(0, 0, 0, .3);
border-radius: 6px;
}
::-webkit-scrollbar-track { /*背景槽*/
background-color: #ddd;
border-radius: 6px;
}
# 依赖overflow
的样式表现
单行文字溢出...
效果,需要使用到overflow:hidden;
、text-overflow:hidden;
,效果实现必需的3个声明如下:
.ell {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
最多显示2行内容,再多就打点的核心CSS代码:
.ell-rows-2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
# overflow
与锚点定位
基于URL地址的锚链location.hash
实现锚点跳转的方法有两种:
a
标签以及name
属性- 使用标签的
id
属性
<a href="#1">发展历程</a>
<a name="1"></a>
1. 锚点定位行为的触发条件
- URL地址中的锚链与锚点元素对应并有交互行为;
- 可
focus
的锚点元素处于focus
状态。
focus
锚点定位指的是类似链接或按钮、输入框等可以被focus
的元素在被focus
时发生的页面重定位现象。
URL地址锚点定位是让元素定位在浏览器窗体的上边缘,而``focus锚点定位
是让元素在浏览器窗体范围内显示即可。
2. 锚点定位作用的本质
锚点定位行为的发生,本质上是通过改变容器滚动高度或宽度来实现。改变了scrollTop
或scrollLeft
的值。
See the Pen 窗体无跳动选项卡 by whjin (@whjin) on CodePen.
处理列表部分区域正在浏览器外面依然会跳动的问题:
$('label.click').removeAttribute('for').on('click', function () {
$('.box').scrollTop(xxx);//滚动数值
});
基于父容器自身的scrollTop
值改变来实现自定义滚动条效果。
- 实现简单,无须做边界判断。
container.scrollTop=99999;
,列表滚动就是scrollTop
值,实时获取。 - 可与原生的
scroll
事件天然继承,无缝对接。 - 无须改变子元素的结构。
# float
的兄弟position:absolute
绝对定位absolute
具有块状化,块状格式化上下文、包裹性和自适应性。自适应性的最大宽度由“包含块”决定。
# absolute
的包含块
普通元素的百分比宽度是相对于父元素的content box
宽度计算,而绝对定位元素的宽度是相对于第一个position
不为static
的祖先元素计算的。
- 根元素
html
被称为“初始包含块”,其尺寸等同于浏览器可视窗口的大小。 - 对于其他元素,如果该元素的
position
是relative
或static
,则“包含块”由其最近的块容器祖先盒子的content box
边界组成。 - 如果元素
position:fixed;
,则“包含块”是“初始包含块”。 - 如果元素
position:absolute;
,则“包含块”由最近的position
不为static
的祖先元素建立,具体方式如下: 如果该祖先元素是纯inline
元素,则规则略复杂:- 给内联元素的前后各生成一个宽度为
0
的内联盒子,则这两个内联盒子的padding box
外面的包围盒子就是内联元素的“包含块”。 - 如果该内联元素被跨行分割,则包含块是未定义的。
否则,“包含块”由该祖先的
padding box
边界组成。
- 给内联元素的前后各生成一个宽度为
和常规元素相比,绝对定位元素的包含块有3个明显的差异:
- 内联元素也可以作为包含块所在的元素;
- 包含块所在的元素不是父级块元素,而是最近的
position
不为static
的祖先元素或根元素; - 边界是
padding box
而不是content box
。
内联元素的“包含块”是由“生成的”前后内联盒子决定,与里面的内联盒子细节没有任何关系。
height:100%;
是第一个具有定位属性值得祖先元素的高度,而height:inherit;
则是单纯的父元素的高度继承。
# 具有相对特性的无依赖absolute
绝对定位
1. 各类图标定位
See the Pen 无依赖绝对定位”与导航图标定位 by whjin (@whjin) on CodePen.
See the Pen 文字和图片水平对齐 by whjin (@whjin) on CodePen.
2. 超越常规布局的排版
See the Pen “无依赖绝对定位”与超越常规布局的排版 by whjin (@whjin) on CodePen.
3. 下拉列表的定位
See the Pen “无依赖绝对定位”与下拉列表定位 by whjin (@whjin) on CodePen.
4. 占位符效果模拟
5. 进一步深入“无依赖绝对定位”
# absolute
与text-align
absolute
元素的display
计算值是块状的,text-align
不会起作用。
See the Pen absolute与text-align互相作用 by whjin (@whjin) on CodePen.
See the Pen 主结构右外侧固定定位 by whjin (@whjin) on CodePen.
# absolute
与overflow
如果overflow
不是定位元素,同时绝对定位元素和overflow
容器之间也没有定位元素,则overflow
无法对absolute
元素进行裁剪。overflow
元素父级是定位元素也不会裁剪。
overflow
属性所在的元素同时也是定位元素,里面的绝对定位元素会被裁剪;overflow
元素和绝对定位元素之间有定位元素,也会被裁剪。overflow
属性值不是hidden
,而是auto
或scroll
,即使绝对定位元素高度比overflow
元素高度大,也不会出现滚动条。
# absolute
与clip
clip
属性要起作用,元素必须是绝对定位absolute
或固定定位fixed
。
clip
属性语法:clip: rect(top right bottom left)
# 重新认识的clip
属性
1. fixed
固定定位的剪裁
.fixed-clip {
position: fixed;
clip: rect(30px 200px 200px 20px);
}
2. 最佳可访问性隐藏
最佳可访问性隐藏指的是视觉上看不见,但是辅助设备能够进行识别和访问。
.logo h1 {
position: absolute;
clip: rect(0 0 0 0);
}
<a href="/" class="logo">
<h1>我是标题</h1>
</a>
# 深入了解clip
的渲染
clip隐藏仅仅是决定了哪部分是可见的,非可见部分无法响应点击事件,虽然视觉上隐藏,但是元素的尺寸依旧是原来的尺寸。
# absolute
的流体特性
# 当absolute
遇到left/top/right/bottom
属性
当absolute
遇到left/top/right/bottom
属性时,absolute
元素才真正变成绝对定位元素。
# absolute
的流体特性
当一个绝对定位元素,其对立定位方向属性同时具有定位数值时,就会发生流体特性。
普通元素流体特性只有水平方向(默认),但是绝对定位元素可以让垂直方向和水平方向同时保持流动性。
# absolute
的margin:auto
居中
.box {
width: 200px;
height: 200px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
# position:relative
才是大哥
# relative
对absolute
的限制
# relative
与定位
relative
与定位特性:一是相对自身,二是无侵入(当relative
进行定位偏移时,不会影响周围元素的布局)。
relative
定位:相对定位元素的left/top/right/bottom
百分比值是相对于 包含块计算,而非自身。
top/bottom
垂直方向的百分比值计算和height
百分比值一样,都是相对于高度计算。
当相对定位元素同时应用对立方向定位值,top/bottom
和left/right
同时使用时,其表现和绝对定位差异很大,只有一个方向的定位属性起作用。
# relative
的最小化影响原则
- 尽量不适用
relative
,定位某元素,可以使用无依赖的绝对定位; - 如果需要使用
relative
,则该relative
需要最小化。
<div>
<div style="position:relative;">
<img src="1.jpg" alt="" style="position: absolute;top: 0;right: 0;">
</div>
<p>内容1</p>
<p>内容2</p>
</div>
# 强悍的position:fixed
固定定位
# position:fixed
不一样的“包含块”
position:fixed
固定定位元素的包含块是根元素。唯一可以限制固定定位元素的是<html>
根元素。relative
对fixed
定位没有任何限制作用。
See the Pen 无依赖固定定位 by whjin (@whjin) on CodePen.
# position:fixed
的absolute
模拟
<div class="page">固定定位元素</div>
<div class="fixed"></div>
html, body {
height: 100%;
overflow: hidden;
}
.page {
height: 100%;
overflow: auto;
}
.fixed {
position: absolute;
}