【问题标题】:How do I use CSS to position a fixed variable height header and a scrollable content box?如何使用 CSS 定位固定可变高度标题和可滚动内容框?
【发布时间】:2011-06-20 16:22:43
【问题描述】:

我正在尝试制作一个带有固定标题和可滚动内容区域的网页。当标题具有已知高度时,这很简单,但我正在努力寻找标题流动时的解决方案。

我想要的布局是:

--------------
head
--------------
content
--------------

其中“head”是其内容所需的任何高度,“content”没有最小高度,但会在变为可滚动之前达到视口底部的最大高度。

这些天在纯 CSS 中可能吗?我的目标是 IE8+。

为了澄清我想要什么,here is what I would do if I knew the height of the header:

<!DOCTYPE html>
<html>
    <head>
        <style type="text/css">

body {
    margin: 0;
}

#head {
    background: yellow;
    height: 20px; /* I can't rely on knowing this. */
}

#content {
    background: red;
    position: absolute;
    top: 20px; /* here also */
    bottom: 0;
    width: 100%;
    overflow: auto;
}

        </style>
    </head>
    <body>
        <div id="head">some variable height content</div>
        <div id="content">
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
            scrollable content<br/>
        </div>
    </body>
</html>

【问题讨论】:

  • 你想要滚动条在内容旁边,还是沿着整个页面的高度?
  • 如果标题是“固定的”,它的高度是什么?
  • 滚动条最好在内容旁边。当我说固定时,我的意思是在位置上,即。它不会随着主要内容滚动。
  • 我为固定高度的情况添加了一个示例,以显示我想要的内容。尝试调整视口的大小以查看它的作用。
  • @David:添加了一个 jsFiddle 链接,以便人们看到。您在这里寻找什么样的兼容性?

标签: css


【解决方案1】:

假设“固定”是指 position:fixed,我认为这在纯 CSS 中是不可能的,因为 position:fixed 将元素从文档流中取出。

但是,只需要一两行 JavaScript 就可以得到你想要的。像这样的东西(未经测试,仅用于示例目的,需要调整语法才能实际工作):

var height = document.getElementById("head").offsetHeight;
document.getElementById("content").style.marginTop = height + 'px';

类似的东西应该让你得到固定&lt;div&gt;的渲染高度,并相应地设置内容&lt;div&gt;的边距。您还需要在固定的&lt;div&gt; 上显式设置背景颜色,否则滚动时内容会渗入固定的颜色。

【讨论】:

  • 页面调整大小后别忘了重新计算
  • 我可以设计页眉,这样当它的宽度改变时它不会重新流动,所以我不必担心调整大小。
  • 如果您可以使用 javascript,这是一个很好的答案,因为它甚至不需要在您的 freezepane 上指定初始高度或在随后的容器上指定边距。我只是将它推入 pageLoad() 并添加一个事件监听器以调整页面大小。
  • 要么是一个用于调整页面大小的事件监听器,要么是一个 setInterval 以确保它被正确定位..
  • 我刚刚遇到了同样的问题,我将与上面非常相似的代码放入由 调用的函数中,这似乎有效。在我的情况下,较低的 div 已经定义为 position: relative 所以我设置了 content.style.top 而不是 marginTop,这可能有优点和缺点,但想法相同。
【解决方案2】:

Here's 一个解决方案,但它是一个骗子。基本上,你有一个重复的标题元素,将内容下推,在固定位置一下:

<div class="outer">
    <div class="header">Header content goes here</div>
    <div class="header-push">Header content goes here</div>
    <div class="content">
        ...
    </div>
</div>

【讨论】:

  • 这是一个不错的(如果有点老套)解决方案,但我简化了我的要求以使问题更容易回答。我实际上想要两个独立的列,所以我不能使用整页滚动来做到这一点。也许Javascript是唯一的方法。我希望一些新的表格布局可以解决问题,但我无法让它发挥作用。
  • 我已经尝试了几个小时来提出一个纯 CSS 解决方案,并得出结论,确实,这是不可能的。 96 年发明的标准的奇迹。
  • 这很棒。如果你不想让你的 HTML 变脏,你总是可以使用 JavaScript 来制作副本。
  • @WoodrowBarlow 这不会使网站无法使用。标题只会滚动,不会保持固定。
  • 不要忘记可访问性:如果您不能只在副本上设置 visibility: hidden,至少使用 aria-hidden="true" 以防止屏幕阅读器认为实际上有 2 个实例文本。
