CSS 相对/绝对(relative/absolute)定位系列(二)

  • A+
所属分类:css/css3 Web开发笔记

一、常见absolute布局的替代实现方案

absolute属性配合left/top/right/bottom属性具有极强的定位性。这种功能特性是如此的明显与强烈,可能会让页面重构人员很单纯的被这一特性“捕获”,而产生迷失。

一板一眼的描述可能难以理解,举个通俗点的例子吧:
一个脸蛋不错身材超好的姑娘穿上超PP的衣服后是如此的光艳动人,对于我们这类常年困居于深宅大院的光棍男来讲,这种美艳是如此的迷人,以至于我们的精力多集中在这沉鱼落雁的美貌上,而忽略了其他一些东西,例如知性,善良,贤惠等。很容易的,我们以后一想到此女子,第一反应就是“美貌”,至于其他,在如此美貌下已经不重要了。

此道理反映在web上就是,我们极易先入为主地认为absolute的价值就是借助left/top属性来进行定位的。说句不严谨的话,目前估计超过90%的普通布局中的absolute属性都是用在定位上了。恩,这个回头再说,这里还是看看一些常见的absolute布局如何通过使用其他属性完成同样的布局效果。既然absolute属性是拿来定位,我们只要使用其他属性定位就可以了。此时,自然而然想到了CSS中另外一个更加低调全能的定位属性margin,下面的前两个例子都是使用margin代替absolute及相关属性。

京东商城首页标价定位
首先拿京东商城首页的一个标价样式举例

用小bug一看其code实现,果然是绝对定位+定位属性://zxx:小bug时我对firebug的昵称

要是我来实现,就不会使用absolute属性,会使用margin实现扩展性容错性更强的布局。

不管怎样,先看对比实现效果,您可以狠狠地点击这里:absolute/margin定位布局对比demo

可见使用margin,可以实现与absolute布局一样的效果,且CSS属性使用量折半,更为关键的是,布局的扩展性与容错性大大增强了。

在demo页面上的底部有两个测试布局扩展性与容错性的按钮,如下图,第一个按钮是改变标签的宽度,第二个按钮是改变父标签的position属性为static:

我们点击第一个按钮改变dl父标签的宽度后,结果absolute定位的标价已经和图片远离了,而使用margin定位的橙红色背景标价依旧坚挺地呆在原来的位置上

点击第二个按钮改变父标签的position属性为static后,结果使用absolute绝对定位的标价没有了束缚,直接跑到浏览器窗口的右下角去了,而margin定位没有丝毫影响

从上面两个简单的测试可以看出两种实现方式见扩展性和容错性方面的差异。

下面简单讲下相关布局的实现,以下是原来absolute实现的相关代码:
HTML部分:

<dl>
    <dt class="p-img">
        <a href="##"><img width="130" height="130" src="http://www.ishangsf.com/wp-content/uploads/2017/08/11752677-6197-4ffa-b4c0-e66d02640bad.jpg" alt="CSS 相对/绝对(relative/absolute)定位系列(二)" /></a>
        <div class="p-price">¥999.00</div>
    </dt>
    <dd class="p-name">
        <a href="##">LG  GD580  3G手机 300万像素 999返100元券!</a>
    </dd>
</dl>

类名为”p-price”标签核心样式如下:

