Why does CSS padding increase size of element? - html

I am trying to give my div and textarea some padding. When I do this, it increases the size of the element, instead of shrinking the content area inside of it. Is there any way to achieve what I am trying to do?

You could add box-sizing:border-box to the container element, to be able to specify a width and height that don't vary when you add padding and/or border to the element.
See here (MDN) for specifications.
Update (copied comment to answer)
Right now, the value border-box is supported in all major browsers, according to MDN Specs
Some browsers of course requires proper prefix i.e. -webkit and -moz as you can clearly see here

According to CSS2 specs, the rendered width of a box type element is equal to the sum of its width, left/right border and left/right padding (left/right margin comes into play as well). If your box has a width of '100%' and also has margin, border and padding, they will affect (increase) the width occupied by the object.
So, if your textarea needs to be 100% wide, assign values to width, margin-left/right, border-left/right and padding-left/right in such a way that their sum equals 100%.
In CSS3 we have three box-sizing models. You can use border-box model:
The specified width and height (and respective min/max properties) on
this element determine the border box of the element. That is, any
padding or border specified on the element is laid out and drawn
inside this specified width and height. The content width and height
are calculated by subtracting the border and padding widths of the
respective sides from the specified ‘width’ and ‘height’ properties.

This was a mess on W3C part and various browsers only added to this complexity with their own versions of box models. Personally, instead of thinking which browser or CSS setting will do the trick I just wrap the box' content in yet another DIV statement and use margins on that DIV, instead of using padding, like this:
<div id="container" style="width: 300px; border: 10px solid red;">
<div id="content" style="width: 250px; margin: 25px;">
Some content
</div>
</div>
Although this only works for fixed size containers

It depends on the browser and it's implementation of the box model. What you are experiencing is the correct behavior.
IE traditionally got it wrong: http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug

For a more cross-browser solution, you can avoid this behavior, by wrapping whatever tag that needs padding into another tag with fixed width, and giving it width:auto. This way, if the parent has a width of x, and you add padding to the child, the child will inherit the full width of x, applying the padding correctly without modifying the parent width or its own.

A div by default takes the width of its parent container, so to avoid browser compatibility issues, you could add a child div in the specified div then add the required padding to the child div.
N.B - don't specify width to the child div because it would increase if you add padding

Related

Padding increasing the total size of a box element

Is this the correct behavior for padding to increase the total size of a box element ? I'm trying to set padding to the left side of a box element which has the width set to 940px but when I add 25px in padding to the left side it adds these pixels to the width of the box element making it overlap the body-wrapper which is the parent element.
I also tried marging-left but while this doesn't add to the total width of my box element it pushes it to the right causing it to overlap as well..
What is the best way to dealing with this issue?
Please check screenshot for a visual:
It is the default behaviour of the box model. You can learn more about the box model here.
In your CSS you can define the behaviour with the box-sizing attribute. In this case you'll want:
box-sizing:border-box;
border-box takes the padding and border sizes into account when setting the width of the element, which is what you're looking for. However, it will not calculate based on margin sizes.

<div> with margin-left and right set to auto becomes uncentered >1634px

I have a div, .instagram_grid which has margin-left and margin-right set to auto, is relatively positioned, and has a width which for browse sizes 900px >makes the div be centered nicely in the page.
when I have the simple structure in the context of the rest of the CSS for a single page, the no longer becomes centered at browser width >1684px. In the Fiddle that follows I only have two lines that modify the div as a whole (and one just sets the background to pink). There are no media queries present, which suggests that it is the effect of some unseen preceding div/element causing the behavior.
https://jsfiddle.net/ebbnormal/m561tpnL/6/
The behaviour is what is expected with that markup.
The element is centered, but then you use relative positioning to show it 500px to the right of where it actually would be.
The .calc-text div above the .instagram_grid div causes its parent to overflow by setting margin-left:auto while simultaneously setting left: to a negative value, which isn't valid CSS.

Why does padding add to the visible width of an element even when box-sizing is set to border-box?

So I was coding using Semantic-ui, and I have two toggle boxes (check boxes) next to each other in a flexbox container. When the window size is reduced, they wrap around so that one is on top of the other.
To get them to spread out a little, I added both right and bottom padding of around 5px. However I noticed a strange behaviour. Padding would cause the boxes to move apart horizontally, but when stacked vertically there was no space between them, even though there was bottom padding on each box.
Further investigation showed that the box-sizing property of the check boxes was set to border-box. After reading up, I found that the border-box box model calculates the width and height to include the padding and the border.
The checkboxes have a height of 1.5rem assigned.
My question is as follows. As is my understanding, padding shouldn't change the size of the element when using border-box. However this only seems to be true if definite dimensions are set as shown in the linked jsfiddle. Height is set, so the bottom padding isn't added on as an extra. But width isn't and right padding has an effect on the visible width of the divs.
Why is this the case? Surely padding should have no effect on the size of the element (unless set to something ridiculous, larger than the element itself), irrespective on whether I've defined a definite width or left it to be calculated?
JSFiddle: http://jsfiddle.net/Astridax/8cd48emn/
Please try and toggle the paddings using dev tools to see what I mean.
As is my understanding, padding shouldn't change the size of the element when using border-box.
This is where you're confused. Here's what the spec has to say on this subject: http://www.w3.org/TR/css3-ui/#box-sizing0
border-box
The specified width and height (and respective min/max
properties) on this element determine the border box of the element.
That is, any padding or border specified on the element is laid out
and drawn inside this specified width and height. The content width
and height are calculated by subtracting the border and padding widths
of the respective sides from the specified ‘width’ and ‘height’
properties. As the content width and height cannot be negative
([CSS21], section 10.2), this computation is floored at 0.
The actual effect of setting box-sizing to border-box is that specified widths will be said to include the border and the padding. The spec says nothing about unspecified widths, which are therefore treated as normal - as wide as they need to be to incorporate both the content and the padding and the border.
Edit:
What you're implying should happen is actually impossible to do, for the following reason. Imagine you have content in a div such that the auto width of the content alone would be 500px exactly. Then throw a 20px padding around that.
#myDiv {
padding: 20px;
width: auto;
}
No problem yet - you have a 540px wide div with the box-sizing at content-box by default.
Okay, so lets change the box-sizing to border-box.
#myDiv {
box-sizing: border-box;
padding: 20px;
width: auto;
}
What you're suggesting should happen is that the padding should now be ignored. So we have a div with 500px worth of content, we're going to now include the padding within that 500px instead of extending the width of the div. But wait - now the content box has shrunk to 460px to allow for the padding and the overall size of the box is 500px. But wait, we're not supposed to be accounting for the padding when calculating the width, so we'd better render the div at 460px right?
You see the problem? You could go on infinitely like this.

