【问题标题】:Sticky flexible footers and headers CSS working fine in WebKit, but not in Gecko粘性灵活的页脚和页眉 CSS 在 WebKit 中运行良好,但在 Gecko 中不行
【发布时间】:2012-09-26 16:01:02
【问题描述】:

我正在尝试构建一个允许高度灵活的页眉和页脚的布局,中间的部分占用剩余空间。中间的任何溢出都应该为这个中间部分提供一个滚动条。

我拥有的适用于 Safari 和 Chrome 的代码是:

<!DOCTYPE html>
<html>
  <head>
    <style>
      html, body {
        margin: 0;
        padding: 0;
        height: 100%;
      }

      .l-fit-height {
        display: table;
        height: 100%;
      }

      .l-fit-height > * {
        display: table-row;
        height: 1px;
        background-color: red;
      }

      .l-fit-height-expanded {
        height: auto;
        background-color: blue;
        display: table-row;
      }

      .l-scroll-content {
        height: 100%;
        overflow-y: auto;
      }
    </style>
  </head>
  <body>
    <div class="l-fit-height">
      <section>
        Header
      </section>
      <section class="l-fit-height-expanded">
        <div class="l-scroll-content">
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
          <p>Foo</p>
        </div>
      </section>
      <section>
        Footer
      </section>
    </div>
  </body>
</html>

我终其一生都无法弄清楚为什么 Firefox 的行为会有所不同。中间的内容会正确扩大高度,但不会缩小超过内容的高度。

很难知道什么是正确的行为。有什么想法吗?

编辑

类似的示例设置在这里:http://jsfiddle.net/t3mZF/

有趣的是,如果将 .l-fit-height-row-content 更改为 display: table-cell,那么 WebKit 和 Gecko 会表现出相同的行为或忽略溢出。

如果使用display: block,则 WebKit 会提供所需的行为(滚动条和页脚保留在视口底部),但 Firefox 拒绝添加滚动条,而是将页脚推离屏幕底部(滚动条在视口上 - 不是中间内容)。

我还开了bugzilla ticket

