156

Why don't we have box-sizing: margin-box;? Usually when we put box-sizing: border-box; in our style sheets we really mean the former.


Example:

Let's say I have a 2 column page layout. Both columns have a width of 50%, but they look kind of ugly because there's no gutter (gap in the middle); Below is the CSS:

.col2 {
    width: 50%;
    float: left;
}


To apply a gutter you might think we could just set a right margin on the first of the 2 columns; something like this:

.col2:first-child {
    margin-right: 24px;
}

But this would make the second column wrap onto a new line, because the following is true:

50% + 50% + 24px > 100%

box-sizing: margin-box; would solve this issue by including margin in the calculated width of the element. I would find this very useful if not more useful than box-sizing: border-box;.

peterh
  • 11,875
  • 18
  • 85
  • 108
Web_Designer
  • 72,308
  • 93
  • 206
  • 262
  • 30
    "Why don't we have `box-sizing: margin-box;`?" Because while horizontal margins don't collapse, such a proposition would seriously interfere with vertical margin collapse. Anyway, if you want to propose something for standardization, Stack Overflow is not the right place. Try the mailing lists. – BoltClock May 30 '12 at 00:30
  • 17
    In certain situations, you can get around this by using `border: xxx solid transparent;`, since the border is included in `border-box`. This will break some other things though, such as `box-shadow`. – Nathan Osman Apr 15 '13 at 23:56
  • 35
    Are we closing all questions about standards as "non-constructive" now?? It's a fair question to ask, and it even has a straightforward answer: we don't have `box-sizing: margin-box` because it wouldn't work with margin-collapsing. – thomasrutter Sep 26 '13 at 06:36
  • @thomasrutter: There wasn't a better-worded reason for it at the time I closed it, which was more than a year ago. Anyway, "not constructive" is gone now (meaning no, we don't actually close anything as non-constructive anymore), and since the whole "I have an idea, here's how it works, let's make this a standard!" thing has been removed since it was last closed it now actually sounds like a practical "why can't X work?" question. It's still an incredibly speculative question (my reasoning above is really nothing more than an educated guess), but I shan't comment further on that. – BoltClock Oct 04 '13 at 11:47
  • why not just have an inner-wrap/div if you want spacing: http://codepen.io/chriscoyier/pen/eGcLw – ashley Oct 04 '13 at 11:58
  • Or use % margins? E.g. 49% + 2% + 49% – sam Oct 10 '13 at 01:09
  • This question appears to be off-topic because it is about revising web standards, instead of troubleshooting a specific problem. – Jeff Oct 29 '13 at 15:41
  • percent widths and floats are a giant hack anyway and certainly not what margins are intended for. as with many things, this is [solved by flexbox](http://philipwalton.github.io/solved-by-flexbox/) :) – Eevee Nov 05 '13 at 07:57
  • What you should do is put your HTML for each column in a
    and put margins on the section: #??? { margin: 10px 10px 10px 10px; }
    –  Nov 19 '13 at 22:56
  • This is not a question, it's a proposal. – noah Nov 20 '13 at 14:43
  • This is solved by multiple CSS techs that have little support, so far. Like calc, flexbox, and css columns (column-count, column-width, column-gap). A better idea might be to take out your static margin and replace it with a percent... – philwills Nov 21 '13 at 01:41
  • I totally agree with @BoltClock'saUnicorn. This would totally ruin vertical margin collapse. – Marko Vasic Nov 25 '13 at 16:14
  • Don't get me wrong I agree with @Web_Designer's question, why isn't it supported? But why has this question not been closed? Surely this is a subjective question? I'm annoyed because I've seen a lot of questions which are looking for advice get closed where as this is allowed to stay open yet it's basically looking for arguments as to why it wasn't done. It essence there is no factual answer to this question, only a subjective guess. – limitlessloop Oct 30 '14 at 20:48
  • `A always relative to the width of the containing block.` – Muhammad Umer Mar 21 '15 at 19:51
  • which means any attempt to use top and bottom margin to center is pointless – Muhammad Umer Mar 21 '15 at 19:51

10 Answers10

60

Couldn't you use width: calc(50% - 24px); for your cols? Then set your margins.

Slouch
  • 637
  • 5
  • 6
  • 7
    It is highly browser-dependant. Probably around 2020 the ie15 will support it and you will be allowed to use that in your work, too :-( – peterh Nov 25 '13 at 10:32
  • 1
    Doesn't seem to be working so well in Firefox? (or something else I've done isn't) – Laurengineer Jul 30 '15 at 22:21
  • @Morgan Feeney: Yeah, but box-sizing doesn't have a value called margin-box (which is the whole point of this question). Even if such a value was introduced now, how do you propose patching/polyfilling/shimming it into existing browsers? – BoltClock Sep 18 '16 at 09:25
  • Yeah but... specifically responding to an answer suggesting calc() as a workaround. – Morgan Feeney Sep 18 '16 at 12:15
  • Not sure if this applies to the specific example but a major negative to using calc() in our scenario (as at FF 53.0.3) is that its behaviour is not analogous with that of width: X%; From what we can see "calc" is done at time of initial rendering to a static Xpx. This means that unlike width: X%, the calc'ed column does not resize automatically with container resize. – Pancho Jun 07 '17 at 11:53
  • but can you decrement any width with this? `width: calc(width - 24px)`? – xealits Jun 18 '17 at 01:08
  • I down-voted this because it doesn't answer the question. The wording of the title and the text of the question is looking for a logical justification why margin-box was omitted from the spec. It's not looking for alternatives. – Syntax Junkie Jul 28 '18 at 22:42
18

I think we could have a box-sizing: margin-box. The css box model shows exactly, what are the positions of the margins of the frames.

There are minor problems - for example, the margin boxes can overlap - but they aren't hard to solve.

I think, the situation is the same, as we can see with the overflow-x & overflow-y combinations, with the absolut positionied divs in table-cells, with the combination of min|max-width|height with the box-sizing, and so on.

There are features, really simple features, which the browser developers simply doesn't develop.

IMHO, box-sizing: margin-box were a very useful feature. Another useful feature were the box-sizing: padding-box, it exists at least in the standard, but it wasn't implemented in any of the major browsers. Not even in the newest chrome!


Note: @Oriol 's comment: Firefox did implement box-sizing: padding-box. But others didn't, and it was removed from the spec. Firefox will remove it in version 50. Sad.

peterh
  • 11,875
  • 18
  • 85
  • 108
  • 2
    Firefox did implement `box-sizing: padding-box`. But others didn't, and it was removed from the spec. Firefox will remove it in version 50. Sad. – Oriol Sep 19 '16 at 23:50
6

The guy at the top is asking about adding margin to the overall width, including padding and border. The thing is, margin is applied outside the box and padding and border aren't, when using border-box.

I have tried to achieve the border-margin idea. What I have found is that if using margin you can either add a class of .last to the last item (with margin, then apply a margin of zero, or use :last-child/:last-of-type). Or add equal margins all the way around (similar to the padding version above).

See examples here: http://codepen.io/mofeenster/pen/Anidc

border-box calculates the width of the element + its padding + its border as the total width. So if you have 2 divs which are 50% wide, they will be adjacent. If you add 8px padding to them, then you will have a gutter of 16px. Combine that with a wrapping element - which also has padding of 8px - you will have a nicely laid out grid with equal gutters all the way around.

See this example here: http://codepen.io/mofeenster/pen/vGgje

The latter is my favourite method.

Solomon Ucko
  • 5,724
  • 3
  • 24
  • 45
Morgan Feeney
  • 737
  • 7
  • 11
5

I'm sure all of this is obvious, but I'll type it out anyway because...well, I need the exercise. Would the following outcome not be just as efficient as box-sizing: margin-box;:

.col2 {
    width: 45%;
    height: 90%;
    margin: 5% 2.5%;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    float: left;
}

http://jsfiddle.net/Fg3hg/

box-sizing is used to control from which point the padding and border are assessed to the overall size of the element. So while it's not kosher to include px margins with a % width (as is usually always the case), it's easier to calculate what the relative percentage amount should be because you don't have to incorporate padding and borders to the defined width.

Plummer
  • 6,522
  • 13
  • 47
  • 75
  • 9
    The use case for something like margin-box is to enable mixing percentage widths with pixel margins. If you want two 50% boxes with a 1px margin between them, this cannot be accomplished with a percentage margin of 1% of similar - some small screen sizes will round 1% down to 0 pixels and suddenly you have no margin. What we really need is more browser support for calc() as @Slouch shows, or the flexbox model. –  May 22 '14 at 20:50
  • 1
    If that's the care, the parent container would be less than 100px, and I would hope some design elements would be re-thought at that point. There are some other things you could do with nested elements and the like, but, yes, have variable calculations would be pretty dope. If you're into things like sass or less, I think they do a lot of this stuff. I've played around with them, but am no Jedi yet. – Plummer Jun 02 '14 at 20:57
  • 2
    What you're suggesting is a work around. It's not an ideal way to write CSS when you are working with complex layouts. You're assuming that the designer or author wants to use percentages in their design. Also regardless of this issue, even if you use the calc() function to work out spacing using pixel margins it still limits the designer because they must predetermine what the guttering is, rather than allowing it to be overwritten using CSS. – limitlessloop Oct 30 '14 at 20:44
  • I don't understand your point. The issue at hand was that including px and % causes line breaks because margin isn't included in size calculation. A margin isn't included in the size of an element, it's the space you want to appear around an element. Plus, how would `margin-box` handle multidimensional margin calculations? `@media` breakpoints, `max-width` and `min-width` work just fine. I guess `margin-box` might cut down on some bloat, but I also get reasons why it may be considered redundant. – Plummer Dec 17 '14 at 17:20
  • Why is no one mentioning that this margin Percentage VALUE is the percentage of width for some reason...doesn't matter height or width. The width of parent is used. Which is bizzare to say the least.. so code above shouldn't work and doesn't work. unless you make height and width equal. – Muhammad Umer Mar 21 '15 at 19:48
4

This is because the box-sizing attribute refers to the size of an element after computing the given dimension-specific values (padding, borders). "box-sizing: border-box" sets the height/width of an element and takes into consideration the padding as well as the border width. The scope of an element's margin is greater than the element itself, meaning it modifies the flow of the page and its surrounding elements, therefore directly altering the way the element fits within its parent relative to its sibling elements. Ultimately a "margin-box" attribute value would cause major problems and is essentially the same as setting the elements height/width directly.

Ryan
  • 295
  • 2
  • 8
  • 1
    my apologies but I don't understand how including padding, border and margin in the spacial calculation via "margin-box" would differ conceptually from including padding and border via "border-box". Surely it's just a variation on the same theme? – Pancho Jun 07 '17 at 12:07
3

Dimensions of block-level, non-replaced elements in normal flow must satisfy

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = width of containing block

When over-constrained, browsers must adjust either the left or right margin. I think that means the width of the margin box must equal the width of the containing block (i.e. 100%).

For your case, transparent borders with box-sizing: border-box can work much like margins.

sam
  • 40,318
  • 2
  • 41
  • 37
1

On Codrops there are a couple of good articles on the subject of the effect of margins and row's forced to overflow. They suggest using the rem or em unit with a normalizer css setting font size to 100% for all browsers, then when you set widths and margins it is easy to keep track of the effect on the row's width by simply making a note in comments for the total width. A conversion of 16px to 1 em is the way to calculte the targeted viewports total witdh.

Working like that for the dev stage at least and then if you want 'responsive' templates you can convert widths to % including the margin widths.

The other and often simpler way they suggest to handle gutters is to use the pseudo after and the content: ''; on each of your columns which I find works really well. If you set a div class that is the defined last column such as end you can then target that class not to have the pseudo after, or to have a wider one; which ever best suits your layout.

The added bonus of using this pseudo element method is it also gives you a target for shadows that can give a more 3d effect and greater depth to the flat image on the readers monitor as well. I am experimenting with this effect at the moment by scaling up the effects being used on buttons, 'tweaking' the gradients, and the z-index.

Weedy101
  • 13
  • 1
  • 8
1

Perhaps set the border to 0% opacity using RGBA and use the border as a margin.

  • Sounds like a hack, but would do the job. – Morgan Feeney Oct 26 '14 at 20:44
  • This can prove useful if you won't want to use wrappers to achieve the job. – limitlessloop Apr 10 '15 at 09:22
  • 2
    ...unless you actually need a border – FrancescoMM Feb 16 '17 at 17:25
  • @FrancescoMM - a bit "noisy", but you could make a box with "margin-width" transparent border (and no margin of course) and inside that place a box with a visible border of the width you want displayed (again having no margin) – Pancho Jun 07 '17 at 12:00
  • 1
    I just can't follow this kind of thinking. Is there anything more natural than saying that I want two boxes `1px` apart, each one taking `50%` of available space? That's exactly what `margin-box` would do. Or forget margin box and think about available space. Not 50% of parent container, but 50% of what's left. No "calc", no "5% margin", no such mess... – maaartinus Jan 15 '19 at 18:50
0

There interesting situation when using box-sizing inside body content

no content no border box gives no any value on left-right margin % recount of this two box recount algoritms

  .body{
    box-sizing: border-box;
    margin:0 3%;
  }

Firefox versions before 57 also supported the padding-box value for box-sizing, though this value was been removed from the specification and later versions of the browser.

So margin-box even not planned...

0

There should be a box-sizing: margin-box;

But does the following work: Put a div around it with

      .divX{
         width:  XX%;
         display:flex;
         align-items: center;
        justify-content: center;
      }