By Toji


2009-01-27 23:28:18 8 Comments

With HTML/CSS, how can I make an element that has a width and/or height that is 100% of it's parent element and still has proper padding or margins?

By "proper" I mean that if my parent element is 200px tall and I specify height = 100% with padding = 5px I would expect that I should get a 190px high element with border = 5px on all sides, nicely centered in the parent element.

Now, I know that that's not how the standard box model specifies it should work (although I'd like to know why, exactly...), so the obvious answer doesn't work:

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

But it would seem to me that there must be SOME way of reliably producing this effect for a parent of arbitrary size. Does anyone know of a way of accomplishing this (seemingly simple) task?

Oh, and for the record I'm not terribly interested in IE compatibility so that should (hopefully) make things a bit easier.

EDIT: Since an example was asked for, here's the simplest one I can think of:

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

The challenge is then to get the black box to show up with a 25 pixel padding on all edges without the page growing big enough to require scrollbars.

13 comments

@Putzi San 2018-06-28 12:36:56

A solution with flexbox (working on IE11): (or view on 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>

(The CSS-reset is not necessarily important for the actual problem.)

The important part is flex: 1 (In combination with display: flex at the parent). Funnily enough, the most plausible explanation I know for how the Flex property works comes from a react-native documentation, so I refer to it anyway:

(...) flex: 1, which tells a component to fill all available space, shared evenly amongst other components with the same parent

@Marco Jardim 2010-06-14 14:10:08

There is a new property in CSS3 that you can use to change the way the box model calculates width/height, it's called box-sizing.

By setting this property with the value "border-box" it makes whichever element you apply it to not stretch when you add a padding or border. If you define something with 100px width, and 10px padding, it will still be 100px wide.

box-sizing: border-box;

See here for browser support. It does not work for IE7 and lower, however, I believe that Dean Edward's IE7.js adds support for it. Enjoy :)

@cronoklee 2012-01-16 11:14:11

Finally! I've been waiting for this exact feature for about 10 years now. Pity IE7 doesnt support it but I always think people who are still using IE dont deserve a beautiful layout.

@Spud 2012-03-26 07:03:23

This worked on iPhone/Safari and Android's default browser for me whereas the absolutely positioned solution above did not work.

@Matt Greer 2012-04-13 02:58:28

This is basically the same as IE's quirks mode box model. I find it funny how everyone hates on IE yet now border-box is everyone's hero :)

@aurora 2012-05-02 19:54:32

but ... quirks mode was the only good about IE ;-) ... thanks for posting this solution, this is EXACTLY, what i was looking for.

@aponzani 2012-08-02 20:06:58

FYI, the browser prefix for box-sizing is now dropped for all but -moz. See paulirish.com/2012/box-sizing-border-box-ftw and the comments for a good discussion

@Andrew Mao 2013-07-05 21:39:32

Yes! This is the right answer! 100% height now scales things correctly relative to their parents, without spilling over. Would give a million +1's if I could.

@rob 2015-10-28 03:43:02

Very minor point (to an older answer). This works with padding, but not margins. Margins are outside the border. Still very useful to me. Thanks!

@Charlie 2017-03-27 21:08:06

this is supported by all major browsers, without the prefixes: caniuse.com/#feat=css3-boxsizing

@Lawrence Dol 2009-01-27 23:33:16

This is one of the outright idiocies of CSS - I have yet to understand the reasoning (if someone knows, pls. explain).

100% means 100% of the container height - to which any margins, borders and padding are added. So it is effectively impossible to get a container which fills it's parent and which has a margin, border, or padding.

Note also, setting height is notoriously inconsistent between browsers, too.


Another thing I've learned since I posted this is that the percentage is relative the container's length, that is, it's width, making a percentage even more worthless for height.

Nowadays, the vh and vw viewport units are more useful, but still not especially useful for anything other than the top-level containers.

@Frank Schwieterman 2009-01-27 23:55:40

There is no reasoning, just what happened where browsers started to converge towards consistent behavior. Check out the book mentioned in my response.

@maaartinus 2018-07-18 16:03:06

Upvoted for using the right term. Tex and any layout manager I've seen got it right, just CSS must be special.

@Kris Randall 2017-12-18 03:19:13

Border around div, rather than page body margin

Another solution - I just wanted a simple border around the edge of my page, and I wanted 100% height when the content was smaller than that.

Border-box didn't work, and the fixed positioning seemed wrong for such a simple need.

I ended up adding a border to my container, instead of relying on the margin of the body of the page - it looks like this :

body, html {
    height: 100%;
    margin: 0;
}

.container {
    width: 100%;
    min-height: 100%;
    border: 8px solid #564333;
}

@Stickers 2017-01-15 20:30:45

1. Full height with padding

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

2. Full height with margin

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

3. Full height with border

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

