2列div布局:右侧列固定宽度,左侧流式布局。

164

我的要求很简单:2列布局,其中右侧列具有固定大小。不幸的是,我在stackoverflow和Google中都没有找到有效的解决方案。每一种在那里描述的解决方案,如果我在自己的上下文中实施,都会失败。当前的解决方案是:

div.container {
    position: fixed;
    float: left;
    top: 100px;
    width: 100%;
    clear: both;
}

#content {
    margin-right: 265px;
}

#right {
    float: right;
    width: 225px;
    margin-left: -225px;
}

#right, #content {
    height: 1%; /* fixed for IE, although doesn't seem to work */
    padding: 20px;
}

<div class="container">
    <div id="content">
        fooburg content
    </div>
    <div id="right">
        test right
    </div>
</div>

使用上述代码,我得到了以下结果:
|----------------------- -------|
| fooburg content  |            |
|-------------------------------|
|                  | test right | 
|----------------------- -------|

请提供建议。非常感谢!
8个回答

273

移除左列的浮动。

在HTML代码中,右列需要在左列之前。

如果右列有一个浮动(和一个宽度),并且左列没有宽度和浮动,那么它将是灵活的 :)

同样,对于外部div应用overflow: hidden和一些高度(可以是自动),以便它包围两个内部div。

最后,在左列中添加width:autooverflow:hidden,使其与右列独立(例如,如果您调整了浏览器窗口大小,并且右列接触到左列,则在没有这些属性的情况下,左列会绕过右列,具有此属性将使其保持在原地)。

示例HTML:

<div class="container">
    <div class="right">
        right content fixed width
    </div>
    <div class="left">
        left content flexible width
    </div>
</div>

CSS:

.container {
   height: auto;
   overflow: hidden;
}

.right {
    width: 180px;
    float: right;
    background: #aafed6;
}

.left {
    float: none; /* not needed, just for clarification */
    background: #e8f6fe;
    /* the next props are meant to keep this block independent from the other floated one */
    width: auto;
    overflow: hidden;
}​​

这里有个例子:http://jsfiddle.net/jackJoe/fxWg7/


2
@Mir 在任何列中使用 clear: both 不会影响外部浮动。除非您将清除放置在列之间的同一级别上,否则这不是“脆弱”的。如果您将其放置在末尾,则不会造成任何损害。 - jackJoe
6
我会考虑使用Adam的例子。我认为在你的HTML标记中将右列放在左列之前不是一个好主意。 - Danny_Joris
1
@Danny_Joris 我同意。此外,如果你使用媒体查询,在现在很难将右列放在左列下面。 - andrewtweber
2
对于那些好奇它是如何工作的人,可以在这里找到解释:https://dev59.com/j4Lba4cB1Zd3GeqPjMYS#25476238 - Hashem Qolami
1
我想知道是否有一种方法可以使右列在左列之后,以便它可以正确堆叠(而不使用flexbox)。 - Dominic
显示剩余8条评论

73

请查看http://www.alistapart.com/articles/negativemargins/,这正是您需要的(其中有示例4)。

<div id="container">
    <div id="content">
        <h1>content</h1>
        <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.  Phasellus varius eleifend tellus. Suspendisse potenti. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Nulla facilisi. Sed wisi lectus, placerat nec, mollis quis, posuere eget, arcu.</p>
        <p class="last">Donec euismod. Praesent mauris mi, adipiscing non, mollis eget, adipiscing ac, erat. Integer nonummy mauris sit amet metus. In adipiscing, ligula ultrices dictum vehicula, eros turpis lacinia libero, sed aliquet urna diam sed tellus. Etiam semper sapien eget metus.</p>
    </div>
</div>

<div id="sidebar">
    <h1>sidebar</h1>
    <ul>
        <li>link one</li>
        <li>link two</li>
    </ul>
</div>

#container {
    width: 100%;
    background: #f1f2ea url(background.gif) repeat-y right;
    float: left;
    margin-right: -200px;
}
#content {
    background: #f1f2ea;
    margin-right: 200px;
}
#sidebar {
    width: 200px;
    float: right;

1
太棒了,简单易行的解决方案,而且还保持了正确的HTML顺序! - user1794295
我之前不知道这个。我怎么会不知道这个呢?太完美了!我一直在尝试实现“流体输入,固定宽度搜索按钮”的效果,显然源代码的顺序非常重要。这个方法解决了我的问题。谢谢! - Malabar Front
我喜欢这个解决方案,因为在移动断点时,右侧列/侧边栏将出现在左列内容下方而不是上方。 - dougtesting.net
我用这种方法无法使右列到达顶部。 - mulllhausen

29

最好避免在左侧之前放置右侧内容,而是使用负的右边距。

同时通过包含@media设置来实现响应式设计,在窄屏幕上使右侧内容落在左侧下方。

<div style="background: #f1f2ea;">
  <div id="container">
    <div id="content">
        <strong>Column 1 - content</strong>
    </div>
  </div>
  <div id="sidebar">
    <strong>Column 2 - sidebar</strong>
  </div>
<div style="clear:both"></div>

<style type="text/css">
#container {
    margin-right: -300px;
    float:left;
    width:100%;
}
#content {
    margin-right: 320px; /* 20px added for center margin */
}
#sidebar {
    width:300px;
    float:left
}
@media (max-width: 480px) {
    #container {
        margin-right:0px;
        margin-bottom:20px;
    }
    #content {
        margin-right:0px;
        width:100%;
    }
    #sidebar {
        clear:left;
    }
}
</style>

