我学到的第一个CSS知识就是如何把一个固定宽度和高度的元素水平或者垂直居中。这些居中的内容可能是入站欢迎页面(Splash Page http://searchsoa.techtarget.com/sDefinition/0,,sid26_gci213036,00.html)中图片,或者是一些设计喜欢的居中设计的网站等。最原始的解决办法就是把元素在窗口中距左和距上边缘进行50%的绝对定位。当然这只是把元素的右上角移动到了窗口的中央,接下来你还需要设置负的margin-left和margin-top并且使它们的值刚好是宽和高的一半来把元素拉加到屏幕的中央。
让我们看一下旧式做法的例子并注意一下其中的不足:
- html,body{
- height:100%;
- margin:0;
- padding:0;
- }
- body{
- background:#eae7d7 url(images/vert-centre.jpg) repeat-x center center;
- text-align:center;
- min-width:626px;
- min-height:400px;
- }
- #vert-hoz{
- position:absolute;
- top:50%;
- left:50%;
- margin-top:-198px;/* half elements height*/
- margin-left:-313px;/* half elements width*/
- width:624px;
- height:394px;
- border:1px solid silver;
- background:#666;
- overflow:auto;/* allow content to scroll inside element */
- text-align:left;
- }
- h1 {color:#fff;margin:0;padding:0}
html,body{ height:100%; margin:0; padding:0; } body{ background:#eae7d7 url(images/vert-centre.jpg) repeat-x center center; text-align:center; min-width:626px; min-height:400px; } #vert-hoz{ position:absolute; top:50%; left:50%; margin-top:-198px;/* half elements height*/ margin-left:-313px;/* half elements width*/ width:624px; height:394px; border:1px solid silver; background:#666; overflow:auto;/* allow content to scroll inside element */ text-align:left; } h1 {color:#fff;margin:0;padding:0}
- <div id="vert-hoz">
- <h1>Content goes here</h1>
- </div>
<div id="vert-hoz"> <h1>Content goes here</h1> </div>
你可以在这里看到线上演示,效果如下图:
图1
为了页面美观起见我给各元素添加了一些背景颜色,这里我们真正感兴趣的是灰色居中部分(此外,你应该注意到为了使背景图片居中你应该设置html、body的高度为100%)。
如图1所示,这个结果正题我们想要的,元素在水平和垂直方向上都完美地实现了居中。文章中已经提到,对元素绝对定位使其top和left值都为50%,然后使用负的顶部填充和左侧填充并使填充的值为高和宽的一半。
尽管看起来没有什么问题,但是使用这种方法存在几个严重的不足,水平或者垂直缩小窗口你就会发现这个问题了。当窗口缩小到比元素还要小时,元素就会开始从窗口的上部和左侧滑出。滑出的部分即使是使用窗口的滚动条也无法可见。这就意味着使用较小屏幕的用户根本看不见这些内容。
图2显示了当窗口缩小时例子中单行文本发生的变化。
图2
文本上部有一半丢失,左侧也有一部分不见了。如果我们进一步缩小窗口,整个文本会完全消失。为了达到我们最初的目的,试着给body增加min-height和min-width属性,但是你会发现这根本没有任何效果,元素依然会滑出窗口之外。
修正后的方法
面对这些问题,一个类似居中技术可以供我们采用,它依然采用了对于顶部的绝对定位,但是对于水平居中使用的是自由浮动。这会限制元素从窗口的左侧滑出。
下面是修正后的代码:
- html,body{
- height:100%;
- margin:0;
- padding:0;
- }
- body{
- background:#eae7d7 url(images/vert-centre.jpg) repeat-x center center;
- text-align:center;
- min-width:626px;
- min-height:400px;
- }
- #vertical{
- position:absolute;
- top:50%;
- margin-top:-198px;/* half main elements height*/
- left:0;
- width:100%;
- }
- #hoz {
- width:624px;
- margin-left:auto;
- margin-right:auto;
- height:394px;
- border:1px solid silver;
- background:#666;
- overflow:auto;/* allow content to scroll inside element */
- text-align:left;
- }
- h1 {color:#fff;margin:0;padding:0}
html,body{ height:100%; margin:0; padding:0; } body{ background:#eae7d7 url(images/vert-centre.jpg) repeat-x center center; text-align:center; min-width:626px; min-height:400px; } #vertical{ position:absolute; top:50%; margin-top:-198px;/* half main elements height*/ left:0; width:100%; } #hoz { width:624px; margin-left:auto; margin-right:auto; height:394px; border:1px solid silver; background:#666; overflow:auto;/* allow content to scroll inside element */ text-align:left; } h1 {color:#fff;margin:0;padding:0}
- <div id="vertical">
- <div id="hoz">
- <h1>Content goes here</h1>
- </div>
- </div>
<div id="vertical"> <div id="hoz"> <h1>Content goes here</h1> </div> </div>
可以在这里查看在线演示。
水平方向上已经达到我们所要的效果,但是当窗口高度缩小时顶部依然会消失,如图3所示:
图3
修正:
为了解决这个问题(也是本文写作的目的)我之前曾经使用过几个比较复杂的方法,但是现在使用的这种方法更简单、更健壮,那就是使用浮动(float)来代替绝对定位。
页面中设置为顶端50%绝对定位的第一个元素进行浮动。然后把浮动向上拉动,大小为元素高度的一半。
下面是必要的修改:
- #vertical{
- float:left;
- height:50%;
- margin-top:-198px;/* half vertical height*/
- width:100%;
- }
#vertical{ float:left; height:50%; margin-top:-198px;/* half vertical height*/ width:100%; }
- <div id="vertical"></div>
- <div id="hoz">
- <h1>Content goes here</h1>
- </div>
<div id="vertical"></div> <div id="hoz"> <h1>Content goes here</h1> </div>
这里有一个在线演示你可以自己观察一下。
图4
重要的是我们对浮动元素设置的宽度是100%,并且记住由于某些浏览器会出现问题我们需要对后面的元素设置clear:both。如果我们不使用“float”,元素依然会居中但是它会从顶端消失掉。
为什么这样可行呢?
实际上这里涉及到浮动的一个有趣的行为,而且也比较好理解它的原理。为什么当我们使用一个静态元素(或者是第一个示例中绝对定位元素)时内容会从窗口的顶端消失,而当我们使用float时却不会产生这个问题呢?
浮动的一个特点就是他们脱离了文本流(尽管你可以通过为后面的元素使用clear来重新控制它们)。浮动元素后面的内容会被移动以为浮动元素留空间(通常是通过浏览器对静态顶部填充来清除浮动)。如果浮动元素根本没有出现该位置,那么后面的内容会占居浮动元素原来在页面中的位置。因此对一个浮动元素使用负的顶部填充(margin),浮动元素会冲破任何包含它的块级元素限制,因为我们前面已经提到浮动元素一开始就脱离了文本流。但是如果我们把元素从包含它的块级元素向外拖动足够远以至于它完全超出父元素范围,那么它后面的任何元素将不会继续跟随其向上移动,但是重新设定包含块级元素的内部内容的大小,会使浮动元素继续浮动。
这就是我们的例子中发生的事情,浮动元素被从body中向上移动,它后面的元素被迫留在body形成的块级元素中。这可能有点难以直接去理解,但是我们可以看一下下面的这个演示。
- .float{
- width:200px;
- height:100px;
- background:red;
- float:left;
- }
- .top{
- background:green;
- height:300px;
- width:100%;
- }
- .follow-on{
- clear:both;
- background:blue;
- height:100px
- }
.float{ width:200px; height:100px; background:red; float:left; } .top{ background:green; height:300px; width:100%; } .follow-on{ clear:both; background:blue; height:100px }
<div class="top">Top</div> <div class="float">Float</div> <div class="follow-on">Following content</div>
上面的代码在页面的顶端设置了一个静态元素,其后是一个浮动元素,再后是其它的静态内容,它就产生了如图5所示的效果,或者可看在线演示。
图5
没有什么特别需要注意的,一切如同我们相像的一样。
如果下面我们给浮动元素增加一个负的100px的顶端边距,我们就得到如图6所示的结果:
- .float{
- width:200px;
- height:100px;
- background:red;
- float:left;
- margin-top:-100px
- }
.float{ width:200px; height:100px; background:red; float:left; margin-top:-100px }
图6
仍然和我们料想的一样,但是如果我们增加负的200px的顶端填充又会发生什么呢?
- .float{
- width:200px;
- height:100px;
- background:red;
- float:left;
- margin-top:-200px
- }
.float{ width:200px; height:100px; background:red; float:left; margin-top:-200px }
图7显示了结果:
图7
和你看到的一样,浮动元素从后面的内容中移走,但是浮动元素后面的内容仍然会停留在包含它的元素的顶端(如在绿色元素的下面)。在我们的前面的例子中,当我们向外移动浮动元素时,也是发生了同样的事情。
但是如果我们从红色的div去掉float属性,那么红色的div和它后面下面的内容就会被移动到绿色元素的上面。
图8
浮动元素负的边距产生变化,后面的内容也会相应地向上移动。