CSS如何实现带有padding/margin的100%高度?

887

如何使用HTML/CSS制作一个元素,它的宽度和/或高度是其父元素的100%,并且仍然具有适当的填充或边距?

“适当”指的是如果我的父元素高度为200px,我指定height = 100%padding = 5px,那么我期望应该得到一个190px高的元素,四周有5px的边框,在父元素中心对齐。

现在,我知道这不是标准盒模型规定的工作方式(虽然我想知道为什么),因此显而易见的答案行不通:

#myDiv {
    width: 100%
    height: 100%;
    padding: 5px;
}

但是在我看来,必须有某种可靠的方法来实现父元素大小任意的这种效果。有没有人知道如何完成这个(似乎很简单的)任务?

哦,顺便说一下,我对IE兼容性不是特别感兴趣,所以这应该会使事情变得更容易一些。

编辑:由于被要求提供示例,这是我能想到的最简单的一个:

<html style="height: 100%">
    <body style="height: 100%">
        <div style="background-color: black; height: 100%; padding: 25px"></div>
    </body>
</html>

挑战在于使黑盒子在所有边缘都有25像素的填充,而页面不会因此变得足够大以需要滚动条。


我发现这两个解决方案最可靠:http://www.xs4all.nl/~peterned/examples/csslayout1.html http://themaninblue.com/experiment/footerStickAlt/ 你有任何特定的HTML代码可以让我们查看和操作吗? - Nick Presta
https://dev59.com/Zm865IYBdhLWcg3wNLw7 - Ben
15个回答

790

我是通过阅读《PRO HTML and CSS Design Patterns》学会了如何做这些事情。对于 div 元素来说,display:block 是默认的显示值,但我喜欢明确表示出来。容器必须是正确的类型;position 属性是 fixedrelative 或者 absolute

.stretchedToMargin {
  display: block;
  position:absolute;
  height:auto;
  bottom:0;
  top:0;
  left:0;
  right:0;
  margin-top:20px;
  margin-bottom:20px;
  margin-right:80px;
  margin-left:80px;
  background-color: green;
}
<div class="stretchedToMargin">
  Hello, world
</div>

Nooshu的讨论中提供了一个Fiddle演示


43
非常棒的解决方案,我会将其加入书签。我已经快速地将它添加到http://jsfiddle.net/Rpdr9/,供任何想要查看演示的人使用。希望你不介意。 - Nooshu
17
虽然@Toji不关心IE兼容性,但很遗憾,我必须要考虑。这个解决方案在IE6下起初并没有奏效。将Dean Edwards的IE9.js添加到页面后,解决方案才开始正常工作。现在我只能希望相对/绝对定位不会对子元素造成影响... - Christopher Parker
26
尽管看起来我在这里是少数派:P。这假设该框可以绝对定位;人们已经过度使用pos:abs了,他们不需要这种方法。以一个div“panels”为例,其中包含多个class为“panel”的div。“panels”具有{overflow:hidden; height:300px;},而“panel”具有不同的内容/内容高度,且具有{border:#000 solid 1px; float:left; margin-right:10px;}。使所有“panel”的高度与“panels”相同,而不会在任何时候失去边框。在这里,“panel” divs不能被pos:abs'd。但@Marco的解决方案适用于此场景。 - eternicode
8
哦,我明白了。top:0, bottom:0 实际上是将元素“拉伸”到最大。不过我只能使用 position:absolute 才能实现它的效果。 - Matt
8
你能不能只使用top:20px;bottom:20px;left:20px;right:20px;,而不用margin属性呢? - chowey
显示剩余14条评论

448

在CSS3中,有一个新属性叫做box-sizing,可以改变盒模型计算宽度/高度的方式。

将此属性设置为"value=border-box",应用于任何元素,都不会在添加padding或border时拉伸元素。如果您定义了100px宽度和10px padding的元素,它仍然是100px宽。

box-sizing: border-box;

这里查看浏览器支持情况。但它不支持IE7及更低版本,然而我相信使用 Dean Edward's 的 IE7.js 可以添加支持。享受吧 :)


51
终于!我已经等了大约十年,期盼这个功能。可惜IE7不支持它,但我总觉得那些还在使用IE的人不配拥有漂亮的布局。 - cronoklee
19
这基本上与IE的怪异模式盒模型相同。我觉得很有趣,每个人都讨厌IE,但现在border-box是每个人的英雄 :) - Matt Greer
14
FYI,现在除了-moz以外,box-sizing的浏览器前缀已经被取消。请参考http://paulirish.com/2012/box-sizing-border-box-ftw/和评论进行深入讨论。 - aponzani
8
一个细微的点(关于早期回答)。 这适用于填充,但不适用于边距。 边距在边框外面。 对我仍然非常有用。 谢谢! - rob
3
如果您不需要边距的话,这将非常棒。 - Lisa
显示剩余4条评论

72
解决方法是完全不使用height和width!使用top、left、right、bottom固定内部框,并添加margin。
.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
  <div class="box" style="background:green">
    <div class="box" style="background:lightblue">
      This will show three nested boxes. Try resizing browser to see they remain nested properly.
    </div>
  </div>