@amolk 2010-04-09 20:03:17

The solution is to NOT use height and width at all! Attach the inner box using top, left, right, bottom and then add 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>

@Toji 2010-04-10 01:03:42

Up-vote because you're technically correct, but it's also basically the same answer as Frank's (Which I think is a bit more friendly to the sloppier browsers out there.)

@Frank Schwieterman 2009-01-27 23:53:17

I learned how to do these sort of things reading "PRO HTML and CSS Design Patterns". The display:block is the default display value for the div, but I like to make it explicit. The container has to be the right type; position attribute is fixed, relative, or 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>

Fiddle by Nooshu's comment

@Toji 2009-01-28 00:02:18

Wow... that's a lot of CSS to go through but it appears to work! This may be what I was looking for. Let me play around with it in a few more scenarios before I mark this as accepted.

@Frank Schwieterman 2009-01-28 00:07:28

If you have more questions, like how to get it to work in a particular context, let me know. Note that the horizontal related elements and the vertical related elements can be used independently, so long as the display is block and position is fixed, absolute or relative.

@Toji 2009-01-28 00:10:41

Just tried it in the context that I'll be using it and it works like a charm. Still blown away that it takes that much code to do something that really ought to be two lines, but if it works I'll take it! Thanks!

@Nooshu 2010-03-04 14:08:30

Superb solution, will be bookmarking this one. Just quickly added it to jsfiddle.net/Rpdr9 for anyone who wants a live demo. Hope you don't mind.

@Frank Schwieterman 2010-03-04 18:38:57

Hmm actually I've come to prefer the book "CSS Mastery" by Andy Budd. Both are worth reading though. The patterns book has great information but the format is a pain. CSS Mastery is the only reference I've found that shows how to seal of a region containing floats though. Maybe its good to read both.

@Christopher Parker 2010-05-19 18:34:33

While @Toji didn't care about IE compatibility, I unfortunately have to. This solution didn't initially work under IE6. Adding Dean Edwards' IE9.js to the page made this work. Now I just have to hope and pray that the relative/absolute positioning doesn't screw with something in a child element...

@eternicode 2011-06-03 01:50:49

