box-sizing: border-box with no declared height/width - css

I'm trying to understand how box-sizing: border-box work in the code below. When the height or width is set (no padding), it works as intended (border appears inside the div). But if you only use the padding to create the dimension of the div, it does not work. Can someone explain why? Here's the demo:
div.test {
background-color: red;
box-sizing: border-box;
display: inline-block;
border: 5px solid;
text-align: center;
padding: 50px;
vertical-align: middle;
// height: 100px;
// width: 100px;
}
div.test:first-of-type {
border: none;
}
<div class="test">aa</div>
<div class="test">aa</div>
https://codepen.io/anon/pen/bxaBER

TL;DR
An idea is to keep border for both. Instead of none simply make the color transparent so that the size (including border + padding) will always be the same for both.
div.test {
background-color: red;
box-sizing: border-box;
display: inline-block;
border: 5px solid;
text-align: center;
padding: 50px;
}
div.test:first-of-type {
border-color: transparent;
}
<div class="test">aa</div>
<div class="test">aa</div>
Why?
When setting height/width you explictly define that both sould have fixed size and this size will include border, padding and content. As we can read in the documentation:
border-box
tells the browser to account for any border and padding in
the values you specify for an element's width and height. If you set
an element's width to 100 pixels, that 100 pixels will include any
border or padding you added, and the content box will shrink to absorb
that extra width.
And
Here the dimensions of the element are calculated as: width = border +
padding + width of the content, and height = border + padding + height
of the content.
Now, suppose you include a padding of 45px with the 5px border. In this case both box will be equal but you will notice that the one with border will have a height/width 0 for the content because we already reached 100px with padding and border (45px*2 + 5px*2 = 100px) but the other box will still have some space for content:
div.test {
background-color: red;
box-sizing: border-box;
display: inline-block;
border: 5px solid;
text-align: center;
padding: 45px;
height:100px;
width:100px;
vertical-align:middle;
}
div.test:first-of-type {
border:none;
}
<div class="test">aa</div>
<div class="test">aa</div>
Now if we start increasing the padding, the first box still have some content to shrink (10px) but the second one no! In this case, border-box and the fixed width/height will have no effect because border + padding exceeded the 100px (46px*2 + 5px*2 = 102px). That's why starting from 45px of padding we see a difference between both boxes and strating from 50px of padding both box will have no content to shrink BUT the second box has more border which will logically make its size bigger. It also become useless to define width or height.
In other words, border-box only applies when padding + border < width/height because only in this case we still have content to shrink.
Here is a better illustration with bigger border and you will see that we have 3 states. (1) when both have content to shrink (2) when only one has content to shrink (3) when both have no content to shrink:
div.test {
background-color: red;
box-sizing: border-box;
display: inline-block;
vertical-align:top;
border: 30px solid;
text-align: center;
padding: 5px;
width:100px;
height:100px;
animation:pad 10s infinite linear alternate;
}
div.test:first-of-type {
border:none;
}
#keyframes pad {
0% {padding:5px}
33% {padding:20px}
66% {padding:50px}
100% {padding:100px;}
}
.change:after {
content:"";
animation:change 10s infinite linear alternate;
}
#keyframes change {
0%,33% {content:" (1): same size for both and fixed width/height are respected "}
33.1%,66% {content:" (2): The second box has no more content to shrink, it starts growing (fixed height/width and border-box has no effect)"}
66.1%,100% {content:" (3): Both boxes has no more content to shrink, they will keep growing BUT the second one has more border so bigger size"}
}
<p class="change">we are at state </p>
<div class="test">aa</div>
<div class="test">aa</div>
In order to avoid this, we keep the same padding/border for both elements like we initially said.

Assuming this is the only css on the page How wide will the box be when its rendered
.box{ Width: 100px; Height: 50px; Padding: 5px; Border: 1px solid red; Background-color: red;}

Related

Why is this CSS code overflowing inside my inner box even though it fits my outer box?

