Specific height and width, but also use padding/margin? - html

So I'm trying to create an A4 page. Let's just say the margin of the page is 50px for now. The whole document (A4) is 300x300 pixels in my example:
https://jsfiddle.net/pfs01ucw/
What I get is this:
What I want is something like this:
I simply want to set a fixed container's width and height, add some margin and make the wrapper inside fill the entire space. If I add padding: 50px to the #container DIV, the height and size will increase by 50px on all sides (basically making it 400x400 pixels instead).
How do I achieve this?

box-sizing: border-box;
The width and height properties include the content, the padding and border, but not the margin. This is the box model used by Internet Explorer when the document is in Quirks mode. Note that padding and border will be inside of the box e.g. .box {width: 350px; border: 10px solid black;} leads to a box rendered in the browser of width: 350px. The content box can't be negative and is floored to 0, making it impossible to use border-box to make the element disappear.
Here the dimension is calculated as, width = border + padding + width of the content, and height = border + padding + height of the content.
MDN - box-sizing - CSS
Fiddle

<div id="container">
<div id="wrapper">
</div>
</div>
<style>
#container {
border: 1px solid #000;
height: 300px;
padding: 50px;
width: 300px;
}
#wrapper {
border: 4px solid #000;
height: 100%;
}</style>

Related

How to make the HTML container and iframe embedded in it, exactly the same size

I created a simple sketch with the P5.js web editor which I would like to embed into my website.
The canvas of my test sketch has a height and widht of 300px.
This is what the sketch looks light when I simply drop it on a website and this is what it looks like when I add some simple CSS. Here is my code:
#container {
border: 2px solid blue;
display: inline-block
}
#canvas {
width: 300px;
height: 300px
}
<div id="container">
<iframe src="https://editor.p5js.org/Kubi/embed/BkuSPoiZ4" frameBorder="0" id="canvas"></iframe>
</div>
Although I manually set the size of the #canvas element to 300 x 300px, the outer #container is visibly larger and has a height of 304 px.
Why is this the case? How can I make the #container the exact same size as the iFrame without manually having to also set the size of #container?
This is because you set a border of 2px on each side for the container: border: 2px solid blue; this expands the container 4px (2px on the left and 2px on the right) hence the 304px width. You could change your CSS to the following to get a 300x300 px container:
#container {
display: inline-block;
line-height: 0;
}
The line-height removes the space that all elements have at the bottom for minimal space between lines.

Padding overrides height of the element with box-sizing: border-box

