71

I want to display an expandable div (width: 100%) with margins...

#page {
  background: red;
  float: left;
  width: 100%;
  height: 300px;
}

#margin {
  background: green;
  float: left;
  width: 100%;
  height: 300px;
  margin: 10px;
}
<div id="page">
  <div id="margin">
    "some content here"
  </div>
</div>
doğukan
  • 23,073
  • 13
  • 57
  • 69
Random78952
  • 1,520
  • 4
  • 26
  • 36

6 Answers6

99

You can use calc() css function (browser support).

#page {
  background: red;
  float: left;
  width: 100%;
  height: 300px;
}

#margin {
  background: green;
  float: left;
  width: calc(100% - 10px);
  height: 300px;
  margin: 10px;
}​

Alternatively, try using padding instead of margin and box-sizing: border-box (browser support):

#page {
    background: red;
    width: 100%;
    height: 300px;
    padding: 10px;
}

#margin {
    box-sizing: border-box;
    background: green;
    width: 100%;
    height: 300px;
}
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Vukašin Manojlović
  • 2,645
  • 2
  • 21
  • 26
  • 2
    The best solution is to use `calc()` in modern browsers, and JS code + Modernizr for older browser which doesn't support `calc()`. – Vukašin Manojlović Nov 10 '12 at 14:27
  • Css function ? thats sound great... but i use chrome and chrome tell me "invalid property value"... but why ? – Random78952 Nov 10 '12 at 14:32
  • 4
    You have to use `calc(100% - 10px)` (space between number and minus). Also for chrome and safari use `-webkit` prefix, `-moz` for FF and `-o` for Opera! – Vukašin Manojlović Nov 10 '12 at 14:39
  • If you want to be cross-browser compatible, this probably is not the best approach. Since often users don't have to latest and greatest browser... – Andy Nov 10 '12 at 15:00
  • 5
    Why isn't this `calc(100% - 20px)`? `10px` would only be one side of the margin and would only reduce the width by half the required distance to fit. Unless I'm missing something. – Mark Carpenter Jr Feb 09 '18 at 19:29
  • There is a new CSS value for `width` that can allow you to automatically use a full width including margins. It looks like `width: stretch` but it's still prefixed in most browsers. In Chrome (et al) it's `-webkit-fill-available`, in Firefox it's `-moz-available`. [caniuse link](https://caniuse.com/#feat=intrinsic-width) – forresthopkinsa Jun 23 '20 at 23:03
18

Sometimes it's better to do the opposite and give the parent div padding instead:

LIVE DEMO

What I did was change the CSS of #page to:

#page {
    padding: 3%;
    width: 94%; /* 94% + 3% +3% = 100% */

    /* keep the rest of your css */
    /* ... */
}

Then delete the margin from #margin

Note: this also adds 3% to the top and bottom (so 6% to the height) which makes it a little taller than 300px - so if you need exactly 300px, you could do something like padding:10px 3%; and change the height:280px; to add up to 300px again.

Vukašin Manojlović
  • 2,645
  • 2
  • 21
  • 26
Andy
  • 1,123
  • 6
  • 9
  • 1
    This is the right approach for doing calculations with CSS for now. This illustrates the basic principle that you end up with a `div` structure that mimic the parse tree of the expression you want to evaluate. – eh9 Nov 10 '12 at 14:27
12

You can use the following CSS to achieve the desired result:

#page {
   background: red;
   overflow: auto;
}

#margin {
   background: green;
   height: 280px;
   margin: 10px
}
Vukašin Manojlović
  • 2,645
  • 2
  • 21
  • 26
Daniel Calliess
  • 861
  • 6
  • 12
  • 8
    Completely removing the width doesn't seem like the appropriate way to solve the problem of combining margin and width functionality. – user3750325 Nov 30 '17 at 20:10
11

The correct way to achieve this by standard is:

#margin {
   background: green;
   height: 280px;
   margin: 10px;
   width: auto;
   display: block;
}
Tolly
  • 115
  • 1
  • 3
  • +1 As `width: auto` worked like a charm compared to `width: 100%`. Having googled the difference I'm not sure why anybody would use 100%. If they know what they're doing. Which I certainly don't. – Josh Jun 08 '18 at 16:41
  • There is no "correct" way, and this question goes beyond elements which are `display:block` by default (like tables for example), therefor this solution is lacking. – vsync Aug 15 '18 at 12:21
  • This does seem like the best solution, when it's available. – cammil Mar 02 '20 at 16:53
  • Well, `width: auto;` is the default value for that property. So adding it is redundant, in my opinion. Not that the answer is not right, just don't add css for a property if you're going to set it to its default value. – 10110 Jun 09 '22 at 00:31
4

For LESS users only:

Using the nice solution of Vukašin Manojlović doesn't work out of the box because LESS executes + or - operations during the LESS compilation. One solution is to escape LESS so that it doesn't execute the operation.

Disable LESS-CSS Overwriting calc()

@someMarginVariable = 15px;

margin: @someMarginVariable;
width: calc(~"100% - "@someMarginVariable*2);
width: -moz-calc(~"100% - "@someMarginVariable*2);
width: -webkit-calc(~"100% - "@someMarginVariable*2);
width: -o-calc(~"100% - "@someMarginVariable*2);

or can use a mixin like:

.fullWidthMinusMarginPaddingMixin(@marginSize,@paddingSize) {
  @minusValue: (@marginSize+@paddingSize)*2;
  padding: @paddingSize;
  margin: @marginSize;
  width: calc(~"100% - "@minusValue);
  width: -moz-calc(~"100% - "@minusValue);
  width: -webkit-calc(~"100% - "@minusValue);
  width: -o-calc(~"100% - "@minusValue);
}
Community
  • 1
  • 1
Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419
0

If possible, try to use padding with box-sizing instead, on #page element

#page {
    padding: 10px;
    box-sizing: border-box;
    background: red;
    float: left;
    width: 100%;
    height: 300px;
}
#margin {
    background: green;
    float: left;
    width: 100%;
    height: 100%;
}
  • You've replaced margin on the inner element with padding on the outer element, so of course it works. But the question is about how to combine `width 100%` with `margin`. Simply adding `border-box` does not solve the problem. – personal_cloud Dec 11 '22 at 23:35