So I created a box with 2 div tags, namely: outer div and box div.
The total width(content block) of my outer div is 600w+50padLeft+50padRight= 700px. Meanwhile the total width of my box div (containing block) is 500w+98padL+98padR+4border = 700px.
Yet, my box is overflowing in the outer div.
Here is the image:
https://www.flickr.com/photos/183721425#N02/48599642452/in/dateposted-public/
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to understand
how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>
Use box-sizng:border-box property.
It defines how the width and height of an element are calculated, should they include padding and borders, or not. Margin is not considered. Usually the size (width or height) of the element not include border or padding
*{
box-sizing: border-box;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>calculating element dimensions</title>
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
/*add styles here*/
</style>
</head>
<body>
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to
understand how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>
</body>
</html>
Problem :
Your issue is with the box model itself as by default the border and the padding are not included in the actual elements width :
.outer has a width of 600px and has a 50px of padding (total width is 600px + 50px right padding + 50px left padding = 700px) so the .box will be shifted 50px to the right.
.box has 500px for the width, 98px for the padding and a 2px border which results in a 500px + 98px right padding + 98px left padding + 2px left border + 2px right border =700px.
the widths are equal but don't forget about the 50px of padding on the .outer that results on an overflow.
Solution :
The solution is very simple, add box-sizing: border-box on the two divs (better to use it on all the elements) which includes the padding and border on the width (meaning the padding and border won't overflow the declared width).
* {
box-sizing: border-box; /** that's it ! **/
}
aside,
article,
section,
header,
footer,
nav {
display: block;
}
div,
p {
margin: 0;
padding: 0;
}
html {
background: #ccc;
}
.outer {
/* TOTAL WIDTH: 700px */
width: 600px;
margin: 0 auto;
background: #9CF;
padding: 50px;
}
.box {
background: #B7D19C;
/* TOTAL WIDTH: 700px */
width: 500px;
padding: 98px;
border: 2px black solid;
}
p {
background: #FF9;
height: 100%;
/* here */
}
<div class="outer">
<div class="box">
<p>Here we'll need to calculate the width of this interior div element. This may seem simple at first, but as we begin to add box model properties, and as the overall width of the parent element and the div conflict with one another, we'll need to understand
how each of the properties combine to effect the overall width (and height) of page elements.
</p>
</div>
</div>

CSS: Why does this inline-block div not display on the same line?

I've been experimenting with display:inline-block on div elements and I'm trying to work out why my two inner div elements are not displaying on the same line. Both divs are set to width of 200px and their parent div is set to 400px.
If I set the inner divs to float left instead of using inner-block it works as expected.
The code snippet is as below:
Note: that I've set box-sizing to border-box. So I assumed this would make both inner divs exactly 200px even with the 1px border.
* {
box-sizing: border-box;
}
html,
body {
padding: 0;
margin: 0
}
.container {
width: 400px;
}
.inner {
border: 1px solid black;
padding: 10px 0;
width: 200px;
display: inline-block;
}
<h1>Why does this display on two lines?</h1>
<div class="container">
<div class="inner">Testing border box property</div>
<div class="inner">Second div</div>
</div>
You could remove the white space between inline-block elements by adding font-size:0px; to parent element (.container) then add font-size (e.g 16px) to child (.inner) elements.
* {
box-sizing: border-box;
}
html,
body {
padding: 0;
margin: 0
}
.container {
width: 400px;
font-size:0px;
}
.inner {
border: 1px solid black;
padding: 10px 0;
width: 200px;
display: inline-block;
font-size: 16px;
}
<h1>Why does this display on two lines?</h1>
<div class="container">
<div class="inner">Testing border box property</div>
<div class="inner">Second div</div>
</div>
You need to remove unnecessary spaces between your HTML tags or reset font-size to 0.
check it here :
Fighting the Space Between Inline Block Elements
There is more solutions on the link above.
Plus you can use display:block; float:left instead.
The border. The border will add 2 pixels to each box, so the contents are actually 404 pixels, and it does not fit within the 400 pixels wide div.
There's not enough space in the container div. Change the container div to 404px to account for the left and right sides for each of the inner divs

CSS: containing five floated 20% elements with borders

I'm trying to align five horizontal menu elements with 'float:left' next to each other inside a container that spans 80% of the screen and a minimum of 960px. For this, I had initially set their min-width to 192px (960/5) and their width to 20%, but quickly realized this does not play well with adding 1px borders, causing one of the buttons to be 'thrown overboard'.
Changing the widths to 19.895333% and 191px, respectively, solved the issue, however this is clearly a hacky solution which also leaves an ugly space of 2-3 pixels at the right side of the menu.
Is there a more elegant way to align these elements and account for the bonus width added by borders, padding etc? I have tried 'overflow:hidden' to simply hide whatever may poke outside the container, but this just hides the entire 5th button.
A picture to illustrate the result:
The html code:
<div class="menucontainer">
<div class="menutab" id="menutab_first">News</div>
<div class="menutab">Game Guide</div>
<div class="menutab">Articles</div>
<div class="menutab">Media</div>
<div class="menutab" id="menutab_last">Community</div>
</div>
The css code:
.menucontainer {
height: 26px;
margin-left: auto;
margin-right: auto;
border-width: 1px;
border-style: solid;
border-color: #303030 #101010 #000 #101010;
border-radius: 0px 0px 8px 8px;
}
.menutab {
line-height: 26px;
float: left;
width: 19.895333%;
text-align: center;
min-width: 191px;
border-right: 1px solid #202020;
background-image: url('../img/menubutton2.png');
background-size: 100% 100%;
font-family: 'Cabin', sans-serif;
}
#menutab_first {
border-radius: 0px 0px 0px 8px;
}
#menutab_last {
border-right: 0px;
width: 20%;
min-width: 192px;
border-radius: 0px 0px 8px 0px;
}
Thank you in advance!
For this you can make use of the box-sizing property to set your borders to appear within your elements rather than outside of them:
elem {
-webkit-box-sizing: border-box; /* Some mobile browsers. */
-moz-box-sizing: border-box; /* Firefox. */
box-sizing: border-box; /* All other browsers IE8+. */
}
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.
So in the case of your CSS:
.menutab {
...
width: 20%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
...
}
What you need is box-sizing:border-box;
This CSS property will change the box model for the element such that the border is included inside the width, rather than outside of it as with the standard box model.
This means that your boxes will then be 20% of the width of the page, rather than 20% + the width of the borders.
Problem solved.
box-sizing: border-box causes the width of the borders to be counted as part of the 20%. That's the best solution but if that will interfere with your layout in some way, an alternative is use calc to subtract the borders from the 20%, e.g. width: calc(20% - 2px);

