I've been doing CSS for a while now but couldn't figure out what's going here. Feeling really dumb :) Could you explain the behaviour?
.parent {
display:inline-block;
}
.child {
border: 2px solid red;
padding: 20px; /* this works as expected */
padding: 20%;
box-sizing: border-box; /* makes no difference */
}
<div class="parent">
<div class="child">CSSisAwesome</div>
</div>
You are facing a cyclic calculation due to the use of percentage value. The parent is an inline-block element so its width is defined by its content and that same content is using a percentage value so the content need a reference for that percentage which is the width of the parent. You have a cycle.
In such case, the browser will first ignore the padding to define the parent width and then calculate the padding BUT we don't get to calculate the parent width again because will have an infinite loop.
Check this:
.parent {
display: inline-block;
}
.child {
border: 2px solid red;
}
<div class="parent">
<div class="child">CSSisAwesome</div>
</div>
<br>
<br>
<div class="parent">
<div class="child" style="padding: 20%;">CSSisAwesome</div>
</div>
Note how in both cases, the width of the parent is the same and that width is defined by the content. The padding is added later and create an overflow.
You can find mode detail in the Specification
Sometimes the size of a percentage-sized box’s containing block depends on the intrinsic size contribution of the box itself, creating a cyclic dependency.
Related questions:
Why does percentage padding break my flex item?
CSS Grid - unnecessary word break
How percentage truly works compared to other units in different situations
As seen in this CSSTricks article, padding using percentage units is in relation to the parent container, not the content within the element. The 20% padding you're setting in your code snippet is in relation to the .parent div's dimensions, not in relation to the content within the .child div.
If you are using % as a unit, Parent should have fixed width and height
Related
This question already has an answer here:
How does padding percentage work?
(1 answer)
Closed 3 years ago.
I wonder if this is very stupid to ask but I am asking anyway because I haven't found the answer anywhere to my satisfaction yet.
I am trying to make a responsive page where I want to define padding of a div called content which contains another div as "text" and is sitting inside another div element called container which has predefined height and width and position: relative. Now the problem is that I defined padding: 45% 45%; and it works very well on the width by taking the root value of the parent container but it flush outside the parent when it comes to height
.container
{
box-sizing: border-box;
position: relative;
border: 1px;
height: 100px;
width: 600px;
margin:0 auto;
}
.content{
background-color: skyblue;
padding: 43% 43%;
}
#textlogo {
font-size: 4em;
}
<div class="container">
<div class="content">
<div id="textlogo">Text</div>
</div> </div>
Your issue seems to be with the box-sizing,
Set box-sizing: padding-box, this way the browse calculates the total width of the element together with the padding and it will clear off any overlay. Your padding is also a bit high and it's causing the problem.
You must note that the flushing is likely caused by your font-size: 4em. This is a large font and it will force the content div to extend in order to accommodate it #textlogo content..
You should very rarely use the padding property in CSS. Going all the way back to Internet Explorer 4 margin worked correctly.
Use margin on the child element instead of padding on the parent. If you use padding on the parent it automatically effects all the child elements. You can "blanket" apply margin to all child elements by using #parent > div selector in example and then cascade secondary margin for individual elements you need to adjust.
You should use padding if there are no child elements or you're dealing with bugs in rendering engines or the standards themselves (e.g. when implied "logic" is used instead of direct (actual) logic).
As Mosia mentioned there is the box-sizing property and while support at this point is pretty much universal if you want to learn CSS the way it was originally intended I wouldn't recommend that shortcut as it will rob you from a true understanding of the code.
This question already has answers here:
Percentage Height HTML 5/CSS
(7 answers)
Closed 6 years ago.
How come a percentage value for height doesn’t work but a percentage value for width does?
For example:
<div id="working"></div>
<div id="not-working"></div>
#working{
width:80%;
height:140px;
background:orange;
}
#not-working{
width:80%;
height:30%;
background:green;
}
The width of #working ends up being 80% of the viewport, but the height of #not-working ends up being 0.
The height of a block element defaults to the height of the block's content. So, given something like this:
<div id="outer">
<div id="inner">
<p>Where is pancakes house?</p>
</div>
</div>
#inner will grow to be tall enough to contain the paragraph and #outer will grow to be tall enough to contain #inner.
When you specify the height or width as a percentage, that's a percentage with respect to the element's parent. In the case of width, all block elements are, unless specified otherwise, as wide as their parent all the way back up to <html>; so, the width of a block element is independent of its content and saying width: 50% yields a well defined number of pixels.
However, the height of a block element depends on its content unless you specify a specific height. So there is feedback between the parent and child where height is concerned and saying height: 50% doesn't yield a well defined value unless you break the feedback loop by giving the parent element a specific height.
A percentage value in a height property has a little complication, and the width and height properties actually behave differently to each other. Let me take you on a tour through the specs.
height property:
Let's have a look at what CSS Snapshot 2010 spec says about 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'. A percentage height on the root element is relative to the initial containing block. Note: For absolutely positioned elements whose containing block is based on a block-level element, the percentage is calculated with respect to the height of the padding box of that element.
OK, let's take that apart step by step:
The percentage is calculated with respect to the height of the generated box's containing block.
What's a containing block? It's a bit complicated, but for a normal element in the default static position, it's:
the nearest block container ancestor box
or in English, its parent box. (It's well worth knowing what it would be for fixed and absolute positions as well, but I'm ignoring that to keep this answer short.)
So take these two examples:
<div id="a" style="width: 100px; height: 200px; background-color: orange">
<div id="aa" style="width: 100px; height: 50%; background-color: blue"></div>
</div>
<div id="b" style="width: 100px; background-color: orange">
<div id="bb" style="width: 100px; height: 50%; background-color: blue"></div>
</div>
In this example, the containing block of #aa is #a, and so on for #b and #bb. So far, so good.
The next sentence of the spec for height is the complication I mentioned in the introduction to this answer:
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'.
Aha! Whether the height of the containing block has been specified explicitly matters!
50% of height:200px is 100px in the case of #aa
But 50% of height:auto is auto, which is 0px in the case of #bb since there is no content for auto to expand to
As the spec says, it also matters whether the containing block has been absolutely positioned or not, but let's move on to width.
width property:
So does it work the same way for width? Let's take a look at the spec:
The percentage is calculated with respect to the width of the generated box's containing block.
Take a look at these familiar examples, tweaked from the previous to vary width instead of height:
<div id="c" style="width: 200px; height: 100px; background-color: orange">
<div id="cc" style="width: 50%; height: 100px; background-color: blue"></div>
</div>
<div id="d" style=" height: 100px; background-color: orange">
<div id="dd" style="width: 50%; height: 100px; background-color: blue"></div>
</div>
50% of width:200px is 100px in the case of #cc
50% of width:auto is 50% of whatever width:auto ends up being, unlike height, there is no special rule that treats this case differently.
Now, here's the tricky bit: auto means different things, depending partly on whether its been specified for width or height! For height, it just meant the height needed to fit the contents*, but for width, auto is actually more complicated. You can see from the code snippet that's in this case it ended up being the width of the viewport.
What does the spec say about the auto value for width?
The width depends on the values of other properties. See the sections below.
Wahey, that's not helpful. To save you the trouble, I've found you the relevant section to our use-case, titled "calculating widths and margins", subtitled "block-level, non-replaced elements in normal flow":
The following constraints must hold among the used values of the other properties:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
OK, so width plus the relevant margin, border and padding borders must all add up to the width of the containing block (not descendents the way height works). Just one more spec sentence:
If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.
Aha! So in this case, 50% of width:auto is 50% of the viewport. Hopefully everything finally makes sense now!
Footnotes
* At least, as far it matters in this case. spec All right, everything only kind of makes sense now.
I think you just need to give it a parent container... even if that container's height is defined in percentage.
This seams to work just fine: JSFiddle
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.wrapper {
width: 100%;
height: 100%;
}
.container {
width: 100%;
height: 50%;
}
You need to give it a container with a height. width uses the viewport as the default width
Another option is to add style to div
<div style="position: absolute; height:somePercentage%; overflow:auto(or other overflow value)">
//to be scrolled
</div>
And it means that an element is positioned relative to the nearest positioned ancestor.
Without content, the height has no value to calculate the percentage of. The width, however, will take the percentage from the DOM, if no parent is specified. (Using your example) Placing the second div inside the first div, would have rendered a result...example below...
<div id="working">
<div id="not-working"></div>
</div>
The second div would be 30% of the first div's height.
Children element not stretch parent container.
My code:
html:
<div class='window'>
<div class='wrapper'>
<div class='short'>short</div>
<div class='long'>long</div>
</div>
</div>
css:
.window{
width: 500px;
height: 100px;
overflow: auto;
background: gray;
}
.wrapper{
background: pink;
border: 1px solid red;
}
.long{
width: 700px;
background: beige;
}
example
I want .long stretch his parent .wrapper.
.wrapper width must be the same as .long (700px).
I can reach this by setting float: left to .wrapper.
But what happens here i don't understand, why it helps? What is the mechanism of such behavior? I need explanation, with links to w3c documentation.
What else can i do to extend .wrapper width?
By default, the .wrapper div is inheriting the fixed width you set on .window. You can float the .wrapper and set it's width to auto so the width expands without restriction to the parent.
CSS:
.wrapper {
float: left;
width: auto;
}
Example: http://jsfiddle.net/WTGAc/3/
Theory:
By default, the dimensions of wrapper are constained to the dimensions placed on it's parent, .window.
Floated elements still live within the parameters defined by their
parent element, ie the width available and horizontal position. They
still interact with text and other elements inside that parent element
(or other following elements). In that respect, they are quite
different from absolutely positioned elements, which are removed from
the document flow and don't interact with other elements ... but even
then, if they have a positioned ancestor then they are restricted by
the envelope of that ancestor and will use that as the basis for
calculating size and dimension (although they can still be made to
extend or exist outside that positioned ancestor).
Source of Quote
Since the element is floated and set outside of the normal document flow, it can now expand to the true width of the parent, instead of the fixed width initially defined.
Widths and the CSS Visual Formatting Model
In you example, you have the following:
<div class='window'>
<div class='wrapper'>
<div class='short'>short</div>
<div class='long'>long</div>
</div>
</div>
In the simplest case, .window is the containing block with a fixed width (500px). The child element .wrapper inherits the width from .window. The .long element has a width of 700px and it will trigger an overflow condition. Since .window has overflow: auto declared, the .window element will generate a horizontal scroll bar. Note that by using overflow: auto, .window establishes a new block formatting context, which is why the horizontal scroll bar appears on .window instead of the viewport/root element.
When you float .wrapper to the left, the .wrapper element defines an additional block formatting context. A new block formatting context will ignore the width inherited from its containing block and computes a new width sufficient to enclose the content (shrink-to-fit), which is why the pink background from .wrapper now extends the entire 700px in width.
You can trigger the same effect by adding position: relative to .window and position: absolute to .wrapper. However, this works because you set the height to .window, otherwise, the .window height would compute to zero since absolute elements are out of the flow and (unlike floats) will no longer affect how the .window content is laid out (not contribute to the height in this case).
As an aside, instead of using float: left on .wrapper, you can also try overflow: auto which will also establish a new block formatting context but this time the scrolling bar appears on .wrapper instead of .window.
The relevant documentation from w3.org is:
10 Visual formatting model details
10.3 Calculating widths and margins
10.3.5 Floating, non-replaced elements
Link: http://www.w3.org/TR/CSS2/visudet.html#float-width
I want to equal two divs height when a div height large
example :
<div style="float:left;padding:2px;background:red;">B</div>
<div style="float:left;padding:2px;background:green;">A<br />C<br />D</div>
<div style="clear:both;"></div>
the Div 2 height larger then div one
I may have a possible solution for you:
http://jsfiddle.net/adaz/wRcWj/1/
Well, it'll probably work on ie7+ so I'm not sure if that's good enough for you.
Brief description:
1) Set position relative to the container and self-clear it (I've used overflow: hidden but you can also use clearfix).
2) Float one of the divs inside so the container will expand depending on content inside.
3) Set position absolute to one of your divs, and give it top and bottom position 0px, this will make sure that it has 100% height.
Cons:
- Lack of IE6 support
- You need to chose which div will always have less content and then position in absolute
Hope it helps!
This is typically the behavior of a table, so you can do this with display: table-cell. I based an example on Adaz's : http://jsfiddle.net/L2uX4/
Wrap the two div's whose height you are trying to equalize in a container div, i.e.
<div id="container">
<div class="column">A<br/>B</div>
<div class="column">C</div>
</div>
Set an explicit height on the container and set height=100% on the columns:
div#container {
float: left;
height: 10em;
}
div.column {
height: 100%;
background-color: red;
}
Suppose I have this HTML structure:
<div class="a">
<div class="floated-left">...</div>
<div class="floated-left">...</div>
</div>
I have noticed that if I don't set overflow:hidden to .a, then the <div class="a"> does not occupy any vertical size. For example, if I set its background to red, it is not visible at all. Inspecting it with FireBug shows that it's there but of almost no vertical size.
To fix this, I found that I have to set overflow:hidden to .a. Then the first <div> goes over all its content.
Here is a real example:
<html>
<head>
<style>
.a { background-color: red; }
.b { background-color: red; overflow: hidden }
.floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
</style>
</head>
<body>
<p>div with class a, that doesn't overflow:hidden:</p>
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
</div>
<div style="clear:both"></div>
<p>div with class b, that does overflow:hidden:</p>
<div class="b">
<div class="floated-left">Hi,</div>
<div class="floated-left">Dad!</div>
</div>
</body>
</html>
Notice how Hi, Mom! does not get red background (no overflow:hidden), while Hi, Dad! does get red background (has overflow:hidden).
Can anyone explain this behaviour?
Here is screenshot of the example:
Thanks, Boda Cydo.
When you float elements they are taken out of the document flow. Among other things, this means that they have no impact on the dimensions of the parent element (although its width will determine where the floats are positioned on the horizontal axis). They do however impact positioning of siblings within the container depending on whether those sibling are inline or block level elements and whether they have width or not.
In order to make the height of the floats impact the height of the container you must have an element after them that clears them. However, what you are seeing here is actually a part of the CSS standard that you can use to clear floats without additional, non-semantic markup. The only issue is this behavior can vary slightly in older browsers and their css implementations. This effect is present with both overflow auto and overflow hidden but does not present with overflow visible. In IE < 6 you must have a width set on the containing element for it to work.
Hi, Mom does not get any background because the background comes from the a div, which is height 0 (or near 0). The inner divs are actually overflowing its bounds (which is what floats do by default).
The thing to remember with floats is that they don't have inherent height (when it comes to layout and determining the parent's height). Inline content simply flows around them. So without overflow: hidden the parent div has no height. No height means no background. The floats are still rendered but they go beyond the bounds of the parent div ie the content in the floats is outside the parent div.
Floated elements don't occupy any vertical space for clearing, there are a few ways to fix this, something like:
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
<br style="clear: left;" />
</div>
Would clear after, and make the outer div have a vertical height. Set a border: solid 1px red; on .a to see this in action.
Alternative CSS only solution:
.a:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
Per the spec for CSS basic box model:
Margins of a floated box do not
collapse with any other margins.
Margins of a box with ‘overflow’ other
than ‘visible’ do not collapse with
its children's margins.
By providing it the "overflow" property explicitly you have allowed the children to fit into this model, thus the b div no longer has bounds attached to its children. If you apply visible or inherit (which the parent of b is visible by default), the bounds return and the children divs define the margins.
http://www.w3.org/TR/css3-box/ (RE: Example X)