Why this behaviour (on ALL browsers) with margin-top?

This is my code :
HTML
<div class='father'>
<div class='son'>Son</div>
</div>
CSS
.father
{
background-color:blue;
}
.son
{
margin-top:50px;
background-color:red;
height:50px;
}
Where is the background-color blue of the father?
I know how to fix this problem (putting padding-top:1px to the father) but I'd like to know why of this behaviour!
For me it doesnt make sense, because on every browsers, not only IE, this is the behaviour.
This is a result of Collapsing Margins. You can read a good article by Eric Meyer on this topic where he illustrates this exact behavior. The following image is from his article.
Here's what the CSS2 specification has to say about it.
8.3.1 Collapsing margins
If the top and bottom margins of a box are adjoining, then it is
possible for margins to collapse through it. In this case, the
position of the element depends on its relationship with the other
elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as
the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved.
The position of the element's top border edge is the same as it
would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through
have no effect on the positions of the other elements with whose
margins they are being collapsed; the top border edge position is only
required for laying out descendants of these elements.
Source: http://www.w3.org/TR/CSS2/box.html#collapsing-margins
This is because the div is a block-level element. Certain block-level elements don't contain any padding by default. Divs are one such element. Block-level elements will take up the entire height and width of the container while respecting any padding it may contain.
W3C Visual formatting model
The parent element's height is set to its content's height by default. Once you set a height on the parent, that's no longer the default. Checking up on it, I believe that the padding adds to the height. So, the height is originally determined by the content unless otherwise stated in the CSS. Then, in most cases (IE 6 may be the exception), the padding is added to the height.
Good thing about SO, it helps us be much more detailed in our responses. :)
In CSS, block level elements naturally fills the elements content area, so your "son" div is filling your "father" div completely. Of course, you can bypass this by adding margin/padding/height to your parent div.
You're setting blue explicitly:
.father {
background-color:blue;
}
It's overridden (thanks to the "C" in CSS a.k.a cascading) but the style remains on your parent element (here, appropriately named "father").
If your .father box receives any height at all (check in the Firebug/Chrome dev tools inspector) than the blue is going to show through. I am guessing this is what you're seeing in IE (that or perhaps there's a flash of content before your child element style comes in). I don't think the IE debug tools show bounding boxes but you can test the element for it's height using JavaScript.
Moving outwards from the content, you have padding, border, and margin (as you probably know). Background covers only padding, but not margin.

Table width goes beyond the div border

I have table within the div. If I view it with IE9 or FF then it is ok. But if I view it within IE8 the table grows beyond the div border. Any ideas?
<div>
<table width="100%" >
<tr>
<td>
</td>
</tr>
</table>
</div>
found the solution here:
http://www.456bereastreet.com/archive/200704/how_to_prevent_html_tables_from_becoming_too_wide/
The trick is to use the CSS property table-layout. It can take three
values: auto, fixed, and inherit. The normal (initial) value is auto,
which means that the table width is given by its columns and any
borders. In other words, it expands if necessary.
What you want to use is table-layout:fixed. Bam! Now the table is as
wide as you have specified in the CSS. No more, no less. And to my
great surprise this seems to be widely supported by browsers. The only
browser of any significance that does not support it is IE/Mac, and
the significance of that browser is rapidly approaching zero.
Next is deciding what to do with the content that doesn’t fit in the
table anymore. If the table only contains text, word-wrap:break-word
(word-wrap is specified in the CSS3 Text Effects Module) will force
the browser to break words as necessary to prevent overflow.
You could set it inside its own div with overflow: scroll; so that it makes a scrollbar when the table expands too much...
Add the style display:table to the div tag. This causes the element to act like a table.
Give table width as 100% so that it will occupy div and wont cross it.
As user384080 mentioned, table-layout:fixed should be added. However, merely having table-layout doesn't always fix the problem. Please make sure that you add the width attribute as well:
<table style="width:100%;table-layout:fixed">
check what box-sizing is set by default by the browser.
box-sizing: content-box; means:
The specified width and height apply
to the width and height respectively
of the content box of the element. The
padding and border of the element are
drawn outside this area.
box-sizing: border-box; means:
The specified width and height
determine the border box of the
element. Any padding or border
specified on the element is drawn
inside the remaining area. The content
box is computed by subtracting the
padding or border widths of the
respective sides from the specified
width and height.
it night just be a matter of changing the box-sizing value.
there's an article about it here: http://ie8demo.com/BoxSizing.aspx
Do you have a width set on the div? If so, it will stick to its width, allowing the table to overlap. Try removing the width and it will expand to its container's width. If you want thwe div to fit the table size, you can float it.
In addition to the first answer, make sure that the container element of the div has overflow: auto or scroll. The clearfix hack is helpful, too.