How to add borders to div without messing up the layout?

I have the following elements:
<body>
<div id="container">
<div id="sidebar1"></div>
<div id="content">
<h3>Lorem ipsum</h3>
<p>Whatnot.</p>
</div>
<div id="sidebar2"></div>
</div>
</body>
Following this style:
/* ~~ this fixed width container surrounds all other divs~~ */
#container {
width: 960px;
background-color: #FFF;
margin: 0 auto;
overflow: hidden;
}
#sidebar1 {
float: left;
width: 180px;
/*border: 2px solid black;*/
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
#content {
padding: 10px 0;
width: 600px;
float: left;
}
#sidebar2 {
float: left;
width: 180px;
/*border: 2px solid black;*/
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
I am trying to achieve this layout: http://jsfiddle.net/QnRe4/
But as soon as I un-comment the borders it turns into this: http://jsfiddle.net/FZxPQ/
** Solved **
The border width was added to each element's total width making them too wide to fit in the container. Removing 2x the border width from each column's width solves the problem: http://jsfiddle.net/FZxPQ/4/
CSS box-sizing to the rescue! This property
alters the default CSS box model used to calculate widths and heights of elements
The border-box value means that
the width and height properties include the padding and border
/* support Firefox, WebKit, Opera and IE8+ */
#container, #sidebar1, #sidebar2 {
box-sizing: border-box;
-moz-box-sizing: border-box;
}
However, browser support is not 100% standardized.
As other answers have already mentioned the extra width which pushes the sidebars out of alignment is because the width calculation includes the border width. box-sizing simply tells the browser that an element with a given width/height should include any border and padding values into the final width/height calculations.
The problem is that when you add in the boarder, the size of the outer divs increased by 4, 2px on each size. So, your container needs to grow in size by 8px.
So change your container to:
#container {
width: 970px;
background-color: #FFF;
margin: 0 auto;
overflow: hidden;
}
See: http://jsfiddle.net/QnRe4/13/
When you apply the borders, that goes outer the divs, so the sidebars will have 184px width which doesn't fits to the container. try addig width: 176px
http://jsfiddle.net/QnRe4/12/
#sidebar1 {
float: left;
width: 176px;
border: 2px solid black;
background-color: #EADCAE;
padding: 0px 0px 100% 0px;
}
Like this? http://jsfiddle.net/QnRe4/3/
What's happening is that your elements are losing their block display properties when you remove the borders.
So, adding display: block to those elements resolves that.
I've also adjusted your element's widths by 4px in width to retain the layout, since removing those borders essentially reduces the space that those elements occupy on-page.

