【问题标题】:Responsive 2-column CSS layout including sidebar with fixed width?响应式 2 列 CSS 布局,包括固定宽度的侧边栏?
【发布时间】:2013-03-04 10:48:53
【问题描述】:

在任何地方都找不到解决方案(我猜这一定是一个很常见的问题)。

我正在创建一个带有侧边栏的响应式设计,其中侧边栏需要具有 200 像素的固定宽度并且具有未知的高度。我怎样才能使主要内容区域占据所有剩余的宽度,而不会出现任何异常。

我最接近它的是以下,但它的问题是侧边栏可以与页脚重叠。谁能建议我的代码修复,或与我分享一些有效的代码?

            * {
            padding: 0;
            margin: 0;
            outline: 0;
            -moz-box-sizing: content-box;
            -webkit-box-sizing: content-box;
            box-sizing: content-box;
        }
        body {
            background: orange;
        }
        #container {
            max-width: 1000px;
            min-width: 768px;
            margin: 0 auto;
            background: yellow;
            position: relative;
            height: 100%;
        }
        #header {
            background: purple;
            color: white;
            text-align: center;
            padding: 10px;
        }
        #main {
            position: relative;
        }
        aside {
            background: blue;
            width: 200px;
            color: white;

            position: absolute;
            top: 0;

            /* change this to "right: 0;" if you want the aside on the right. Also, change the "margin-left" code, below. */
            left: 0;

            padding-top: 20px;
            padding-bottom: 20px;

            padding-left: 10px; /* If you change this value, remember to change the margin-left value of #primary */
            padding-right: 10px; /* ditto */
        }
        #primary {
            background: red;

            /* change this to margin-right if you want the aside on the right. Also change the "left" code, above. */
            margin-left: 220px; /* aside_width + aside_left_padding + aside_right_padding = 200px + 10px + 10px */
            padding: 1em; /* whatever */
        }
        #footer {
            background: green;
            color: white;
            padding: 10px;
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
        }

        <div id="container">
        <div id="header">
            <h1>LAYOUT TEST #2</h1>
        </div>
        <div id="main">
            <div id="primary">
                <h2>THIS IS THE MAIN CONTENT ** THIS IS THE MAIN CONTENT ** THIS IS THE MAIN CONTENT</h2>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <h2>sub heading</h2>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <h2>sub heading</h2>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
            </div>
            <aside>
                <h3>navigation (left)</h3>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
                <p>lorem ipsum</p>
            </aside>
        </div>
        <div id="footer">
            <h1>LAYOUT TEST #2</h1>
        </div>
    </div>

【问题讨论】:

  • 无论你做什么,你都必须先用 flexbox 创建它,然后再为愚蠢的浏览器创建一个后备。
  • 使用 flexbox:jsfiddle.net/rudiedirkx/CjWbv/2 在 Chrome 25 中工作,但根据 MDN:“Gecko 实现没有前缀,但在偏好之后”(在 about:config 中,非常奇怪)。

标签: html css layout fluid-layout


【解决方案1】:
#main { position: relative; overflow:hidden;}

这会阻止侧边栏行为不端。

