CSS increase width using calc() does not affect parent container - html

Take a look at the following snippet. How can I increase the width of the red container with 10px?
Is there a way to increase the width of an element in CSS, still affecting the parent container? Or do I have to use a pseudo-element placeholder to accomplish this instead?
<div style="
background:blue;
display:inline-block;
height:50px">
<div style="
font-size:30px;
width:calc(100% + 20px);
background:red">
Inner container</div>
</div>
In the snippet above the blue container is not affected, and the red overflows.

Is there a way to increase width of an element by a certain amount, where the width of the element itself is not known until runtime?
You can only reliably do this using padding; however, padding will affect the layout of the element's contents, which may not be what you want. In your example, padding the child element will affect the layout of the text inside it; the content width is never really increased at all.
You can't change an element's content width by a definite amount when it is not known in advance and depends on external factors such as the amount of content it actually has, which is usually the case with floats, absolutely positioned elements, and inline-blocks. The closest you can get is an auto width, and that only has a meaningful effect on in-flow block boxes — which are none of the above — with respect to their parents, not their children.
In fact, the behavior that you see with calc(100% + 20px) is not governed by the spec, although it's as far as browsers generally go without falling into the cyclic dependency trap:
<percentage>
Specifies a percentage width. The percentage is calculated with respect to the width of the generated box's containing block. If the containing block's width depends on this element's width, then the resulting layout is undefined in CSS 2.1.
(calc() is CSS3, but the box model hasn't changed much from CSS2.1.)

If I understood correctly, you want to increase the child's initial width and add another 10px.
But when you set this property:
The width: 100% will always be relative to its parent, so if you add another 10px in relation to the 100% it will always be 10px bigger than its parent.
You may want to set just a min-width and a max-width instead of setting explicitly its width so that the child will be within some specified ranges, but to increase the width by 10px from the starting witdh using JUST CSS its not possible.
Note: Keep in min that using calc you have to add the according browser-engine property extension i.e:
-webkit-calc()
-moz-calc()
calc()
<div style="
background:blue;
display:inline-block;
height:50px">
<div style="
font-size:30px;
width: 100%;
background:red">
Inner container</div>
</div>
Hope this helps in some way, gl.

Related

Why the difference when using percentage vs px to define height?

I am trying to achieve the fade-in and fade-out effect as mentioned here Jquery replacewith fade/animate, but I would like to avoid content below it moving up and down. So I define a container with fixed height.
<div class="container">
<div id="foo"></div>
</div>
<h1>content below</h1>
If I set the height of container using px, "content below" will not move up and down during the animation.
.container {
height: 475px;
}
But if I set "height: 90%;", then it will. Why?
I prefer to use percentage, so how to in this case?
Percentages are relative and pixels are absolute. The computer knows what 400 pixels is. However when the measurement is relative, the final absolute output must have a relation with some other measurement. 400px is 50% of 800px.
If example you have no content in your <body>, the page collapses and it has no height.
If you set <body>'s height to 100%, it still has no height because its parent <html> has no height. However by setting <html>'s and <body>'s heights to 100% you will fill the viewport (html's "parent").
This applies to other block elements like divs.
Pixels are an absolute unit of measure. Percents are relative to some other value.
Each have valid use cases, neither is "better".
Reference : More detail here

Why setting padding on a descendant element reduces content box width?