【解决方案3】:

我将接受的答案和 Eric 的答案结合起来。一个空的 div 用于将内容推送到“头部”下方。触发 window.onresize 时,此 div 的宽度由 jQuery 设置:

function resizeHeader() {
    $(".header-push").height($(".header").height());
}
$(document).ready(resizeHeader);
$(window).resize(resizeHeader);

请参阅this jsFiddle 了解更多信息。

【讨论】:

  • 奇怪的是,我最喜欢这种方法。它不需要重复的标头(但它确实需要一个空的 div,这对我来说不是),并且它不需要内容了解有关标头的任何信息。它也短得多。
  • 有助于在窗口调整大小期间添加一点延迟以避免太多触发器 - 我使用 250 毫秒,似乎足够好:stackoverflow.com/questions/2854407/…
  • 我花了很多时间才弄清楚纯 CSS 解决方案是不可能的。这确实可以解决问题,但是禁用 JS 的人呢(尽管我可以想象他们的浏览体验可能已经很糟糕了)?
  • CSS 非常复杂。对于这样的问题,必须存在干净的、纯 CSS 的解决方案。真正聪明和有 CSS 经验的人应该坐下来重新设计整个事情。应该可以做所有可以想象的简单的事情:创建一个固定高度的 div,一个适合其内容的 div,计算一个元素与另一个元素的真实像素距离,等等。意思是,像“min-height: 30rem”,那么显示的高度绝不应该是违反这个规则的东西,比如1rem,除非抛出错误。
  • 我们已经有了 flexbox,它可能很容易解决这个问题。见css-tricks.com/snippets/css/a-guide-to-flexbox。
【解决方案4】:

此 javascript 将采用固定标题的可变高度并将内容的上边距设置为在下方流动。只需调用页面加载。

<script type="text/javascript">
    function AdjustHeight() {
        var height = document.getElementById("fixedheader").offsetHeight;
        document.getElementById("content").style.marginTop = height + 'px';
    }    
</script>

【讨论】:

    【解决方案5】:

    这是 Shauna 上述解决方案的完整代码示例,适用于无法使其工作的懒惰/困惑/人。

    <html>
    <head>
    
    <style>
    #FreezePaneHeader {
        position: fixed; top:0; left: 0; width: 100%;background-color: gray;
    }
    
    #FreezePaneBody {
        margin-top: 30px;
    } 
    </style>
    
     <script type="text/javascript">        
            function resizeFreezePane()
            {
                var height = document.getElementById("FreezePaneHeader").offsetHeight;
                document.getElementById("FreezePaneBody").style.marginTop = height + 'px';
            }
    
            //Resizes content to allow static header with dynamic height on postbacks
            function pageLoad() {
                resizeFreezePane();
            }
    
            var addEvent = function (elem, type, eventHandle) {
                if (elem == null || typeof (elem) == 'undefined') return;
                if (elem.addEventListener) {
                    elem.addEventListener(type, eventHandle, false);
                } else if (elem.attachEvent) {
                    elem.attachEvent("on" + type, eventHandle);
                } else {
                    elem["on" + type] = eventHandle;
                }
            };
    
            //also when page is resized.
            addEvent(window, "resize", resizeFreezePane);
    
        function GenerateLorem(ele){
            var x = document.getElementById(ele);
            x.innerHTML = x.innerHTML + "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur pretium euismod leoquis convallis. In ornare suscipit massa eu commodo. Pellentesque vel nibh volutpat, commodo libero et, 
    
    porta tellus. Duis eu fringilla arcu. Etiam imperdiet lectus diam, dignissim viverra dui hendrerit id. Fusce condimentum bibendum tincidunt. Aenean fringilla felis elit, et dapibus ante tempus at. Phasellus quis dolor odio.</p>";
            resizeFreezePane();
            }
        </script>
    </head>
    
    <body>
    <div id="FreezePaneHeader">Frozen Page Header</div>
    <div id="FreezePaneBody">
    <button id="ButtonAddText" onclick="GenerateLorem('FreezePaneHeader'); return false;">Add more header text</button>
    <button id="ButtonAddText" onclick="GenerateLorem('FreezePaneBody'); return false;">Add more body text</button>
    <p id="PageContents"></p>
    </div>
    </body>
    
    </html>
    

    【讨论】:

      【解决方案6】:

      最简单的方法是简单地将position: fixed; 替换为position: sticky;

      header {
        position: sticky;
        top:0;
        background-color: red;
        color: #fff;
      }
      
      main {
        background-color: green;
        color: #fff;
        min-height: 150vh;
      }
      

      演示:https://jsfiddle.net/4zndve6p/

      【讨论】:

        【解决方案7】:

        我使用 getComputedStyle 解决了这个问题。 此方法允许您采用所有 CSS 样式。并基于它们,改变另一个元素的样式。 以下是使用原生 JS 的所有代码:

        <style>
        #head {
            position: fixed;
            width: 100%;
            top: 0;
            left: 0;
            background: rgb(170, 170, 170);
            /* height: 50px; for example no fixed height*/
            z-index: 2;
        }
        
        #content {
            position: relative;
            width: 100%;
            background: rgb(180, 37, 37);
          }
        
        <body>
        <div id="head">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Enim, quisquam.</div>
        <div id="content">
            Some content text<br />
        
        </div>
        <script>
            const header = document.querySelector('#head'),
                content = document.querySelector('#content');
            //Now get all possible CSS styles from #head using getComputedStyle
            const marginTopOffset = getComputedStyle(header);
        //Resize event is for autosearch width of a browser window
        window.addEventListener('resize', ()=> {
            function marginOffset() {
                content.style.marginTop = marginTopOffset.height;
                // you can add changes to another CSS style 
                // content.style.backgroundColor = marginTopOffset.backgroundColor;
            };
            marginOffset();
            // You can see how changes margin-top in console on the fly
            console.log(content);
        });
        </script>
        </body>
        

        【讨论】:

          【解决方案8】:

          这是我的简单有效的解决方案,只需四行代码。

          说明

          • getBoundingClientRect 计算元素的有效属性,包括边距。我用它来获得有效的底部值。
          • 此值分配给内容元素的 marginTop 属性。
          • 需要 onResize 的事件侦听器来响应窗口大小的变化,这会影响标题高度。

          看看它的工作原理

          我的小提琴(调整宽度看效果):https://jsfiddle.net/z1uac3Lw/

          function adjustHeaderHeight() {
             let header = document.getElementById('head');
             let rect = header.getBoundingClientRect();
             document.getElementById('content').style.marginTop = rect.bottom + 'px';
          }
          
          window.addEventListener('resize', function() {
             adjustHeaderHeight();
          });
          body {
              margin: 0;
          }
          
          #head {
              background: yellow;
          //    height: 20px; /* I can't rely on knowing this. */
          }
          
          #content {
              background: red;
              position: absolute;
              top: 0px;
              bottom: 0;
              width: 100%;
              overflow: auto;
          }
          <!DOCTYPE html>
          <html>
              <head>
              </head>
              <body onLoad='adjustHeaderHeight();' >
                  <div id="head">some variable height content ... with a very long long long long long long long long long long long long long long long long long long long long long line to show the effect</div>
                  <div id="content">
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                      scrollable content<br/>
                  </div>
              </body>
          </html>

          内嵌 javascript / CSS 的代码

          <!DOCTYPE html>
          <html>
              <head>
                  <style type="text/css">
          body {
              margin: 0;
          }
          
          #head {
             background: yellow;
          //    height: 20px; /* I can't rely on knowing this. */
          }
          
          #content {
             background: red;
             position: absolute;
             top: 0px;
             bottom: 0;
             width: 100%;
             overflow: auto;
          }
          
                  </style>
                  <script type="text/javascript" type="text/javascript">        
              
          function adjustHeaderHeight() {
             let header = document.getElementById('head');
             let rect = header.getBoundingClientRect();
             document.getElementById('content').style.marginTop = rect.bottom + 'px';
          }
          
          window.addEventListener('resize', function() {
             adjustHeaderHeight();
          });
          
                </script>        
                  
             </head>
             <body onLoad='adjustHeaderHeight();' >
                <div id="head">some variable height content ... with a very long long long long long long long long long long long long long long long long long long long long long line to show the effect</div>
                <div id="content">
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                   scrollable content<br/>
                </div>
             </body>
          </html>
          

          【讨论】:

            猜你喜欢
            • 2023-03-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-22
            • 1970-01-01
            • 2018-10-08
            • 1970-01-01
            • 2012-04-08
            相关资源
            最近更新 更多