CSS percentual padding / margin in border-box - css

To my understanding, using box-sizing:content-box, when setting the padding and margin of an element in percent, these will be the percent of the width of the actual content area. So a 50% margin of a 300px wide image, without any relation to its padding, will create a 150px wide margin and therefore an actual size of 450px width (+padding).
Now, when I use box-sizing:border-box, width is defined as content+padding+border. If I set the padding of my element in border-box using percent, will it refer to this different definition of width, therefore referring to itself? If not, and it refers to the content's width only, in that case the content width itself is also dependent of the padding's and border's width (content width=(border-box width)-border-padding), therefore a higher percentage on the padding would refer to a smaller content, making the padding itself smaller again. Am I understanding this right? This seems like the padding would base itself off itself to me in both cases. What am I missing? And in what order is the browser calculating the percentages, based on what (the content only or the actual width)?
Thanks a lot!

It doesn't matter what you set box-sizing to with respect to how the actual sizes of margins and borders are calculated. It will be the same either way.
What content-box or border-box do is control with width and height of an element so that the border and padding are not included (content-box) or they are included (border-box) in the overall size specified by height and width.
Also, borders can't have a width set to a percentage and padding is based on the element's width, not content.
#one {
box-sizing:content-box; /* default */
width:100px;
height:100px;
padding:10%; /* padding % is a percentage of the element's width */
border:1px solid red;
border:10% solid black; /* Borders can't be set to percentages */
background:yellow;
float:left;
}
#two {
box-sizing:border-box; /* default */
width:100px;
height:100px;
padding:10%; /* padding % is a percentage of the element's width */
border:1px solid red;
border:10% solid black; /* Borders can't be set to percentages */
background:blue;
float:left;
}
<div id="one"></div>
<div id="two"></div>

Related

Textarea very strange behavior

Please, have a look at http://jsfiddle.net/g995s/.
<div id="textarea_wrapper">
<textarea>How and where my width is derived from?</textarea>
</div>
#textarea_wrapper{
height: 250px;
border:thick solid green;
}
textarea{
background-color: #930;
border:none;
margin:0;
width:auto;
resize:none;
overflow:hidden;
height:95%;
padding-top:5%;
}
It is impossible to me to explain two things: The first one is why textarea goes outside its parent since height+padding-top=100%?
The second one is how and from where this certain width of textarea is derived?
Thank you
In regards to the first issue, the percentage based padding-top value is relative to the width, not the height, therefore the positioning won't be consistent if the width of the browser is changed - try resizing the window to see this.
8 Box model - 8.4 Padding properties
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.
The padding-top percentage is based of the width of the parent element, not the height.
So it goes outside because 95% of the smaller height + 5% of the larger width = more than 100% of the height.
The width is the default width for the textarea because setting width: auto on textareas does nothing.
Set the textarea width and height to 100% and use a fixed measurement like px or em for the padding if you don't like how the top and bottom percentages work.
Then use box-sizing: border-box on the textarea to make its width, height and padding stay within 100% of its parent; http://www.paulirish.com/2012/box-sizing-border-box-ftw/
Its the padding-top that is increasing the size of the text area
*edit: beaten to it! :)

Using max-height with border-box

Why isn't max-height applied on the box in this example ? It seems like that the border-box mode is ignored (tested on Chrome), but it seems counterintuitive.
The box-sizing property isn't ignored, this is exactly how the border-box value should behave:
Your padding is set to 100px on top and bottom, therefore 200px of your element's height is consumed by the padding.
If you specify a height of 200px, the computed height will be 0 because 200 - 200 is 0.
If you specify a height of 201px, the computed height will be 1, etc.
From the box-sizing documentation:
The content width and height are calculated by subtracting the padding widths of the respective sides from the specified ‘width’ and ‘height’ properties. As the content width and height cannot be negative, this computation is floored at 0.
This is easily demonstrated using borders instead of padding:
#test {
background: #000;
border-width: 100px 0;
border-style: solid;
border-color: red;
height: 200px;
box-sizing: border-box;
}
Here our element has a black background and a red border, however as its height is equal to the sum of the top and bottom border widths, the element ends up with 0px computed:
As you can see, the box is entirely red. The element has no height so there is no black background to be seen. If we adjust the element's height to 250px, we end up with:
The element's computed height here is 50px, so we see 50px of the background. The remaining 200px is consumed by the border.

Css box fluidity issue