In snippet below padding-top overrides the height and max-height properties of container:
I want this <div> to be 10px high, but its 100px because of padding-top
as far as I understand this should be solved by box-sizing: border-box but this doesn't help
w3schools - border-box: the width and height properties (and min/max properties)
includes content, padding and border, but not the margin
.padding-test {
background: linear-gradient(109deg, #3adffd, #00abfb);
outline: 1px solid #3b3c6d;
width: 100%;
padding-top: 100px;
max-height: 10px;
height: 10px;
box-sizing: border-box;
}
<div class='padding-test'></div>
Can someone explain why is this happening and how to fix this?
Same happens for width and padding-left
UPD: I faced this issue when tried to change max height for box sized by aspect-ratio approach. I solved initial issue by setting parent size, but I still want to understand how border-box works with the padding - does it shrinks only content? is this correct behavior? is there any solution for this exact situation - can I override padding somehow?
I had run into the same doubt. According to MDN:
border-box
The width and height properties include the content, padding, and border, but do not include the margin. Note that padding and border will be inside of the box. For example, .box {width: 350px; border: 10px solid black;} renders a box that is 350px wide, with the area for content being 330px wide. The content box can't be negative and is floored to 0, making it impossible to use border-box to make the element disappear.
so box-sizing: border-box doesn't mean you can set the "border box" directly, but only affects how "content box" is calculated, which cannot be negative.
And my solution is: avoid the paddings, use a height-holding div or ::before pseudo element with designated height instead. (may also need overflow: hidden.) For example:
.padding-test {
height: 10px;
box-sizing: border-box;
overflow: hidden;
}
.padding-test::before {
height: 100px;
content: '';
display: block;
}

Input element with padding and percentage width exceeds parent div

I have this:
<div class="wrapper">
<input type="text"/>
</div>
div{
border: 1px solid red;
width: 300px;
}
input{
width: 100%;
padding: 10px;
}
I need the input to be 100% of the parent div, but also I need this input to have 10px padding. Results can be seen here: http://jsfiddle.net/pdJYF/
How can I achieve this?
Add box-sizing to your input field:
input{
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
padding: 10px;
}
Example Fiddle
Browser Compatibility
The underlying "problem" is the box model of HTML/CSS. As you can see in the illustration of the respective MDN article each element's box has 4 different areas: margin box, border box, padding box and content box.
When you assign measures (width or height) to the element, this is applied to one of these areas. If the area is, e.g., the content box, then for the total size of the element margin, border and padding is added. So you wont set the total dimensions of the box, but one of its contained boxes.
The CSS property box-sizing tells the browser, which box to use, when calculating the element's dimensions. The default value is content-box. So in the above example values for margin, border and padding get added and hence the element is too big. By setting the box model to border-box, only the margin gets added to the dimensions (which is zero here) and the elements fits.
Why you don't put the padding in percentage too:
input{
width: 94%;
padding: 0 3%;
border:0;
}
You must decrease 2x padding from left and right, and decrease 2x for any pixel you want use like this and insert your input's width.
For example: 20px (paddings left & right) + 2px (borders left & Right )= 22px
300px - 22px = 278px
div { border: 1px solid red; width:300px; }
input { width: 278px;padding: 10px; }

IE6 Two Div's inside a wrapper div, one div refuses to change width when the contents change

I have two divs wrapped by another div. One of the div's is a header, the other will contain an image. I want the content div to wrap the with the correct aspect ratio of the image.
The wrapper div has minimum widths and heights specified. The image can have an arbitrary width specified. The height of the content div should adjust depending on the image height.
It works fine in FF, but in IE6 the header width does not change when the wrapper div changes to accommodate the specified image width.
Here's a fiddle. fiddle
Here's a picture of the problem: Image
In IE6, the header element is going to take up the amount of space defined by it's container element. In this case #testWrapper, which is set to 100px. IE6 won't play very nicely with absolutely positioned elements or floats with widths set to auto. I'd suggest defining the width that you want in #testWrapper and setting the img to 100%, if possible.
#testWrapper{
position:absolute;
bottom: 0;
left: 0;
margin: 5px;
border: 1px solid black;
width:150px;
}
#testHeader {
background: blue;
height: 10px;
}
#testContent {
background: black;
}
#testimage {
display: block;
width: 100%;
}

Fluid CSS layout and Borders