Keeping/scaling DIV Ratio with percentages

At the moment I have a layout that pulls a number of thumbnails into a grid - each is defined by a style that keeps them a fixed ratio, (roughly 16:9) which is defined by pixel dimensions (389px x 230px) but they are looking a bit small on high-res screens.
The images are actually pulled into the DIV as a background that covers 100% width and height of the DIV and then the DIV's obviously control the aspect and size.
What I am looking to do is have these DIV's dynamically resize based on the page size of the device but to keep the ratio of the DIV's.
Is this possible?
My thoughts would be to set the width based on the percentage of the page but then I'm not sure how I would set the height and keep the correct aspect ratio (due to different resolutions etc.)
What would be the best way to do this?
EDIT - Thanks for all your ideas so far, thought maybe I should show you how I'm pulling in the data at the moment.
In my HTML I've got the following code which generated the grid
<a class="griditem" href="../video.php?video=13" style="background-image:url(../video/Relentless/Relentless.jpg); background-size:100% 100%;">
<div class="titles">
<h5>Relentless Short Stories</h5>
<h6>Frank Turner: The Road</h6>
</div>
This is styled with the following CSS
.griditem {
position: relative;
float: left;
margin-right: 17px;
margin-bottom: 17px;
background-color: #777;
-webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
width: 389px;
height: 230px;
text-align: left;
}
.titles {
padding: 5px;
position: absolute;
bottom: 10px;
left: -1px;
right: -1px;
background: transparent url(../images/layout/white80.png) top left;
-moz-border-radius: 1px 1px 0 0;
border-radius: 1px 1px 0 0;
text-align: left;
}
The reason I'm implementing it this way is so that the Div can float over the bottom of the image.
Just a quick idea which might be useful for you.
It is based on the fact that vertical padding/margin use the WIDTH of the parent box when it is set to percentages, so it is possible to resize a div relative its parent box
http://jsfiddle.net/xExuQ/2/
body,html { height:100%; }
.fixed-ratio-resize {
width: 50%; /* child width = parent width * percent */
padding-bottom: 50%; /* child height = parent width * percent */
height: 0; /* well, it is not perfect :) */
}
​If you want to put some (non-background) content into this nicely resized box, then put an absolutely positioned div inside it.
Reference:
http://www.w3.org/TR/CSS2/box.html#margin-properties and
http://www.w3.org/TR/CSS2/box.html#padding-properties says:
Margins: "The percentage is calculated with respect to the width of the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1."
Paddings:"The percentage is calculated with respect to the width of the generated box's containing block, even for 'padding-top' and 'padding-bottom'. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1."
EDIT
http://jsfiddle.net/mszBF/6/
HTML:
<a class="griditem" href="#" style="background-image: url(http://pic.jpg);">
<span class="titles">
<span class="name">Unicomp Studios</span>
<span class="title">Springs Buckling (2012)</span>
</span>
</a>
CSS:
.griditem {
float: left;
margin-right: 17px;
margin-bottom: 17px;
min-width: 100px; /* extremely narrow blocks ==> crap looking */
width: 30%;
background: blue no-repeat;
background-size: contain; /* from IE9 only: https://developer.mozilla.org/en/CSS/background-size */
border: 1px solid transparent; /* prevent .titles:margin-top's margin collapse */
}
.titles {
/* <a> elements must only have inline elements like img, span.
divs, headers, etc are forbidden, because some browsers will display a big mess (safari) */
display: block; /* so display those inline elements as blocks */
padding: 5px;
margin: 0 auto;
margin-top: 105%;
background: yellow;
}
.titles > span {
display: block;
}​
I know this might not be the best solution, but
<html>
<style type="text/css">
#cool{
width:40%;
background:blue;
padding-bottom:10%;
}
</style>
<div id="cool" >
</div>
</html>
Here Ive used padding-bottom, to maintain its height relative to its width. U can set padding-bottom as a percentage. Hope this helped.

Resources