前言
流的破坏和保护,可能大家一想到的就是float
与clear
,并且认为float
的出现就是为了解决布局问题的,但实际上这并不是它的本意,它的本质是为了实现文字环绕效果,即文字环绕图片显示的效果,很显然,从float
的设计初衷来看,当下哪些漫天飞舞的浮动属性完全是滥用了。
float的特性
- 包裹性
- 块状化并格式化上下文
- 破坏文档流
- 没有任何
margin
合并
一旦元素的float
的属性值不为none
,则display
的计算值就是block
或table
,所以不要出现设置浮动后还设置display:block
这样的组合,下面是常见的float
和display
转换表:
float的天然克星clear
一般我们设置浮动属性后,都会设置clear
属性清楚浮动造成后面的元素的影响,clear
属性的官方解释就是:元素盒子的边不能和前面的浮动元素相邻。下面我们来看一个例子:
HTML:
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
CSS:
li{
width:20px;height:20px;
margin:5px;
float:left;
}
li:nth-of-type(3){
clear:both;
}
效果:
这里的第三个设置清楚浮动,并且是both
,讲道理,li
显示应该是3行,但实际显示的却是两行,原因在于,clear
属性是让自身不能和前面的浮动元素相邻,注意这里的"前面的"三个字,也就是clear
属性对后面的元素是不闻不问的,因此才显示两行而不是三行。更进一步,考虑到float
属性不是left
就是right
,不可能同时存在,同时由于clear
属性对“后面的”浮动元素不闻不问,因此设置clear:right
有效的时候,必然clear:left
必然无效,也就是此时的clear:left
等同于设置clear:both
,因此,在平时使用的过程中,直接使用both
属性就好。
clear
属性只有块级元素才有效,而::after等伪元素默认都是内联水平,这就是借助于伪元素清除浮动元素影响需要设置display
属性值的原因。
.clear:after{
content:"";
display:block;//也可以是table,list-item
clear:both;
}
CSS世界的结界——BFC
BFC全称为block formatting context
,中文名为“块状格式化上下文”,相对应的还有IFC,也就是“内联格式化上下文”,本节主要研究BFC。
关于BFC的特性,可以将其称为“css世界的结界”,有点类似于神话中的结界一样,结界内的元素无论怎么翻江倒海,都不可能影响结界外的元素,所以BFC元素不可能发生margin重叠,因为重叠会影响到外面的元素,BFC元素也可以清除浮动的影响。
常见触发BFC的情况:
<html>
根元素;float
的值不为none
;overflow
的值为auto、scroll
或hidden
;display
的值为table-cell
、table-caption
和inline-block
中的任何一个;position
的值不为relative
和static
。
overflow的不兼容
直接上代码:
HTML:
<div class="box">
<img src="1.jpg" width="256" height="192">
</div>
CSS:
.box {
width: 200px; height: 80px;
margin: auto;
padding: 10px;
border: 10px solid;
overflow: hidden;
}
当鼠标向下滚动的时候,chrome变现与其他浏览器表现不一致,具体表现在chrome浏览器下面会有10px
的空白,IE和火狐则没有。
原理则是在chrome浏览器下,如果容器可滚动(假设是垂直滚动),则padding-bottom
也算在滚动尺寸之内,IE和火狐则会忽略padding-bottom
。所以为了减少不必要的麻烦,尽量避免滚动容器设置padding-bottom
值。
overflow的依赖样式
我们常用的单行文本溢出显示点点效果,虽然核心技术是text-overflow:eliipsis
,但是要想实现这种效果,必须申明以下3个:
.ell{
text-overflow:ellipsis;
white-word:nowrap;
overflow:hidden;
}
无依赖绝对定位
包含快这个概念简单解释就是元素用来计算和定位的一个框。下面是包含快的常用计算规则:
- 根元素(很多场景下可以看成是)被称为“初始包含快”,其尺寸等同于浏览器可视窗口的大小。
- 对于其他元素,如果该元素的
position
是relative
或者static
,则包含快由最近的块容器祖先盒的content box
边界组成。 - 如果元素
position:fixed
,则包含快是初始包含快。 - 如果元素
position:absolute
,则包含快由最近的position
不为static
的祖先元素建立,具体规则如下;
如果该祖先元素是纯inline
元素,则规则略微复杂:
- 假设给内联元素的前后各生成一个宽度为0的内联盒子(inline box),则这两个内联盒子的padding box外面的包围盒就是内联元素的“包含快”;
- 如果该内联元素被跨行分割了,那么“包含快”是未定义的,也就是css2.1规范 并没有明确定义,浏览器自行发挥。
否则,“包含快”有该祖先的padding box边界形成。
如果没有符合条件的包含快,则“包含快”就是“初始包含快”。
思考这样一个问题:一个绝对定位元素,没有任何left/top/right/bottom
属性设置,并且其祖先元素全部都是非定位元素,其位置在哪里?
很多人都认为是浏览器窗口的左上方,实际上,还是当前位置,不是浏览器的左上方。
考虑下面这样一个例子:
下图左上角需要一个TOP1
的图像标志,请问如何布局?
想必大多数都是这样的:
.father{
position:relative;
}
.shap{
positiong:absolute;
top:0;left:0;
}
实际上只需要一行代码就可以了,不信?点击demo测试即可。
.shap{
positiong:absolute;
}
看到没有,这种不需要position:relative
或者其他属性就可以实现,我们把这种没有left/top/right/bottom
属性值的绝对定位简称为“无依赖绝对定位”,我们还可以将其运用在表单验证提示语中。
有下图的一个表单psd文稿:
一般来说在注册的时候客户端都需要验证一番,从而减少用户出错,验证提示信息都是放在填写表单每一个行的后面,假设提示文字内容元素的类名是remark
,则有css代码如下:
.remark{
position:absolute;
margin-left:10px;
}
详细demo可点击查看。
重新认识clip属性
很多人都不知道css中还有就地剪裁属性,其基本语法为:
clip:rect(top,right,bottom,left)
当然其生效的前提是元素必须会绝对定位或者固定定位,也就是position
的属性值必须是absolute
或者fixed
。
其主要运用在两个重要的场景。
1.fixed固定定位的剪裁
对于普通元素,我们想要对齐进行剪裁,我们可以利用语义更明显的overflow
属性,但是对于position:fixed
元素,overflow
属性往往就是失效了,因为固定定位的包含块是根元素,所以这时候clip
属性就可以大展身手了。例如:
.fixed-clip{
position:fixed;
clip:rect(30px 200px 20px 10px);
}
2.最佳可访问性隐藏
所谓“可访问性隐藏”,指的是虽然肉眼看不见,但是其他辅助性设备却能够识别和访问的隐藏。
比如,很多网站为了SEO优化,往往会在自己的网站的标识,即logo旁边使用标签写上自己网站的名词,代码如下:
<a href="/" class="logo">
<h1>hello world!</h1>
</a>
如何隐藏标签中的文字,一般有以下技术选型:
- 最简单的是
display:none
或者visibility:hidden
,但是屏幕阅读器会忽略这里的文字。 text-indent
是稍微好一点的中策之计,但是缩进太大,屏幕阅读器也会忽略。color:transparent
移动端上策之选,但是桌面端却是中策之选,毕竟ie8并不支持透明颜色。clip
隐藏测试最佳实践,移动桌面支持都良好。
.logo h1{
positiong:absolute;
clip:rect(0 0 0 0);
}
absolute的margin:auto居中
实现一个元素的水平垂直居中,我们常用的便是这样:
.el{
width:400px;
height:400px;
position:absolute;
left:50%;
right:50%;
margin-left:-200px;
margin-top:-200px;
}
兼容奇好,IE7也支持,但是明显有一个缺点,margin
和元素的宽高耦合了。
第二个方案则是通过transform
实现:
.el{
width:400px;
height:400px;
position:absolute;
left:50%;
right:50%;
transform:translate(-50%,-50%);
}
这里的耦合问题解决了,但是百分比的transform
会让iOS微信闪退,这里也不推荐。
第三种就是最佳实践了:
.el{
width:400px;
height:400px;
position:absolute;
left:0;
right:0;
bottom:0;
top:0;
margin:auto;
}
通过margin
自动平分,可以说最佳了,但是不兼容IE8,所以视情况而定吧。
参考自《css世界》