1、具有相对特性的无依赖 absolute 绝对定位
一个绝对定位元素,没有任何 left/top/right/bottom 属性设置,并且其祖先元素全部都是非定位元素,其位置在哪里?
很多人都认为是在浏览器窗口左上方。实际上,还是当前位置即html代码布局的位置,不是在浏览器左上方。正是这种错误认知导致凡是使用
absolute 绝对定位的地方,一定父容器 position:relative,同时 left/top 等属性定位,甚至必同时使用 z-index 属性设置层级。
请牢记下面这句话:absolute 是非常独立的 CSS 属性值,其样式和行为表现不依赖其他任何 CSS 属性就可以完成。
上图左上角有一个“TOP1”的图形标志,很多人都是这样布局的:
.father{
position: relative;
}
.shape {
position: absolute;
top: 0; left: 0;
}
其实只需要一行代码就够了
.shape {
position: absolute;
}
absolute 定位效果实现完全不需要父元素设置 position
为 relative 或其他什么属性就可以实现,把这种没有设置 left/top/ right/bottom 属性值的绝对定位称为“无依赖绝对定位”。
1)、各类图标定位
我们经常会在导航右上方增加一个“NEW”或者“HOT”
这样的小图标。
.icon-hot {
position: absolute;
margin: -6px 0 0 2px;
width: 28px; height: 11px;
background: url(hot.gif);
}
要实现在导航文字右上方的定位很简单,直接对加图标这个元素进行样式设定就可以了,原来纯文字导航时的样式完全不需要有一丁点儿的修改。日后这个图标下架了,我们只需要把图标对应的 HTML 代码和 CSS 删掉就可以,原来的代码完全不需要改动。不仅代码简洁,日后的维护也很方便,更关键的是,即使导航中的文字长度发生了变化,我们的图标依然定位良好,因为“无依赖绝对定位”的图标是自动跟在文字后面显示的。
设想一下,如果给父元素设置 position:relative,然后 right/top 定位,文字长度一旦发生变化,CSS 代码就要重新调整,这维护成本显然要比前一种方法高了很多。
要实现下面图
<span class="icon-x">
<i class="icon-warn"></i>邮箱格式不准确
</span>
.icon-x {
line-height: 20px;
padding-left: 20px;
}
.icon-warn {
position: absolute;
margin-left: -20px;
width: 20px; height: 20px;
background: url(warn.png) no-repeat center;
}
同样是 position:absolute,然后简单的 margin 偏移实现。此方法兼容性很好,与 inline-block 对齐相比的好处在于,inline-block 对齐最终行框高度并不是20px,因为中文下沉,图标居中,要想视觉上水平,图标 vertical-align 对齐要比实际低一点儿,这就会导致最终整个行框的高度不是预期的 20px,而是 21px 或者更大。但是,如果使用“无依赖绝对定位”实现,则完全不要担心这一问题,因为绝对定位元素不会改变正常流的尺寸空间,就算我们的图标有 30px 大小,行框高度依然是纯文本所在的 20px 高度。
2)超越常规布局的排版
实现这样的效果
remark {
position: absolute;
margin-left: 10px;
}
就这么简简单单的 CSS 代码,效果即达成,既在输入框的后面显示,又跳出了容器宽度的限制,同时显隐不会影响原先的布局。更为关键的是,提示信息的位置智能跟随输入框。例如,我们这里把输入框的宽度改小,会看到提示信息会自动跟着往前走,与容器设置 position:relative 再通过 left 属性实现的定位相比,其代码更简洁,容错性更强,维护成本更低。
此外,页面中的星号也是典型的“无依赖绝对定位”,自身绝对定位,然后通过 marginleft 负值偏移实现,从而保证所有输入信息头左对齐,同时又不会影响原先的布局,也就是
星号有没有对布局没有任何影响。
3)下拉列表的定位
这里,这个下拉列表的定位采用的就是“无依赖绝对定位”,相关 HTML 和 CSS 代码如下:
.search-input {
width: 200px; height: 20px;
line-height: 20px;
padding: 9px 39px 9px 9px;
border: 1px solid #ddd;
}
/* 搜索按钮的无依赖绝对定位 */
.search-btn {
width: 20px; height: 20px;
border: 9px solid #fff;
background: #ddd url(search.png) no-repeat center;
position: absolute; margin: 1px 0 0 -40px;
}
/* 下拉列表的无依赖绝对定位 */
.search-datalist {
position: absolute;
width: 248px;
border: 1px solid #e6e8e9;
background-color: #fff;
}
<div class="search-box">
<input class="search-input" placeholder="搜索"><a href="javascript:" class="search-btn">搜索</a>
<div class="search-result">
<div class="search-datalist">
<a href>搜索结果1</a>
<a href>搜索结果2</a>
<a href>搜索结果3</a>
<a href>搜索结果4</a>
<a href>搜索结果5</a>
</div>
</div>
</div>
就一个 position:absolute 就实现了我们想要的效果,没有 left、top 定位,父元素也没有 position:relative 设定,效果就达成了,而且兼容性好到 IE6 都完美定位。
4)占位符效果模拟
IE9 及其以下浏览器不支持 placeholder 占位符效果,实际开发的时候,针对这些浏览器,需要进行模拟。比较好的做法是使用
<label class="placeholder" for="text">占位符</label>
<input id="test">
/* 和输入框一样的样式 */
.placeholder, input {
...
}
/* 占位符元素特有样式 */
.placeholder {
position: absolute;
...
}
由于“无依赖绝对定位”本质上就是一个不占据任何空间的相对定位元素,因此这里我们
让占位符元素和输入框的布局样式一模一样,再设置绝对定位,就可以和输入完美重叠定位。
当然有一些样式是需要重置的,比方说,输入框经常会设置 border 边框样式,那么我们的占位符元素就需要把边框颜色设置成透明的,例如:
.placeholder {
border-color: transparent;
}
5)进一步深入“无依赖绝对定位”
虽然说元素 position:absolute 后的 display 计算值都是块状的,但是其定位的位置和没有设置 position:absolute 时候的位置相关
<h3>标题<span class="follow">span</span></h3>
<h3>标题<div class="follow">div</div></h3>
其差别就在于“标题”文字后面跟随的标签,一个是内联的<span>
,还有一个是块状的<div>
,此时,显然 span 字符是跟在“标题”后面显示,div 字符则换行在“标题”下面显
示,这个想必大家都知道。好,现在有如下 CSS 代码:
.follow {
position: absolute;
}
虽然此时无论是内联的还是块状的
假如 HTML 是下面这样的:
<h3>标题</h3><span class="follow">span</span>
<h3>标题</h3><div class="follow">div</div>
那么由于非绝对定位状态下 span 和 div 都在“标题”的下面,因此,这里最后的效果也同样是都在“标题”的下面。
注:position之后该标签原来在哪个位置就在哪个位置,前提是父元素没有什么居中对齐之类的属性设置,不然设置position之后,该标签会在未设置这些属性的位置。
首先,IE7 浏览器下,块状的<div>
“无依赖绝对定位”的定位表现如同内联的<span>
。其次,前文提到浮动和绝对定位是死对头,当“浮动”和“无依赖绝对定位”相遇的时候,
就会发生一些不愉快的事情。
<div class="nav">导航 1</div>
<img src="new.png" class="follow">
<div class="nav">导航 2</div>
.follow {
position: absolute;
}
.nav {
width: 100px;
line-height: 40px;
background-color: #333;
color: #fff;
text-align: center;
float: left;
}
结果在 IE 和 Chrome 浏览器下,夹在中间的在中间显示(上),但是 Firefox浏览器却是在最后显示(下)
Firefox浏览器下的定位位置或许比较好理解,因为和没有设置 position: absolute 表现一致,符合我们对上面规则的理解。那为何 IE 和Chrome 浏览器却在中间显示呢?我认为是这样的:浏览器对于DOM 元素的样式渲染是从前往后、由外及内的,因此渲染顺序是先“导航 1”,再“图片”,最后是“导航 2”。当渲染到“图片”的时候,由于“导航 1”左浮动,因此内联的图片跟在后面显示,此时由于设置了 position:absolute,因此当前位置定位并不占据任何空间,再渲染“导航 2”的时候,中间的“图片”基本上跟不存在没什么区别,因此也就和“导航 1”紧密相连了,最终形成了“图片”在中间显示的样式表现。
对于上述场景,如果希望各个浏览器的表现都是一样的<img>
外层嵌套一层标签并浮动即可,注意,是外层标签浮动。由于浮动和绝对定位水火不容,本身设置浮动是没有任何效果的。
2、absolute 与 text-align
理论上说,absolute 和 float 一样,都可以让元素块状化,应该不会受控制内联元素对齐的 text-align 属性影响,但是最后的结果却出人意料,text-align 居然可以改变absolute 元素的位置。
<p><img src="1.jpg"></p>
p {
text-align: center;
}
img {
position: absolute;
}
在 Chrome 和 Firefox 浏览器下,图片在中间位置显示了,但是仅仅是在中间区域显示,并不是水平居中,如果我们给<p>
设定尺寸并添加背景色,就会看到如图所示的效果
虽然本示例中图片位置确实受 text-align 属性影响,但是并不是 text-align 和absolute 元素直接发生关系,absolute 元素的 display 计算值是块状的,text-align是不会有作用的。这里之所以产生了位置变化,本质上是“幽灵空白节点”和“无依赖绝对定位”共同作用的结果。
具体的渲染原理如下。
(1)由于是内联水平,
标签中存在一个宽度为 0、看不见摸不着的“幽灵空白节点”,也是内联水平,于是受 text-align:center 影响而水平居中显示。
(2)设置了 position:absolute,表现为“无依赖绝对定位”,因此在“幽灵空白节点”后面定位显示;同时由于图片不占据空间,这里的“幽灵空白节点”当仁不让,正好在<p>
元素水平中心位置显示,于是我们就看到了图片从<p>
元素水平中间位置显示的效果。
此时,我们只要 margin-left 一半图片宽度负值大小,就可以实现图片的水平居中效果了,与父元素 position:relative 然后定位元素设置 left:50%的方法相比,其优势在于不需要改变父元素的定位属性,避免可能不希望出现的层级问题等
然而,IE 浏览器的支持不一样导致此方法的场景实用性打了折扣。当然,有小技巧可以使所有浏览器都完美支持,如果只需要兼容 IE Edge(移动端开发时候),额外加下面这一段 CSS
语句就可以了:
p:before {
content: '';
}
如果希望兼容 IE8 浏览器,则 CSS 代码还要再多一点儿:
p {
text-align: center;
font-size: .1px;
font-size: -webkit-calc(1px - 1px);
}
p:before {
content: '\2002';
}
img {
position: absolute;
}
其中,\2002 表示某一种空格。通过插入显式的内联字符,而非借助飘渺的“幽灵空白节点”实现所有浏览器下的一致表现。
需要注意的是,只有原本是内联水平的元素绝对定位后可以受 text-align 属性影响,这不难理解,因为块级元素的“无依赖绝对定位”是掉在下面显示的,水平方向上并无可“依赖”的内联元素,text-align 属性自然鞭长莫及。
利用 text-align 控制 absolute元素的定位最适合的使用场景就是主窗体右侧的“返回顶部”以及“反馈”等小布局的实现。
<div class="alignright">
<span class="follow"></span>
</div>
.alignright {
height: 0;
text-align: right;
overflow: hidden;
}
.alignright:before {
content: "\2002";
}
.follow {
position: fixed;
bottom: 100px;
z-index: 1;
}
使用:before 伪元素在前面插入一个空格,此时.alignright 设置 text-align:right,则此空格对齐主结构的右边缘显示,后面的固定定位元素(同绝对定位元素)由于“无依赖定位”特性,左边缘正好就是主结构的右边缘,天然跑到主结构的外面显示了,而这个效果正是固定在右下角的“返回顶部”以及“反馈”小按钮布局需要的效果。
此方法兼容性很好,层级单纯,唯一的问题就是插入了一个空格,会占据一定的高度,这
是不推荐的,最好就是有没有“返回顶部”等元素都不影响主结构的布局。所以,我们要把占
据的高度抹掉,方法很简单,设置 height:0 同时 overflow:hidden 即可。