1
很棒的解决方案。在HTML中将右侧保持在左侧下方对于像博客这样左侧具有更重要内容的布局至关重要。 - Jake
3
非常好的回答!这里有一个在Codepen上的工作示例:http://codepen.io/martinkrulltott/pen/yNxezM - Martin

13

目前最简单、最灵活的解决方案是使用table display

在HTML中,左侧div应先出现,右侧div应次之……我们从左到右阅读和书写,因此将div放置在右侧并不合适。

<div class="container">
    <div class="left">
        left content flexible width
    </div>
    <div class="right">
        right content fixed width
    </div>
</div>

CSS:

.container {
  display: table;
  width: 100%;
}

.left {
  display: table-cell;
  width: (whatever you want: 100%, 150px, auto)
}​​

.right {
  display: table-cell;
  width: (whatever you want: 100%, 150px, auto)
}

案例示例:

// One div is 150px fixed width ; the other takes the rest of the width
.left {width: 150px} .right {width: 100%}

// One div is auto to its inner width ; the other takes the rest of the width
.left {width: 100%} .right {width: auto}

很好,运行得很顺利,谢谢。有时候在使用flexbox不可行的情况下,表格是一个合适的选择。与其将正确的内容放在DOM中无法正确堆叠的位置之前... - Dominic
1
我喜欢这个“干净”的解决方案。然而,将您的div放入表格单元格模式中的唯一问题是,您最好使用表格和Tds。并且你会失去像溢出滚动等功能。 - MarzSocks
这是不公平的,因为这个解决方案至少在语义上是正确的,并且对于简单的RWD技术也很友好,而使用带有tdtable则完全不是! - ianp
这种方法可以轻松地允许媒体查询在列变得太窄时将表格转换为普通的div。非常简洁明了,我喜欢。 - AnthonyVO

6
我想建议一个尚未提到的解决方案:使用CSS3的calc() 来混合使用%px单位。如今,calc()有着很好的支持,可以快速构建相当复杂的布局。
这里是下面代码的JSFiddle链接HTML:
<div class="sidebar">
  sidebar fixed width
</div>
<div class="content">
  content flexible width
</div>

CSS:

.sidebar {
    width: 180px;
    float: right;
    background: green;
}

.content {
    width: calc(100% - 180px);
    background: orange;
}

这里有另一个JSFiddle演示了如何将这个概念应用于更复杂的布局。我在这里使用了SCSS,因为它的变量允许编写灵活且自描述的代码,但如果“硬编码”值不是问题,则可以轻松地使用纯CSS重新创建布局。


2

这是一个通用的、基于HTML源代码的解决方案,其中:

  • 源代码中第一列是流式的
  • 源代码中第二列是固定的
    • 可以使用CSS将此列向左或向右浮动

固定/第二列在右侧

#wrapper {
  margin-right: 200px;
}
#content {
  float: left;
  width: 100%;
  background-color: powderblue;
}
#sidebar {
  float: right;
  width: 200px;
  margin-right: -200px;
  background-color: palevioletred;
}
#cleared {
  clear: both;
}
<div id="wrapper">
  <div id="content">Column 1 (fluid)</div>
  <div id="sidebar">Column 2 (fixed)</div>
  <div id="cleared"></div>
</div>

左侧固定/第二列

#wrapper {
  margin-left: 200px;
}
#content {
  float: right;
  width: 100%;
  background-color: powderblue;
}
#sidebar {
  float: left;
  width: 200px;
  margin-left: -200px;
  background-color: palevioletred;
}
#cleared {
  clear: both;
}
<div id="wrapper">
  <div id="content">Column 1 (fluid)</div>
  <div id="sidebar">Column 2 (fixed)</div>
  <div id="cleared"></div>
</div>

另一个解决方案是使用display: table-cell,这将导致列高相等。


右侧的第二列不起作用。如果左列已经充满文本,那么右列将显示为新行。 - TomSawyer
你有没有试过增加更多的内容和调整大小。我刚刚测试了你的代码,不起作用。 - TomSawyer
@TomSawyer,我不确定你在说什么。这是我试图添加更多内容的链接:http://jsfiddle.net/salman/mva6cnxL/ 和 http://jsfiddle.net/salman/mva6cnxL/1/。运行得非常完美。 - Salman A
正是我所寻找的。谢谢。 - user9168386

0

嘿,你可以对两个容器应用固定宽度,然后使用另一个div类,其中clear:both,就像这样

div#left {

width: 600px;
float: left;
}

div#right {

width: 240px;
float: right;

}

div.clear {

clear:both;

}

将一个清除浮动的 div 放置在左右容器下方。


-3
我简化了它:我编辑了jackjoe的答案。我认为不需要高度自动等。

CSS:

#container {
position: relative;
margin:0 auto;
width: 1000px;
background: #C63;
padding: 10px;
}

#leftCol {
background: #e8f6fe;
width: auto;
}

#rightCol {
float:right;
width:30%;
background: #aafed6;
}

.box {
position:relative;
clear:both;
background:#F39;
 }
</style>

HTML:

<div id="container">

  <div id="rightCol"> 
   <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>

  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>
 </div>

 <div id="leftCol">

   <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>

  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>
  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Phasellus varius eleifend。

</div>

</div>

<div class="box">
  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>

  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>
  <p>Lorem ipsum dolor sit amet,consectetuer adipiscing elit. Phasellus varius eleifend. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.Phasellus varius eleifend.</p>
</div>

原始问题要求一个具有固定大小的右侧列。 - Dr. Aaron Dishno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接