In designing a fluid layout, how do you use borders without ruining the layout.
More specifically, I have a HTML widget which consists of five divs. I would like the five divs to take up all the room in the containing element. I would also like to have a 1px border around each.
I tried:
.box { float: left; height: 100%; width: 100%; border: 1px solid red; }
This doesn't work: there will be an extra 10px in width causing the boxes to wrap. Reducing the width percentage doesn't work as it will not take up the correct amount of space and for certain page sizes, will still wrap.
Whats the proper way to manage the interaction between these elements?
See this article.
Basically, in the "traditional" CSS box model, the width of a box element only specifies the width of the content of the box, excluding its border (and padding).
In CSS3, you can switch to a different box model as follows:
box-sizing: border-box;
Browser-specific implementations of this are:
-moz-box-sizing: border-box; // for Mozilla
-webkit-box-sizing: border-box; // for WebKit
-ms-box-sizing: border-box; // for IE8
This will cause the box sizes to include the element's border and padding. So you can now specify
.box {
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
width:20%;
border:1px solid red;
float:left
}
and have the five divs take up all the width of the containing element without wrapping.
Note that this is not supported by older browsers. For these, you'll have to wrap each box into a second box, as per other responses on this page.
Only put width: 100% on the outermost div, and don't put a border on it. If you do this, then the inner boxes will fill the space (assuming you haven't floated them or anything) since they're block elements, and you won't have to worry about borders adding to the total size.
If you really need the appearance of five solid single pixel nested borders, you can do something like this (with properly semantic names, hopefully):
<div class="one">
<div class="two">
<div class="three">
etc.
</div>
</div>
</div>
<style>
.one {
width: 100%;
}
.two {
border: 1px solid red;
padding: 1px;
background: red;
}
.three {
border: 1px solid red;
background: white;
}
</style>
As you can see, you can fake the second border using padding and background colors on the second div (might even cut down on the total number of divs by doing this; just remember you can't pad the outmost div without screwing up your width).
Oh boy, I almost hate to mention this, but there is a very easy way to do this in a horizontal bar. It isn't "pixel perfect" except at your minimum width, but is not discernible to the naked eye.
Divide the container div by the number of items. Let's say, you have six nav items with a white border (this is especially good for numbers that don't divide into 100 because it won't be perfect in any case).
Set your total width for each left-floated child div to the correct fraction (using % for left or right margin or padding) so that they equal # 100%. Go ahead and put a 1px border-right on the child divs. For the last div at the right end, either make a second class with no border or just use style='border:none'.
Then, at your minimum width, slowly drop the width of each child div until they fit.
Here is a bit of code from an old page of mine using this method for a liquid page with minimum width of 960px (958 px and a 1px border on each side):
.navitem {
width: 16.57%;
height: 35px;
float: left;
text-align: center;
font: 1em/35px arial,sans-serif;
border-right: 1px solid #eee;
margin: 0 auto 0 auto;
padding: 0;
}
I think it actually is as close to pixel perfect as you can get at minimum width, and at higher widths although the right-hand div is maybe 4 px wider than the others, you can't tell by looking at it. (Obviously, this wouldn't work if you need a right border on the right-most div, since you'd see a few pixels of background.)
This will get you fairly close but not 100% of the way (pun intended). To give an element 100% height it needs to know "100% of what?". All parent elements must also be given 100% height and this includes the body. Or as the W3C put it: "If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'." As you can see we also need to give the body "position: absolute;" for the height to be honored. This example also divides the width into five equal columns with borders (and some padding and margin just for fun):
<style>
body {
width: 100%;
height: 100%;
margin: 0;
position: absolute;
/* overflow: hidden; */
}
div.section {
float: left;
width: 19.95%;
height: 100%;
}
div.column {
height: 100%;
border: 1px solid blue;
margin: 1em;
padding: 2em;
}
</style>
<div class="section"><div class="column">one</div></div>
<div class="section"><div class="column">two</div></div>
<div class="section"><div class="column">three</div></div>
<div class="section"><div class="column">four</div></div>
<div class="section"><div class="column">five</div></div>
As you can see when you test it we have no problem with the witdh. This is because the "sections" that divide the width have no padding, margin or borders. Thus the width we set will be the width they occupy on screen. Now, this is not strictly true in practice. I have actually set the widths 19.95% and not the expected 20%. Problem is that some browsers (IE for one) have a rounding error when adding up percentages and the more subdivisions to add up the greater the error.
Where this method obviously fails is when it comes to the height. Unlike "width: auto;", which will make the div occupy the available horizontal space, "height: auto;" will only make the div as tall as its content. You have to specify "height: 100%;" to get the div to fill the height of the window but alas, when adding margin, padding and borders, the rendered height of the div becomes greater than the viewport, resulting in a vertical scrollbar.
Here I can only really see two choices; Either 1) accept that the divs don't quite fill the window height and set their height to maybe 80% or 2) Skip the bottom border and set the body to "overflow: hidden;", which will crop off the parts of the divs that protrude beyond the edge of the window.
Finally, of course you could also make use of some simple scripting to achieve what you're after. Shouldn't be very complicated at all - but that's a question with another tag... Happy coding!