【讨论】:

    【解决方案2】:

    您可以通过将margin-bottom: FOOTER_HEIGHT 添加到aside 来修复它,或者改用以下方法:

    <div id="container">
        <div id="header">
            YOUR_HEADER
        </div>
        <div id="body>
            <div id="sidebar">
                YOUR_SIDE_BAR_CONTENT
            </div>
            <div id="main">
                YOUR_CONTENT
            </div>
            <br />
        </div>
        <div id="footer">
            YOUR_FOOTER
        </div>
    </div>
    

    还有 CSS:

    #sidebar {
        width: ...;
        height: ...;
        float: right;
    }
    #main {
        margin-right: WIDTH_OF_SIDE_BAR;
    }
    #body > br {
        clear: both;
    }
    

    【讨论】:

      【解决方案3】:

      我认为所有position: absolute 的方法并不是最好的。

      1. 您希望拥有一个具有max-widthmargin: 0 auto 的容器元素。不知道你为什么也想要min-width;当然可以。

      2. 您放置的任何块元素都会自动获取父元素的所有width。因此,headerfooter 没有问题,只需将它们放置在正确的位置,它们就会正确呈现。

      3. 正如您所做的那样,为您的主要部分使用容器元素。由于元素是从左到右呈现的,您可能需要在 #primary 之前编写 aside

      4. float: left 应用到具有所需固定宽度的aside

      5. 主要内容#primary元素会自动占用剩余空间(或者直接应用width: auto注意:剩余空间是剩余空间的父元素,所以,如果你在父元素上设置min-width,不要指望你的#primary会更窄!

      6. 现在你会遇到一个问题:容器元素#main 不会得到正确的高度。 That's because of an issue with float。要强制父元素达到其浮动子元素的高度,请使用overflow: hidden

      你应该准备好了。这是slightly modified version of your code

      【讨论】:

      • 那太恶心了。您正在使用隐式溢出来更改 #main 的内容位置。这很快就会失控。
      • 您能详细说明一下吗?如果有讨厌的东西,我很乐意删除/编辑我的答案;但正如我在文章中指出的那样,还有其他解决方案可以包装元素的浮动内容。 overflow 是最简单和最快的;我从来没有遇到过任何问题。
      • 不要删除您的答案。这是一个有效的答案。但这很讨厌,因为现在您的 #primary 是 1000px 宽,而实际上您希望它是 800px 宽(这就是它的外观)。我认为“它看起来如何”应该是它的样子。如果您假设#primary 具有正确的尺寸,您以后可能会犯错误。这就是为什么(我认为!)它很讨厌。使用 calc() 和 flexbox,视觉尺寸是真实的/实际的。
      • 啊,好吧!当然flexbox 是解决这个问题的确切解决方案;不幸的是,浏览器支持还太稀少,不适合生产,我想。无论如何,您将不得不依赖某种后备。它可能会是这样的东西或 javascript。
      • 是的 =( 4 年他们一直在 flexbox 上工作。太棒了。我仍然更喜欢你的方法而不是 JS。你会认为有一个正确的方法可以很好地支持这样做......
      【解决方案4】:

      1 = 使用弹性框:http://jsfiddle.net/rudiedirkx/CjWbv/2/

      #main {
          display: flex;
      }
      #primary {
          background: #bbb;
          flex: 1;
      }
      aside {
          background: #ddd;
          flex: 0 0 200px;
      }
      

      2 = calc(): http://jsfiddle.net/rudiedirkx/CjWbv/

      #main:after { clearfix here }
      #primary {
          float: left;
          background: #bbb;
          width: calc(100% - 200px);
      }
      aside {
          background: #ddd;
          float: right;
          width: 200px;
      }
      

      两者都需要对旧版浏览器(和供应商前缀)进行回退。从其他答案中选择。

      【讨论】:

        【解决方案5】:

        在我们得到 flexbox 之前,我相信做你正在寻找的最好的方法是简单地使用 css display: table;。您需要将容器设置为display: table;,然后将每一列设置为display: table-cell;。这将消除使用浮点数或任何其他 JS 魔法的需要。此外,这适用于 IE8。我知道使用任何带有“表格”一词的布局都感觉很粗略,但试一试。

        Check out this link for more info.

        Here is an updated version of your code.

        编辑:示例代码

        html:假设这个标记

        <div id="main">
            <div id="sidebar"></div>
            <div id="content"></div>
        </div>
        

        css:

        #main {
            display: table;
            width: 100%;
        }
        #sidebar {
            display: table-cell;
            width: 200px;
        }
        #content {
            display: table-cell;
            /* no need to specify width. 
             * width will auto fill remaining width of parent `table` #main.
             * so 100% - 200px */
        }
        

        【讨论】:

        • 我们有 Flexbox... 只有仍然重要的 IE 9 没有 Flexbox。不过喜欢这个解决方案。超级简单。只要您在答案中添加代码即可。
        • 虽然不赞成使用表格进行布局,但这并不是真正使用表格 :P 所以这是一个非常好的解决方案