</div>


6
点赞因为你在技术上是正确的,但其实这跟Frank的答案基本上是一样的(我认为他的回答对于那些比较粗心的浏览者更友好一些)。 - Toji
@Toji 但是这个答案更简洁,而且更贴近问题的示例(它具有嵌套元素,在这里非常重要)。 - personal_cloud

53

更好的方法是使用 calc() 属性。因此,您的情况将如下所示:

#myDiv {
    width: calc(100% - 10px);
    height: calc(100% - 10px);
    padding: 5px;
}

简单、干净、无需变通。只需确保不要忘记值和操作符之间的空格(例如(100%-5px)这将破坏语法)。享受吧!


6
好的解决方案。只需记得检查浏览器支持情况: Can I use calc() - Brett Postin
8
这样做实际上会给你100%的宽度和高度,再加上5像素的内边距,因为内边距会将元素的宽度和高度分别增加10像素。 - user3476725
终于找到了一个好的解决方案,不像其他的那样你把上、右、下和左都设为0,那只适用于position:absolute;。 - Gil Epshtain
3
我认为正确的写法是:#myDiv { 宽度:calc(100%-10px); 高度:calc(100%-10px); 内边距:5px; }左右各5像素=10, 上下各5像素=10。 - Chris P

21
根据w3c规范,height指的是可视区域的高度,例如在1280x1024像素分辨率的显示器上,100% height = 1024像素。 min-height指的是包括内容在内的页面总高度,因此在内容大于1024px的页面上,min-height:100%将会拉伸以包含所有内容。 然后,另一个问题是,在大多数现代浏览器中,padding和border都会被添加到高度和宽度中,除了ie6(ie6实际上相当合理,但不符合规范)。这被称为盒模型。所以如果你指定了...
min-height: 100%;
padding: 5px; 

实际上它会给你高度100% + 5px + 5px。要解决这个问题,你需要一个包装容器。

<style>
    .FullHeight { 
       height: auto !important; /* ie 6 will ignore this */
       height: 100%;            /* ie 6 will use this instead of min-height */
       min-height: 100%;        /* ie 6 will ignore this */
    }

    .Padded {
       padding: 5px;
    }
</style>

<div class="FullHeight">
   <div class="Padded">
      Hello i am padded.
   </div
</div>

4
@Alex: 但是是什么让内部div(Padded的那个)高度为外部div的100%呢?我的经验是你只会得到一个比外部div稍短的小div。 - Lawrence Dol

9

1. 使用 padding 实现全高度

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  padding: 50px;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

2. 使用 margin 实现全屏高度

body {
  margin: 0;
}
.container {
  min-height: calc(100vh - 100px);
  margin: 50px;
  background: silver;
}
<div class="container">Hello world.</div>

3. 带有 border 的完整高度

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  border: 50px solid pink;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>


7
这是CSS中最愚蠢的之一 - 我还没有理解其中的原因(如果有人知道,请解释一下)。
100%意味着容器高度的100% - 加上任何边距,边框和内边距。因此,几乎不可能获得一个填充其父容器并具有边距,边框或内边距的容器。
另外,请注意,设置高度在浏览器之间存在严重的不一致性。
我自从发布这篇文章以来学到的另一件事是,百分比相对于容器的长度,也就是它的宽度,使百分比对于高度更加无用。
如今,vh和vw视口单位更有用,但仍然对除顶层容器以外的其他内容不太有用。

没有推理,只有浏览器开始趋向一致行为的发生。请查看我回答中提到的书籍。 - Frank Schwieterman
点赞,因为使用了正确的术语。Tex 和我看过的所有布局管理器都做得很好,只有 CSS 可能比较特殊。 - maaartinus

5
另一个解决方案是使用具有不同盒模型行为的 display:table。您可以设置父级的高度和宽度,并添加填充而不扩展它。子元素具有除填充之外的100%高度和宽度。JSBIN。另一个选项是使用 box-sizing 属性。两种方法的唯一问题是在 IE7 中无法使用。

4

使用flexbox的解决方案(在IE11上工作):(或在jsfiddle上查看

<html>
  <style>
    html, body {
      height: 100%; /* fix for IE11, not needed for chrome/ff */
      margin: 0; /* CSS-reset for chrome */
    }
  </style>
  <body style="display: flex;">
    <div style="background-color: black; flex: 1; margin: 25px;"></div>
  </body>
</html>

CSS-reset 不一定对实际问题很重要。)
重要的部分是 flex: 1 (与父元素的 display: flex 结合使用)。有趣的是,我知道 Flex 属性如何工作的最可信解释来自于 react-native 的文档,因此我仍然参考它:

(...) flex: 1,告诉组件填充所有可用空间,并与具有相同父级的其他组件共享。


4
另一种解决方案:您可以使用百分比单位来设置边距和尺寸。例如:
.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

主要问题在于边距会随着父元素的大小而略微增加/减少。假设您希望的功能是边距保持恒定,子元素随着间距的变化而增长/缩小。因此,根据您需要显示的紧密程度,可能存在问题。(我还建议使用更小的边距,例如0.3%)。

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