-1 (though it looks like I'm a minority here :P ). This assumes that the box can be absolutely-positioned; people already overuse pos:abs as it is, they don't need this ammo. Take this example: a div "panels" with multiple divs of class "panel" inside it. "panels" has {overflow:hidden; height:300px;}, and "panel" have varying contents/content-height, with {border:#000 solid 1px; float:left; margin-right:10px;}. Make all "panel" the height of "panels" without losing borders at any point. The "panel" divs cannot be pos:abs'd here. @Marco's solution works for this scenario, though.

@stevendesu 2011-08-05 00:58:05

I seem to have a unique issue. While this works for stretching a <div> to the size of a page with margins, it fails with padding. I wanted to have emulate frames by having a <div> along the left side that stretched to fill the page and had a border-right and a padding. Once the padding is applied it again stretches beyond the page, despite the top:0; bottom:0; rules.

@Matt 2011-09-12 08:42:41

Oh wow, I get it. The top:0, bottom:0, essentially "stretch" out the element. I can only get it to work with position:absolute though

@Primus202 2011-10-11 20:50:06

I too can only get it to function when absolutely positioned but doing so messes up my float based layout. Is there a way to get full width/height divs including margins/paddings using floats?

@Frank Schwieterman 2011-11-10 06:47:09

Primus you'd need to provide examples about what is floating. For the div in the example and its container, float is not an option. If something outside or inside is floating, you may need to seal it off. One way to seal float behavior is to wrap it in something with overflow:hidden or overflow:auto.

@Saul 2012-06-20 09:07:15

This breaks when content in .stretchedToMargin spans over height of 100%.

@Frank Schwieterman 2012-06-23 19:50:15

When the content is longer, I do see it rendered beyond the bottom of the div. What would you prefer it to do? Consider adding overflow:scroll or overflow:hidden.

@chowey 2013-03-13 01:50:11

Couldn't you just do top:20px;bottom:20px;left:20px;right:20px; instead of using margins at all?

@Artur Bodera 2013-06-14 09:23:28

Warning! This will not work with SVG. Tested on Chrome/webkit: jsfiddle.net/Thinkscape/UTMcn

@VIK 2013-10-29 22:14:50

Unfortunately this solution does not work with <textarea> in most browsers. Only Chrome is good with it.

@karmasponge 2015-09-17 04:03:32

The '.stretchedToMargin' does not work with 'button' tags in Chrome v45 or Firefox v40. The button width does not stretch. jsfiddle.net/Rpdr9/2258

@user1721135 2012-11-30 14:35:08

Another solution is to use display:table which has a different box model behaviour.

You can set a height and width to the parent and add padding without expanding it. The child has 100% height and width minus the paddings.

JSBIN

Another option would be to use box-sizing propperty. Only problem with both would be they dont work in IE7.

@Peter Tseng 2012-02-08 07:37:49

Frank's example confused me a bit - it didn't work in my case because I didn't understand positioning well enough yet. It's important to note that the parent container element needs to have a non-static position (he mentioned this but I overlooked it, and it wasn't in his example).

Here's an example where the child - given padding and a border - uses absolute positioning to fill the parent 100%. The parent uses relative positioning in order to provide a point of reference for the child's position while remaining in the normal flow - the next element "more-content" is not affected:

#box {
    position: relative;
    height: 300px;
    width: 600px;
}

#box p {
    position: absolute;
    border-style: dashed;
    padding: 1em;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
<div id="box">
  <p>100% height and width!</p>
</div>
<div id="more-content">
</div>

A useful link for quickly learning CSS positioning

@ktbiz 2013-10-29 19:12:38

Another solution: You can use percentage units for margins as well as sizes. For example:

.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

The main issue here is that the margins will increase/decrease slightly with the size of the parent element. Presumably the functionality you would prefer is for the margins to stay constant and the child element to grow/shrink to fill changes in spacing. So, depending on how tight you need your display to be, that could be problematic. (I'd also go for a smaller margin, like 0.3%).

@Brian Aderer 2013-06-15 17:34:43

The better way is with the calc() property. So your case would look like:

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

Simple, clean, no workarounds. Just make sure you don't forget the space between the values and the operator (eg (100%-5px) that will break the syntax. Enjoy!

@Brett Postin 2013-06-17 08:12:08

Nice solution. Just remember to check browser support: Can I use calc()

@user3476725 2014-11-01 15:50:41

Wouldn't this actually give you 100% width and height each PLUS 5px padding, since the padding would effectively make the element 10px wider and larger, respectively?

@Gil Epshtain 2018-01-20 17:57:32

Finally a good solution, and not like the rest of them there you pot the top, right, bottom and left to be 0, that will work only with position: absolute;

@Chris P 2019-03-15 09:10:27

I think the correct is: #myDiv { width: calc(100% - 10px); height: calc(100% - 10px); padding: 5px; } 5 from left and 5 from right = 10, 5 from top and 5 from bottom = 10

@Mujassir Nasir 2012-01-20 13:10:13

  <style type="text/css">
.stretchedToMargin {
    position:absolute;
    width:100%;
    height:100%;

}
</style>

@Alex 2009-01-27 23:45:00

According the the w3c spec height refers to the height of the viewable area e.g. on a 1280x1024 pixel resolution monitor 100% height = 1024 pixels.

min-height refers to the total height of the page including content so on a page where the content is bigger than 1024px min-height:100% will stretch to include all of the content.

The other problem then is that padding and border are added to the height and width in most modern browsers except ie6(ie6 is actually quite logical but does not conform to the spec). This is called the box model. So if you specify

min-height: 100%;
padding: 5px; 

It will actually give you 100% + 5px + 5px for the height. To get around this you need a wrapper container.

<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>

@Lawrence Dol 2009-01-28 03:19:16

@Alex: But what makes the inner div (the Padded one) 100% of the outer div's height. My experience has been that you just get a little short div inside a larger full-height div.

Related Questions

Sponsored Content

32 Answered Questions

[SOLVED] How to make a div 100% height of the browser window

  • 2009-10-15 21:18:43
  • mike
  • 1869756 View
  • 2022 Score
  • 32 Answer
  • Tags:   html css height

47 Answered Questions

[SOLVED] How can I transition height: 0; to height: auto; using CSS?

  • 2010-08-18 02:50:35
  • Hailwood
  • 955687 View
  • 1990 Score
  • 47 Answer
  • Tags:   css css-transitions

27 Answered Questions

[SOLVED] Set cellpadding and cellspacing in CSS?

28 Answered Questions

[SOLVED] How do I give text or an image a transparent background using CSS?

  • 2009-04-30 09:00:02
  • Stijn Sanders
  • 1513078 View
  • 2216 Score
  • 28 Answer
  • Tags:   html css opacity

35 Answered Questions

[SOLVED] Change an HTML5 input's placeholder color with CSS

19 Answered Questions

[SOLVED] Is it possible to apply CSS to half of a character?

31 Answered Questions

[SOLVED] Is there a CSS parent selector?

  • 2009-06-18 19:59:36
  • jcuenod
  • 1856805 View
  • 2991 Score
  • 31 Answer
  • Tags:   css css-selectors

31 Answered Questions

[SOLVED] Make a div fill the height of the remaining screen space

  • 2008-09-18 05:06:17
  • Vincent McNabb
  • 915842 View
  • 1747 Score
  • 31 Answer
  • Tags:   html css html-table

Sponsored Content