CSS设计:绝对位置 vs. 相对位置
什么使用嵌套的层?
最近一个好奇的读者问起了关于 Adaptive Path 的网站重构:“对于主导航栏的设计,我一直很困惑,为什么把一个具有绝对位置(absolute)的层嵌套在一个具有相对位置(relative)的层中?”
一个简单的答案是:因为我想要使标题和导航栏具有最适宜的灵活性,并且无论文本大小如何变化,都能保持导航栏与LOGO之间的距离不变。
这是战略性(strategic)的答案,它给出了基本原理。但是,我推断他也正在寻找一个战术性(tactical)的答案。为了更彻底的回答他的问题,我将退一步,用我自己的语言来解释绝对位置如何在样CSS中工作,并通过举例来演示与Adaptive Path不同的设计效果,然后我们在回来讨论AP的导航栏。
容器块(布置上下文)
将具有绝对位置的元素嵌套于具有相对位置的元素,这是一种相当常用的技术。更普遍的是,我们可以看到相反的状况:将一个具有相对位置的元素包在一个具有绝对位置的元素之外。
依照CSS2的说明,一个具有绝对位置的元素(absolute-positioned element),其位置是由它所在的容器块(containing block)来决定的。只要元素的位置值(position value)被设定为相对(relative
),绝对(absolute
),或者固定(fixed
)[只要不是静态(static
)],那么该元素就将被视为是已经定位的 (positioned)元素。“静态”是位置属性中一个可能的取值。同时,对于那些没有被指定位置的元素,它也是默认值。静态基本上意味这这一元素的位置是不可修改的,并和文档中的其它的同胞元素(sibling element)以及容器块以预期的正常流动(normal flow)状态显示。
如果一个具有绝对位置的元素未处于其它容器块中,(当没有已定位的父元素时)那么它的位置即是相对于页面边界的(称为初始容器块)。因此,一个按照如下规则设置的元素:
#topleft { position:absolute; top:0; left:0; }
将被置于页面的左上角。然而,所有已经定位的父元素会为它们的子元素设定新的容器块。如果一个父元素已被定位,那么它的所有子元素的的定位将会以父元素(新的容器块)的边界来重置。因此,上面的这个规则中的盒偏移(box offsets)会使得这一#topleft元素置于父辈元素的左上角,而不是页面的左上角。
还是很迷惑?对我来说,它也好像是在胡言乱语。下面,我将举一个普通的例子帮助你掌握它!
动态定位
对于stopdesign.com,(在写这篇文章的时候)我在右侧栏目(#subcol
)上使用了绝对位置。在设计模板时,我希望右侧栏目中的每一个元素能够无交迭,无空隙地,紧随着页眉(#header
)。页眉包括logo和主导航栏。由于主导航栏是文本,它可以通过浏览器的控制来调整大小。这将直接影响整个页眉的高度。我本可以将右侧栏目基于页边距进行定位,根据页眉的标准高度为其指定top值。但是由于不同的浏览器的默认文字大小不同,引起了页眉的高度改变,这就意味着如果标题的高度增加,右侧栏目有可能会与页眉交迭。或者当页眉的高度小于标准,则页面与右边专栏之间将会出现空隙。
图1
为了适应页眉的高度变化,我使用了一个已定位的容器元素(#content
)。在标记(markup)中,这一容器紧随页眉,并且其位置被设为相对(position:relative;
)。这就允许此容器元素出现于(并且影响)文档的正常流动;容器顶部会始终紧随页眉的底部,无论标题是变大还是缩小。因为#content
已经过定位,它内部的元素也会因此而重新调整位置。右侧栏目(#subcol
)包含于#content
中,因此右侧栏目被放置于#content
的右上角,而不是页面的右上角。这就使右侧栏目能够在竖直方向上适应页眉的高度变化,如图1中显示的那样。
置底的导航栏
图2-A 图2-B
最后,我们回到 Adaptive Path 的导航栏,它体现了绝对位置和相对位置(making-absolute-relative)的使用方法。我本可以很容易的为导航栏指定一个固定的上侧外补丁(margin-top
),以完成对它的定位。但是在这里,我希望页眉总能保持相同的高度,无论导航栏的文字变得多大或者多小。换句话说,我不希望导航栏下的墨绿色边框,相对于LOGO的竖直位置改变,如图2-A和图2-B。
更准确的说,导航栏的文字可以随意地调整大小,但是它的底线位置仍然保持不变。它总是与这条墨绿色的边框相切,并无交迭。通过为#nav
元素设置相对位置(position:relative;
),并为这一容器指定高度(72px
),那么它就为其内部的层建立了限定了新的位置。这时,就可以为容器#nav
的内部层指定一个置底的绝对位置(bottom:0;
)。
这项技术当然也存在的其它的使用方法。对于希望为元素重新定义一个基于非页边距的绝对位置,这种想法其实并不罕见。做什么,为何这样做,这些背后所依据的理论对我来说是显而易见的。但是,它并不总是对每个人都那么显而易见。现在,这项技术对其它人来说,或许能够更加容易理解一点(也许甚至是显而易见的)。