【问题讨论】:

    标签: html css firefox css-tables


    【解决方案1】:

    我发现有几个额外的 div 和一个重要的display: inline-block 可以在 Firefox 中使用 Torben 提到的绝对定位技巧。这意味着完全灵活的页眉和页脚可以作为纯 CSS 解决方案。

    <!DOCTYPE html>
    <html>
      <head>
        <style>
          html, body {
            margin:  0;
            padding: 0;
            height:  100%;
          }
    
          .l-fit-height {
            display: table;
            height:  100%;
          }
    
          .l-fit-height-row {
            display: table-row;
            height:  1px;
          }
    
          .l-fit-height-row-content {
            /* Firefox requires this */
            display: table-cell;
          }
    
          .l-fit-height-row-expanded {
            height:  100%;
            display: table-row;
          }
    
          .l-fit-height-row-expanded > .l-fit-height-row-content {
            height: 100%;
            width:  100%;
          }
    
          .l-scroll {
            /* Firefox requires this to do the absolute positioning correctly */
            display:    inline-block;
            overflow-y: auto;
            position:   relative;
          }
    
          .l-scroll-content {
            position: absolute;
            top:      0;
            bottom:   0;
          }
        </style>
      </head>
      <body>
        <div class="l-fit-height">
          <section class="l-fit-height-row">
            <div class="l-fit-height-row-content">
              Header
            </div>
          </section>
          <section class="l-fit-height-row-expanded">
            <div class="l-fit-height-row-content l-scroll">
              <div class="l-scroll-content">
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
                <p>Foo</p>
              </div>
            </div>
          </section>
          <section class="l-fit-height-row">
            <div class="l-fit-height-row-content">
              Footer
            </div>
          </section>
        </div>
      </body>
    </html>
    

    希望对你有帮助

    【讨论】:

    • 干得好!我也试过display:inline-block,当我在寻找你的问题的答案时它对我不起作用,但显然我做错了什么。这完美地工作。也可以对我的CSS-Layout-Grid 代码进行很好的改进。很高兴看到什么时候会变得更好:)
    • 我发现这很乏味,因为所有的类名都被过度使用了,我相信其他人也会这样做。然而,这是一个非常有用的解决方案,我认为如果有人仅仅因为他或她难以遵循它而不使用它,那将是一种耻辱。因此,我用一个我希望更语义化、更容易理解的小提琴示例更新了小提琴示例,供任何希望使用它的人使用:jsfiddle.net/t3mZF/17
    【解决方案2】:

    我认为您在这里遇到了两个综合问题:

    1. 表格尺寸并不像您对普通 div 所期望的那样固定。表格通常会随着内容而增长,如果内容太大,则不会太在意其高度属性。

      因此,您必须通过绝对定位将滚动框的内容从内容大小计算中排除。现在剩下要做的就是设置滚动框的位置和大小以填充展开的表格行的完整空间。然而,这引发了另一个问题:

    2. 直接的解决方案是为表格行设置position:relative;,为滚动框设置width:100%;height:100%;,但这不起作用,因为大多数浏览器都会忽略表格行的位置属性。您可以在表格行和滚动框之间插入另一个带有display:table-cell;position:relative; 的 div,但这仅适用于除 Firefox 之外的所有浏览器,因为 Firefox 不允许在表格中进行任何相对定位。

      然而,Firefox 允许对表格本身进行相对定位,因此诀窍是为 table-div 设置position:relative;,并根据整个表格的尺寸设置滚动框的大小和位置。

    如您所料,如果您想使用纯 CSS 解决方案,这会带来一些限制,但还是有一些限制。除此之外,还有一种优雅的方式来解决 JavaScript 问题,我也将其包含在代码中。

    下面的代码包含三种解决问题的方法。两种是纯 CSS 解决方案,一种是使用 JavaScript。我已尝试尽可能少地更改您的代码并评论了所有更改,所以我认为您会发现自己的方式。如果您仍有疑问,请发表评论。

    <!DOCTYPE html>
    <html>
      <head>
        <style>
          html, body {
            margin: 0;
            padding: 0;
            height: 100%;
          }
    
          .l-fit-height {
            display: table;
            height: 100%;
            /* NOTE Use the table as refernece for absolute positioning. This */
            /*      is the only place where Firefox accepts the position property */
            /*      within a table. */
            position: relative;
          }
    
          .l-fit-height > * {
            display: table-row;
            height: 1px;
            background-color: red;
          }
    
          .l-fit-height-expanded {
            /* NOTE Set the important flag to override the generic setting */
            height: auto !important;
            background-color: blue;
            display: table-row;
          }
    
          .l-scroll-content {
            /* NOTE We will set the height attribute later */
            /* height: 100%; */
            overflow-y: auto;
            /* INFO Prevent the table from growing in height */
            position: absolute;
            /* INFO The content should span the full width */
            width: 100%;
          }
    
          /* INFO Since Firefox only allows absolute positioning relative to the */
          /*      whole table, setting the correct height is a bit tricky. I've */
          /*      found two pure CSS solutions which work, but both have their */
          /*      glitches. If JavaScript is ok for you, there's another solution */
          /*      which I would recommend. */
    
          /* INFO Example for percentage height footer and header. This sometimes */
          /*      leaves one or two pixels between the scroll-box and the footer. */
          /* REMOVE THIS LINE TO ACTIVATE
          .l-fit-height > * {
            height: 20%;
          }
          .l-scroll-content {
            height: 60% !important;
          }
          /**/
    
          /* INFO Example for fixed height footer and header. Unfortunately this */
          /*      makes the header and footer-content unclickable, but I'm quite */
          /*      sure this could be solved by setting a z-index. */
          /* REMOVE THIS LINE TO ACTIVATE
          .l-fit-height > * {
             height: 40px;
          }
          .l-scroll-content {
             -moz-box-sizing: border-box;
             -webkit-box-sizing: border-box;
             box-sizing: border-box;
             height: 100%;
             border-top: 40px solid transparent;
             margin-top: -40px;
             border-bottom: 40px solid transparent;
             margin-bottom: -40px;
          }
          /**/
        </style>
        <script type="text/javascript">
            // INFO Example how to fix the problem with JavaScript. This works for
            //      all kinds of heights (flexible, percentage and fixed) and has no
            //      issues except for the need of JavaScript to see a correctly
            //      layouted page.
            //* REMOVE THE FIRST SLASH TO DEACTIVATE
            function fixScrollContentHeight() {
                var nodes = document.getElementsByClassName('l-scroll-content');
                for (var i = 0; i < nodes.length; i++)
                    nodes[i].style.height = nodes[i].parentNode.offsetHeight+'px';
            }
            window.onload = fixScrollContentHeight;
            window.onresize = fixScrollContentHeight;
            //*/
        </script>
      </head>
      <body>
        <div class="l-fit-height">
          <section>
            Header
          </section>
          <section class="l-fit-height-expanded">
            <div class="l-scroll-content">
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
              <p>Foo</p>
            </div>
          </section>
          <section>
            Footer
          </section>
        </div>
      </body>
    </html>
    

    PS:我无法用 IE 测试我的代码,但我认为它也应该在那里工作。

    【讨论】:

    • 太棒了!很好的答案。我想我将不得不选择 JS 根,因为百分比和像素是不可能的。感谢您解释我遇到的行为。
    • Torben:我想我找到了一种方法可以让 Firefox 的绝对定位正常工作。请看我的回答。
    【解决方案3】:

    从这里How to get firefox to show an auto horizontal scollbar for a div?

    Firefox 无法识别 overflow-x 和 overflow-y。

    改为使用overflow:-moz-scrollbars-horizontal;overflow:-moz-scrollbars-vertical;

    【讨论】:

    • .l-scroll-content 更改为overflow: -moz-scrollbars-vertical; 使其永久滚动条,但仍会强制视口中的页眉和页脚,因为中间部分无法缩小。
    • Mozilla 现已弃用 -moz-scrollbars-horizo​​ntal 和 -moz-scrollbars-vertical...developer.mozilla.org/en-US/docs/CSS/overflow
    • 如果我没看错,问题不在于滚动条不可见,而是滚动框的大小不正确。
    【解决方案4】:

    请检查我的更新。

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <title>Untitled Document</title>
    <style>
    
    html, body {
    height:99.9%;
    margin:0;
    padding:0;
    }
    
    #wrapper {
        margin: auto;
        overflow: hidden;
        position: relative;
        width: 99.9%;
    }
    
    #main {
        margin-bottom: 67px;
        margin-top: 77px;
        overflow: auto;
        padding-bottom: 80px;
    }
    
    #footer {
        bottom: 0;
        clear: both !important;
        height: 75px !important;
        margin-top: -68px !important;
        position: fixed !important;
    }
    
    #header {
        background: none repeat scroll 0 0 #FFFFFF;
        border: 1px solid #000000;
        height: 75px !important;
        margin-top: -77px;
        overflow: hidden;
        position: fixed;
        width: 100%;
    }
    </style>
    
    </head>
    
    <body>
    
         <div id="wrapper">
             <div id="main">
                <div id="header">header contents goes here</div>
    
                <div id="content">
                    main contents
                </div>
             </div>
         </div>
         <div id="footer" style="width:99.9%; margin:auto; border:solid 1px #666; ">
          Footer content goes here
         </div>
    
    </body>
    </html>
    

    【讨论】:

    • 我已经在 Chrome 和 Firefox 中尝试过了,它不会给出粘性页眉和页脚(在视口中始终可见的类型)。因此,中心部分不会滚动。
    • 我已经尝试过更新版本,但是当我用更多内容填充中心部分时,它会在整个视口中添加一个滚动条,并溢出到页脚中。页眉和页脚也是静态大小,不灵活。
    猜你喜欢
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-28
    • 2013-01-10
    相关资源
    最近更新 更多