I have been trying to make fluid boxes that will squeeze when you resize the window.
but this is whats happening:
When I resize the window the 4th box moves to the bottom and then the width of the boxes shrink. why is the 4th box moves under? what am I doing wrong?
Here's is whats happening:
http://www.dinkypage.com/169785
Here's the source:
http://pastebin.com/raw.php?i=4ZbbXxCq
Help Please
It's because you give the width: 25% to all 4 block, but also give 'padding: 10px' to them so obviously the width need to take more than 100%.
You need to either remove your padding or reduce the width of your block less than the total length of your padding, for example 22%
You need to use box-sizing: border-box. This is because the padding of 10px you have assigned to each of the floated div elements are added on top of the 25% width you have assigned, so the actual sum of the width of all four floated divs will exceed 100% (in fact, it will be 100% + (2*10px)*4 = 100% + 80px
The box-sizing: border-box property will ensure that the height and width you have set for the element will also include the paddings (if any) and/or border widths (if any).
In fact, I would suggest Paul Irish's recommendation using:
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
Since you also have your height explicitly declared, you might want to change the height of the containers to reflect the change in the box model. Since you have a padding-top of 30px and now it will be computed as part of the height of 240px, you should change the height to 240px + 30px (top padding) + 10px (bottom padding) = 280px.

How to set border's thickness in percentages?

How to set border-width of an element in percentages? I tried the syntax
border-width:10%;
But it doesn't work.
The reason I want to set border-width in percentages is I have an element with width: 80%; and height: 80%;, and I want the element to cover the whole browser window, so I want to set all borders 10%. I am not doing this with the two elements method, in which one would be positioned behind the other and act as the border, because the element's background is transparent, and positioning an element behind it would affect it's transparency.
I know this can be done via JavaScript, but I am looking for an CSS only method, if possible at all.
Border doesn't support percentage... but it's still possible...
As others have pointed to CSS specification, percentages aren't supported on borders:
'border-top-width',
'border-right-width',
'border-bottom-width',
'border-left-width'
Value: <border-width> | inherit
Initial: medium
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value: absolute length; '0' if the border style is 'none' or 'hidden'
As you can see it says Percentages: N/A.
Non-scripted solution
You can simulate your percentage borders with a wrapper element where you would:
set wrapper element's background-color to your desired border colour
set wrapper element's padding in percentages (because they're supported)
set your elements background-color to white (or whatever it needs to be)
This would somehow simulate your percentage borders. Here's an example of an element with 25% width side borders that uses this technique.
HTML used in the example
.faux-borders {
background-color: #f00;
padding: 1px 25%; /* set padding to simulate border */
}
.content {
background-color: #fff;
}
<div class="faux-borders">
<div class="content">
This is the element to have percentage borders.
</div>
</div>
Issue: You have to be aware that this will be much more complicated when your element has some complex background applied to it... Especially if that background is inherited from ancestor DOM hierarchy. But if your UI is simple enough, you can do it this way.
Scripted solution
#BoltClock mentioned scripted solution where you can programmaticaly calculate border width according to element size.
This is such an example with extremely simple script using jQuery.
var el = $(".content");
var w = el.width() / 4 | 0; // calculate & trim decimals
el.css("border-width", "1px " + w + "px");
.content { border: 1px solid #f00; }
<div class="content">
This is the element to have percentage borders.
</div>
But you have to be aware that you will have to adjust border width every time your container size changes (i.e. browser window resize). My first workaround with wrapper element seems much simpler because it will automatically adjust width in these situations.
The positive side of scripted solution is that it doesn't suffer from background problems mentioned in my previous non-scripted solution.
You can also use
border-left: 9vw solid #F5E5D6;
border-right: 9vw solid #F5E5D6;
OR
border: 9vw solid #F5E5D6;
So this is an older question, but for those still looking for an answer, the CSS property Box-Sizing is priceless here:
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box;
It means that you can set the width of the Div to a percentage, and any border you add to the div will be included within that percentage. So, for example, the following would add the 1px border to the inside of the width of the div:
div { box-sizing:border-box; width:50%; border-right:1px solid #000; }
If you'd like more info: http://css-tricks.com/box-sizing/
You can use em for percentage instead of pixels,
Example:
border:10PX dotted #c1a9ff; /* In Pixels */
border:0.75em dotted #c1a9ff; /* Exact same as above in Percentage */
Percentage values are not applicable to border-width in CSS. This is listed in the spec.
You will need to use JavaScript to calculate the percentage of the element's width or whatever length quantity you need, and apply the result in px or similar to the element's borders.
Modern browsers support vh and vw units, which are a percentage of the window viewport.
So you can have pure CSS borders as a percentage of the window size:
border: 5vw solid red;
Try this example and change window width; the border will change thickness as the window changes size. box-sizing: border-box; may be useful too.
Box Sizing
set the box sizing to border box box-sizing: border-box; and set the width to 100% and a fixed width for the border then add a min-width so for a small screen the border won't overtake the whole screen
You can make a custom border using a span. Make a span with a class (Specifying the direction in which the border is going) and an id:
<html>
<body>
<div class="mdiv">
<span class="VerticalBorder" id="Span1"></span>
<header class="mheader">
<span class="HorizontalBorder" id="Span2"></span>
</header>
</div>
</body>
</html>
Then, go to you CSS and set the class to position:absolute, height:100% (For Vertical Borders), width:100% (For Horizontal Borders), margin:0% and background-color:#000000;. Add everthing else that is necessary:
body{
margin:0%;
}
div.mdiv{
position:absolute;
width:100%;
height:100%;
top:0%;
left:0%;
margin:0%;
}
header.mheader{
position:absolute;
width:100%;
height:20%; /* You can set this to whatever. I will use 20 for easier calculations. You don't need a header. I'm using it to show you the difference. */
top:0%;
left:0%;
margin:0%;
}
span.HorizontalBorder{
position:absolute;
width:100%;
margin:0%;
background-color:#000000;
}
span.VerticalBorder{
position:absolute;
height:100%;
margin:0%;
background-color:#000000;
}
Then set the id that corresponds to class="VerticalBorder" to top:0%;, left:0%;, width:1%; (Since the width of the mdiv is equal to the width of the mheader at 100%, the width will be 100% of what you set it. If you set the width to 1% the border will be 1% of the window's width). Set the id that corresponds to the class="HorizontalBorder" to top:99% (Since it's in a header container the top refers to the position it is in according to the header. This + the height should add up to 100% if you want it to reach the bottom), left:0%; and height:1%(Since the height of the mdiv is 5 times greater than the mheader height [100% = 100, 20% = 20, 100/20 = 5], the height will be 20% of what you set it. If you set the height to 1% the border will be .2% of the window's height). Here is how it will look:
span#Span1{
top:0%;
left:0%;
width:.4%;
}
span#Span2{
top:99%;
left:0%;
width:1%;
}
DISCLAIMER: If you resize the window to a small enough size, the borders will disappear. A solution would be to cap of the size of the border if the window is resized to a certain point. Here is what I did:
window.addEventListener("load", Loaded);
function Loaded() {
window.addEventListener("resize", Resized);
function Resized() {
var WindowWidth = window.innerWidth;
var WindowHeight = window.innerHeight;
var Span1 = document.getElementById("Span1");
var Span2 = document.getElementById("Span2");
if (WindowWidth <= 800) {
Span1.style.width = .4;
}
if (WindowHeight <= 600) {
Span2.style.height = 1;
}
}
}
If you did everything right, it should look like how it is in this link: https://jsfiddle.net/umhgkvq8/12/
For some odd reason, the the border will disappear in jsfiddle but not if you launch it to a browser.
Take a look at calc() specification. Here is an example of usage:
border-right:1px solid;
border-left:1px solid;
width:calc(100% - 2px);

Setting height: 100% on my label element doesn't work

I tried to set height: 100%; in the label, but it didn't work. Why not?
.field label {
color:#3E3E3E;
font-weight:bold;
width:80px;
display:block;
float:left;
margin-top:5px;
margin-left:3px;
height:100%; /* <-- doesn't work */
}
.field {
display:block;
margin-bottom:9px;
background:none;
border:none;
}
<div class="field large">
<label>Textarea</label>
<textarea></textarea>
</div>
You have height set to 100% but 100% of what? It's always the parent of that element so what is the parent's height set to? If it's not set to anything then the browser has nothing to reference.
In this case I believe your div's height is being determined by the height of the tallest element within it: the text-area. (Reference) Perhaps you want to figure out how many pixels tall your text-area is (for instance this can be done with Firebug, or IE or Chrome's developer tools), and then set your label to that same height.
I'd also explicitly set that height for the text-area to be sure it's the same in all browsers.
The reason height: 100% isn't working as you expect is that the parent element has a height of auto. This results in your label also getting a computed height of auto.
<percentage>
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. 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'.(Reference)

Resources