I'm in a confusion since yesterday. Actually I have a markup as follows:
<div class="container">
<div class="child>
<div class="descendant">Content</div>
</div>
</div>
And CSS:
.container {
max-width: 500px;
min-width: 100px;
}
The .container element has some width between 100px to 500px according to my content and the child & descendant elements have some other content without any specific width or min/max-width.
What happens is that when I apply horizontal padding to .container, its content-box size remains as is & just padding is added to it. But whenever I apply horizontal padding to any of the child or descendant elements, they do not add padding to their size or the parent's size. Instead, their content-box size reduces and they accommodate padding.
I seriously can't get what is going on here. Can anyone explain me what's actually happening?
The width describes the content width, which you explicitly set to a maximum of 500px. So long as there is room, the content width of the container will be 500px. If you add padding to the container, that doesn't affect the content width because nothing else constrains it.
The descendants, on the other hand, have their width constrained by the container. If you add padding to a descendants, the width is reduced so the whole box can still fit inside teh container.
This is just normal box model behavior. Adding padding to an element that isn't bound by a parent element restricting it's size will grow outward to accommodate the new padding. But if an element is contained within a parent with a fixed width, and you add padding to the inner element, it can't grow outward and force the bounding parent to grow - it can only reduce it's content-box to make room for the padding.
If you want the outer and inner divs to behave consistently, you can add box-sizing: border-box; to .container and the padding will not cause the element to grow beyond the specified width/height.

Why does this flex item have its height limited?

I've stumbled across something that happens to my flex child items, illustrated in this JSFiddle.
This is the code:
<div style="position:absolute; top:10px; left:10px; background-color:yellow; height:50px; width:200px; display:flex; flex-direction:column;">
<div style="overflow:hidden;">inner div text<br>inner div text<br>inner div text<br>inner div text<br>inner div text</div>
</div>
<div style="position:absolute; top:10px; left:250px; background-color:green; height:50px; width:200px;">
<div style="overflow:hidden;">inner div text<br>inner div text<br>inner div text<br>inner div text<br>inner div text</div>
</div>
<div style="position:absolute; top:200px; left:100px; border:1px solid black; height:300px; width:300px; overflow:hidden;">
<div style="overflow:hidden;">
Why does the inner div on the yellow left have its height limited to that of its container, but not the inner div on the green right? As far as I can tell there are 4 things combined that trigger this:<br>1) the container has position:absolute<br>
2) the container has a fixed height/width<br>
3) the container is flexbox<br>
4) the flex item has overflow:hidden<br><br>But I can't find anything exactly in the flexbox spec to cause this behaviour. Why is it happening?
</div>
</div>
Basically, the flex item inside a flexbox container with a fixed height is getting its height limited to that of the flexbox container when overflow:hidden is set. On the other hand, an equivalent div inside a fixed height non-flex container just expands to the size of its content.
Where in the flexbox spec is this behaviour specified? Is it just a browser quirk? That seems unlikely as it happens in Firefox, Chrome, and IE. Assuming it is well-defined flexbox behaviour, I'd like to know exactly how and when it is triggered. Also note that when you remove overflow:hidden from the child (not the container), its height stops getting limited.
OK, I think I figured out what's happening.
Up until flexbox, there was no way to cause an element to be smaller than the size of its content without explicitly settings its width/height. With flexbox, there is a second way.
Para 9.11 of the flexbox spec talks about how to calculate a flex-item's cross size. Basically if the flex item has align-self: stretch set (which in my example it does), it will try to fill the container's flex line (in my example the vertical line, ie. height). This is implicitly setting the flex item's height, without explicitly using the height property. The container itself needs to have a definite height, too, to be handed down to the flex item (in my example the container's height is explicitly set through the height CSS attribute, which I guess ultimately needs to be done at some point in the chain).
However, two conditions need to be met: the browser needs to want to resize the item, and the item needs to be resizable.
To make the browser want to resize the item, it needs to be a flex item that meets the conditions mentioned above for its cross size (which ultimately may determine its width or height) to be calculated by the browser with relation to its container's cross size.
To make the item resizable in this context, it needs to both not have flex-shrink set to 0 (note that flex:none is shorthand for setting flex-shrink to 0, amongst other things), and have overflow:hidden set (presumably giving the browser "permission" to resize the flex item such that its content will be larger than it, and get hidden). Only then will the browser actually resize the flex item itself.
This is notably different behaviour to what happens outside the flexbox model, where the child of a fixed height/width container may have it content clipped, but it will retain the necessary size to hold its content. Part of the content will merely be hidden. Here, the flex item really is being (potentially) resized to be smaller than its content, which has quite important implications (particularly if you want a child element to have a scrollbar for its content).