.p-price {
   position: absolute;
   bottom: 10px;
   right: 50px;  
   ......

京东商城的实现,中规中矩,想这种带有覆盖效果的定位,使用absolute定位估计是大部分页面重构人员的首选。但是,绝对定位之“绝对”一词本身就意味着其在扩展性方面的表现受限。如果我们要求更高,可以使用CSS代码量更少,扩展性更强的margin布局。

其实现代码如下:
首先HTML部分需要添加一层block水平的标签(其实可以不用加,只要让img外面的a标签block水平显示即可),让标价与图片不会在一个line box中显示,同时将标价外面的div标签改为inline水平元素的标签方便inline-block化,于是,最后的HTML代码如下:

<dl>
    <dt class="p-img">
        <a href="##"><img width="130" height="130" src="http://www.ishangsf.com/wp-content/uploads/2017/08/11752677-6197-4ffa-b4c0-e66d02640bad.jpg" alt="CSS 相对/绝对(relative/absolute)定位系列(二)" /></a>
        <div class="new-price-x"><span class="new-price">¥999.00</span></div>
    </dt>
    <dd class="p-name">
        <a href="##">LG  GD580  3G手机 300万像素 999返100元券!</a>
    </dd>
</dl>

相关的核心的CSS代码如下:

.new-price-x {
    margin: -28px 0 0 74px;
}
.new-price {
    display: inline-block;
    ......
}

淘宝首页示例
下面再看另外一个例子,就是淘宝首页的滚动播放效果,使用是absolute定位,通过改变top属性值实现上下的滚动切换

实际上,完全可以使用margin-top属性代替这里的relative+absolute+top属性组合。

您可以狠狠地点击这里:淘宝首页margin下的滚动播放demo

使用小bug一看demo页面的定位属性,啊,是margin-top

就效果来说,margin-top与绝对定位的切换是一样的,优点在于省了一点点的CSS代码量。但是,相对absolute的动画切换,margin-top值的改变会产生更强的回流(reflow),就性能上而言,要比absolute属性低。

究竟使用哪个,看您自己如何取舍了。

新浪微博示例
最后,拿新浪微博页面的主导航示例。

首先来看看为什么新浪微博的主导航要使用绝对定位。我想主要原因可能是半透明的纯色背景吧。

而IE浏览器下药实现opacity效果需要使用filter滤镜,然而opacity属性的半透明效果不仅会影响到当前元素,所有的子元素也会跟着半透明,此时,如果导航内元素放在半透明化的div内部显然容易死翘翘。所以,半透明背景层,与导航内容层不是父子关系,而是兄弟关系,导航内容覆盖于半透明背景上,就避免了导航内容被半透明化的危险。

而覆盖定位一般都离不开absolute属性,所以,新浪微博的主导航使用了绝对定位。然而,这里的绝对定位使用我必须称赞一下,因为很难得的,这里的absolute使用主要是利用了absolute属性的破坏性(高宽占据空间为0的特性),而不是利用其定位性(借助left/top等属性的定位)。

至于这里如何利用absolute属性的破坏性实现自适应的布局,不想讲。有微博的自己用小bug看看,没微博的注册个。

就这里绝对定位的使用来讲,除了莫名的top/right属性外,还是不错的。然而,问题在于这里非要使用绝对定位吗?兼容性的半透明纯色效果非要用并行的两个标签错开重叠定位吗?父子关系不行吗?有句成语叫做“与时俱进”,要是几年前,可能还真得这么搞。但是现在,什么绝对定位啊,重叠啊,计算啊什么乱七八糟的东西完全不需要。就当没有什么半透明效果写,同样可以实现一样的效果。

同样的,关于这里的替代方法,我做了个demo,您可以狠狠地点击这里:新浪微博主导航无absolute实现demo

使用opacity属性或是IE filter半透明滤镜会让子元素跟着半透明。实际上对于半透明的纯色背景,有更佳的实现方法。下面是demo页面的替换实现方法的CSS代码:

.newheader .menu_c {
    background-color: rgba(0, 0, 0, .25);
    filter: progid:DXImageTransform.Microsoft.Gradient(startColorStr=#40000000,endColorStr=#40000000);
}

现代浏览器使用CSS3 rgba实现半透明背景色,IE浏览器使用渐变滤镜实现半透明。

HTML方面,原来的绝对定位的半透明div层直接删掉,此时相关的relative属性等也可以一并去掉。HTML结构变得简单有层次,维护也更加方便了。

关于实现兼容性的半透明背景色,您可以参考我之前的“RGBA颜色与兼容性的半透明背景色”一文。所以具体使用,细节等这里就不多说

二、absolute可以一个人战斗

如果在CSS的世界中没有left/top/right/bottom属性,absolute的潜力估计会挖得深得多。

我们需要意识到,一个应用的position:absolute的元素,其实就只是个非常普通的元素,我感觉与应用了float:left的差异仅仅在于宽度的缺失。为说明此观点,我做了个很简单的demo.
您可以狠狠地点击这里:absolute元素只是个普通的货demo

此demo默认如下图,可以看到浮动的高度缺失造成的塌陷:

点击示意的按钮后,可以发现图片还是那个图片,还在那个位置,还是那么的安静与优雅。唯一变化的就是文字们有的跑到它的下面了(宽度缺失)。

由此可见,absolute属性只是个很普通的属性,跟float:left是个近亲。一个是陨落凡间的恶魔,一个是天空中的恶魔。所以,很多时候,我们在普通布局中使用absolute时候,只要设置position:absolute就可以了,至于left/top之类的都是浮云,定位什么的就当作普通元素,使用margin定位一样有着刮目的表现的。

三、absolute与left/top等属性之间的关系

单纯应用了absolute属性的元素就是个普通元素,跟变身前的美少女战士一样。left/top等属性是具有变身性质的东西,是恶魔absolute元素的翅膀。absolute元素一旦应用了left/top等属性,就具有了飞翔的能力,奔向天空自由驰骋,如果没有relative属性的限制,其会一直飞到天空的边缘(浏览器窗口),并且具有非常明确的方向性。

四、body标签是absolute元素自由的天空

来首小诗调节一下吧:
生命成可贵,
爱情价更高。
若为自由故,
两者皆可抛。

知道《美少女战士》吧,知道主人公水冰月(月野兔)吧,因为人家牛叉,所以为了保护地球,保护未来而战斗。知道《火影忍者》吧,你说要是把鸣人就限制在火影村,帮助老太太抓抓猫,帮助欧巴桑照看孩子,能有大成吗?人家是注定要肩负起忍者世界和平的职责的。

同样的,要是把绝对定位属性用在很深的DOM tree中,再用relative限制住。其实就是把鸣人当作看孩子的人使用,虽然用的时候觉得很好用,但是实际上是埋没了绝对定位元素的才能。没有限制,给予足够的自由,广阔的天空才是绝对定位元素大放异彩,拯救人类的舞台。

一般而言,在web页面上,最宽广的天空莫过于body标签,所以,在我看来,把绝对定位元素直接放在body标签下才是王道,才能最大限度的发挥绝对定位元素的才能。举个例子,淘宝首页顶部小横条上的下拉。

此下拉就是使用的绝对定位,但是却是深深地嵌入到DOM中的

这种方法的好处在于简单,对于非IE6浏览器直接使用CSS就可以实现效果了。然而,将默认隐藏的绝对定位元素被relative限制在很深的DOM节点中,弊处相当多:首先增加了DOM的复杂度,不利于维护;越深的DOM元素,造成了回流越强;因为父标签需要relative限制,增加了CSS代码的消耗量;隐藏元素头部加载,延迟了页面的呈现速度;每个下拉几乎都要重新定位,其重用性受限。

如果是我,一定会把这些隐藏的绝对定位元素放在在body标签内部,且最底部加载,以提高页面的呈现速度,甚至根本就不加载。此做法就是mtime时光网下拉导航的做法,是推荐的做法。绝对元素的定位不是通过当前触发元素的relative限制,而是在body大环境中,直接通过触发元素的偏移值设定位置,是最直接最高效的做法。

在body标签下自由驰骋,这才是绝对定位元素真正应该呆的地方。真正有才华的元素应该放在更大的舞台上,限制在蹩脚的角落里注定要埋没的。我之前写过一个名为”powerFloat“的万能浮动插件,就是希望通过降低使用的学习成本,让大家都把绝对定位元素解放到body标签下。

于是乎,我们不用担心什么层级错乱的破问题,不会再看到密密麻麻错乱的HTML代码。做页面重构的,本来就应该是每天喝喝咖啡,跟美女前台打情骂俏的工作,现在却搞那么辛苦,太不应该了。

absolute元素犹如有翅膀的小鸟,你是把它限制在鸟笼中,还是把它放飞到天空中自由的飞翔?我想,一切不言而喻。

weinxin
我的微信
爱生活、爱学习的小伙伴可以通过扫一扫二维码添加我的个人微信一起交流!
青青子衿

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: