
本文旨在解决如何使用纯css创建一个可滚动的覆盖层,该覆盖层位于页面固定头部和动态高度的底部之间,且不与头部和底部重叠。我们将利用`calc()`函数和相对定位,根据视口高度、头部高度和底部高度动态计算覆盖层的最大高度,实现预期的布局效果。
实现原理
核心思想是利用CSS的calc()函数动态计算覆盖层的最大高度。具体来说,覆盖层的最大高度等于视口高度减去头部高度和底部高度。为了确保覆盖层位于底部之内,我们将使用position: relative和bottom: calc(100%)将覆盖层相对于底部定位。
具体步骤
-
html结构:
<div class="wrapper"> <div class="header">Header</div> <div class="content"> Long middle content..... </div> </div> <div class="footer"> Footer <a href="#" id="button">Click me</a> <div class="footer-wrapper"> <div id="footer-content">Start of footer content Long footer content.... </div> </div> </div>
保持与原HTML结构一致,wrapper包含header, content, footer,footer内部包含footer-wrapper,footer-wrapper内部包含footer-content。
-
html, body { height: 100%; margin: 0; } .wrapper { height: 100%; display: flex; flex-direction: column; max-height: calc(100vh - 1.5rem); } .header, .footer { padding: 10px; background: silver; } .header { margin-top: 20px; } .content { overflow-y: auto; min-height: 2.5rem; padding: 2.5rem; flex-grow: 1; position: relative; background: pink; } #footer-content { display: none; background: white; padding: 10px; overflow-y: auto; position: absolute; bottom: calc(100%); /* 将footer-content的底部放置在footer的顶部 */ max-height:calc(100vh - 100% - 58px); /* 视口高度 - footer高度 - header高度 */ width: 100%; /* 确保宽度与footer一致 */ } .footer-wrapper { position: relative; /* 相对于footer定位 */ } .footer { position: relative; }关键在于#footer-content的样式:
- position: absolute;:使其可以相对于父元素(.footer-wrapper)进行定位。
- bottom: calc(100%);:将覆盖层的底部与底部的顶部对齐,利用了底部的高度作为计算的基准。
- max-height:calc(100vh – 100% – 58px);:计算覆盖层的最大高度,100vh是视口高度,100%是底部的高度,58px是头部的高度(包含margin-top)。
- overflow-y: auto;:允许内容滚动。
- width: 100%;: 确保宽度与footer一致。 .footer-wrapper的position: relative;是使#footer-content可以相对于它进行绝对定位的关键。
-
$(document).ready(function(){ $('#button').click( function(e) { e.preventDefault(); // stops link from making page jump to the top e.stopPropagation(); // when you click the button, it stops the page from seeing it as clicking the body too $('#footer-content').toggle(); }); $('#footer-content').click( function(e) { e.stopPropagation(); // when you click within the content area, it stops the page from seeing it as clicking the body too }); });这段javascript代码负责切换覆盖层的显示和隐藏,以及阻止事件冒泡。
完整示例
<!DOCTYPE html> <html> <head> <style> body { height: 600px; } #content { background: salmon; display: none; height: 300px; width: 100%; } html, body { height: 100%; margin: 0; } .wrapper { height: 100%; display: flex; flex-direction: column; max-height: calc(100vh - 1.5rem); } .header, .footer { padding: 10px; background: silver; } .header { margin-top: 20px; } .content { overflow-y: auto; min-height: 2.5rem; padding: 2.5rem; flex-grow: 1; position: relative; background: pink; } #footer-content { display: none; background: white; padding: 10px; overflow-y: auto; position: absolute; bottom: calc(100%); /* 将footer-content的底部放置在footer的顶部 */ max-height:calc(100vh - 100% - 58px); /* 视口高度 - footer高度 - header高度 */ width: 100%; /* 确保宽度与footer一致 */ } .footer-wrapper { position: relative; /* 相对于footer定位 */ } .footer { position: relative; } </style> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script> $(document).ready(function(){ $('#button').click( function(e) { e.preventDefault(); // stops link from making page jump to the top e.stopPropagation(); // when you click the button, it stops the page from seeing it as clicking the body too $('#footer-content').toggle(); }); $('#footer-content').click( function(e) { e.stopPropagation(); // when you click within the content area, it stops the page from seeing it as clicking the body too }); }); </script> </head> <body> <div class="wrapper"> <div class="header">Header</div> <div class="content"> Long middle content..... </div> </div> <div class="footer"> Footer <a href="#" id="button">Click me</a> <div class="footer-wrapper"> <div id="footer-content">Start of footer content Long footer content.... </div> </div> </div> </body> </html>
注意事项
- 确保引入jQuery库,以便使用JavaScript代码。
- 头部高度和底部高度的计算需要根据实际情况进行调整。
- 如果底部高度是动态变化的,则需要考虑使用JavaScript来动态更新覆盖层的最大高度。
总结
通过结合CSS的calc()函数和相对定位,我们可以创建一个可滚动且位于固定头部和动态底部之间的覆盖层,而无需使用JavaScript来动态计算高度。这种方法简单有效,适用于各种需要类似布局的场景。