CSS height property doesn`t work on iframe? [duplicate]

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.

Difference between width:auto and width:100% - what is it 100% of? (CSS)

Why does setting an element to be position:fixed change its width? I know that HTML elements by default span the entire width of the browser window, but when I set the position on my header to be fixed, the <div> shrinks to zero width. Why is this?
Trying width:auto does not fix it, the <div> still has zero width!
This example is taken from Code Academy "Build a Resume" project at the end of their Web Fundamentals course.
I have an HTML file like so:
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
<title></title>
</head>
<body>
<div id="header"></div>
<div class="left"></div>
<div class="right"></div>
<div id="footer"></div>
</body>
</html>
and a CSS file like so:
div {
border: 5px solid red;
border-radius: 5px;
}
#header{
height:30px;
background-color:orange;
z-index:1;
}
#footer{
height:30px;
background-color:teal;
clear:both;
}
.left{
height:300px;
width:200px;
float:left;
}
.right{
height:300px;
width:200px;
float:right;
}
UPDATE: I noticed that setting width:100% does keep the width all the way across the browser window. What is going on here? I've read Why does fixed positioning alter the width of an element? but am not sure how that applies here.
Edit: Thought I would move this up from the comments and try answering it here, to give more direction on where I'm confused:
"Yes, it seems like "Whereas the position and dimensions of an element with position:absolute are relative to its containing block, the position and dimensions of an element with position:fixed are always relative to the initial containing block" is the key part. So I see that position:fixed will set the dimensions of my relative to the viewport, but isn't the viewport the whole browser window? So why does its size collapse to zero? And beyond that, why does width:auto not fix it but width:100% does make it span the whole horizontal length again?"
width:auto is different from width:100%. width:auto will expand the width of the element to all horizontal space within its containing block. Since the space is on the inside of the containing block it doesn't count borders/padding/margins.
width:100% does what width:auto does and adds the width of the borders/padding/margins of the containing element. difference between width auto and width 100 percent provides a good visual demonstration.
So, when I set width:auto on my position:fixed element, and the position:fixed shrink-wrapped the element's width to be that of its content (which was nothing), then the width automatically adjusted to be that of the containing element, which in this case was _________ (what? and why did it have a width of zero?).
When I set it to be width:100% then it includes the padding/margins/border of _________ (what? and why did it expand to cover the whole page horizontally?).
The reason is because both fixed and absolute positioning take the element out of the flow of the document. The residual effect of this is that, unless explicitly told otherwise, the element will now grow/shrink according to the size of its content rather than the size of its parent.
As you've already discovered, a simple fix is to give it a width of 100 percent:
.fixed-element{
position:fixed;
width:100%
}
To address the issue of the quote on fixed positioning:
Whereas the position and dimensions of an element with position:absolute are relative to its containing block, the position and dimensions of an element with position:fixed are always relative to the initial containing block. This is normally the viewport: the browser window or the paper’s page box.
I actually find it to be quite poorly worded. It's not meant to say that the dimensions will grow to the size of the viewport. Instead it's trying to distinguish the specific differences between absolute and fixed positioning. More thoroughly put: the dimensions/size of the fixed element will always be relative to the initial element. Whereas the dimensions/size of the absolute element will be relative to the containing element. That doesn't explicitly mean that it will actually take 100% of the viewport by default...
This is the default behavior.
Read http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Specifying_dimensions
Absolutely positioned elements will shrink-wrap to fit their contents
unless you specify their dimensions. You can specify the width by
setting the left and right properties, or by setting the width
property. You can specify the height by setting the top and bottom
properties, or by setting the height property.