CSS实现侧栏固定宽度,内容栏宽度自适应

在网页设计中,很常用侧栏固定宽度,内容栏的宽度自适应,这样可以在不同的分辨率下,带给客户同样的良好体验。

这里以我博客的右侧栏固定、左侧内容部分宽度自适应为例。

html部分:

<div id="wrapper">
	<div id="sidebar" style="height:240px;">固定宽度区</div>
	<div id="content" style="height:340px;">自适应区</div>
</div>
<div id="footer">后面的一个DIV,以确保前面的定位不会导致后面的变形</div>

#wrapper 用来包裹定位部分,#footer 用来测试前边的定位不会影响后边的部分,下面是几种实现方法及适用情景,请各位需要的童鞋要认真阅读。

一、固定宽度区浮动 float,自适应区宽度自适应设置 margin

CSS部分:

#wrapper { overflow:hidden; *zoom:1; }
	#content ,#sidebar { background-color:#eee; }
	#sidebar { float:right; width:300px; }
	#content { margin-right:310px; }
#footer { background-color:#f00;color:#fff; margin-top:1em; }

其中 sidebar 设置固定宽度 300px 并 float 右浮动;content 没有设置宽度,而是加了个 margin-right:310px; 因为 sidebar 在右边,值比sidebar的宽度大一点点——以便区分他们的范围。

注:html 部分必须使用 div 标签,因为div有个默认属性,即如果不设置宽度,div也会自动填满父标签的宽度,假设 content 的默认宽度是100%,那么它设置了margin后,他的宽度就变成了100%-310,此时content发现自己的宽度可以与sidebar挤在同一行了,于是他俩就在同一行了。

这里的宽度100%是相对于他的父标签来的,如果我们改变了他父标签的宽度,那content的宽度也就会变——比如我们把浏览器窗口缩小,那wrapper的宽度就会变小,而content的宽度也就变小,但他的实际宽度100%-310始终是不会变的。

这个方案很不错,但郁闷的是 html 代码中的固定宽度部分 sidebar 必须在自适应 content 之前,否则这个方法就会失灵,但考虑到 content 部分是网页的主要内容,在侧栏 sidebar 之后输出怎么都不爽。

怎么解决呢?

我们先修改想要的 html 部分:

<div id="wrapper">
	<div id="content" style="height:340px;">自适应区,在前面</div>
	<div id="sidebar" style="height:240px;">固定宽度区</div>
</div>
<div id="footer">后面的一个DIV,以确保前面的定位不会导致后面的变形</div>

二、固定宽度区使用绝对定位,自适应区仍然设置margin

先上 CSS 部分:

#wrapper { *zoom:1; position:relative; }
	#sidebar { width:300px; position:absolute; right:0; top:0; }
	#content { margin-right:310px; }

sidebar加上了绝对定位,但它的父标签 wrapper 一定要加上相对定位,否则 sidebar 会太绝对而跑到整个页面的右上角。

为了测试,我们将 sidebar 的高度增加到比 content 高,这时候我们再看看 footer ,靠,被上边的定位给影响了!只能接着找解决方法。

三、漂浮 float、margin 联合

这里总结一下我们想要实现的几个点:

1、sidebar宽度固定,content宽度自适应;
2、content要在sidebar之前;
3、不能影响其它部分的正常定位;

由于B方案的绝对定位会影响到其他部分的定位,所以必须放弃。

如果content和sidebar一样,都用float,那content的自适应宽度就没戏了;如果不给content加float,那sidebar又会跑到下一行去。那我们就尝试一下:float与margin结合,看看能不能实现。

先把 content 的宽度设为100%,然后让它 float:left,最后把它向左移动310,以便于sidebar能挤上来。

结果 content 里面的内容也会跟着左移310,导致移出页面球了,所以要把内容部分重新移回原位。

这里需要一个新的 div 来包裹内容,最终的 html 代码如下:

<div id="wrapper">
	<div id="content" style="height:140px;">
		<div id="content2">content自适应区,在前面</div>
	</div>
	<div id="sidebar" style="height:240px;">sidebar固定宽度区</div>
</div>

css 部分:

#sidebar { width:300px; float:right; }
#content { width:100%; float:left; margin-left:-310px; }
	#content2 { margin-left:310px; }

如此,原来包裹内容的 content 就变成了 content2,他的宽度仍然是:100%-310。

其中的“-310px”是将内容移回原位的作用。

来个示例演示大家看看效果吧:演示Demo

四、标准浏览器的解决方案

w3c标准已经为我们提供了制作这种自适应宽度的标准方法。

把 wrapper 设为 display:table 并指定宽度100%,然后把 content和sidebar 设为 display:table-cell;,而 sidebar 只需要指定宽度300px,如此就能实现 content 的宽度自适应了。

这种方法很简装,但 display:table-cell; 只有IE8+及其它现代浏览器才支持。

写在最后:如果不考虑 IE7 及以下版本,可使用D方案;如果不在意sidebar与content的顺序,可使用A方案,否则使用C方案。