What are the problems of my box size determination? - css

<html>
<body>
<style>
#div11 {
height: 100%;
}
</style>
<div id="div1">
<div id="div11"></div>
</div>
</body>
</html>
In above case I think heights of div1 and div11 both are 0. Below is my inference.
There is a cyclic dependence of box size between div1 and div11: Generated box b1 of div1 is containing block of generated box b11 of div11. b1's height is initial value auto. So b1's height depends on b11's. b11's height is specified as a percentage value which depends on its containing block that is b1.
The closed dependence is resolved in below way. Section 10.5 of CSS 2.1 prescribes: " 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 (of the element's height) computes to 'auto' ", so b11's height computes to auto.
After resolving closed dependence box size is determined in such way: b11 has not content so its height is 0 according to rule 4 in section 10.6.3 of the specification. Then b1's auto height computes to 0.
But the actual rendering in browser is different. What are the problems of my inference? Do I misunderstand some rules or ignore some semantics in the specification? Thank for your help very much.

You are quoting the correct part of the specification. The reason that's not what you experience is because by not specifying a DOCTYPE. you've put the browser in quirks mode. So the browser is behaving quirkily different from the CSS standand, and what you have to look at instead is the Quirks mode standard.
In this case the relevant quirk is 3.5. The percentage height calculation quirk. Basically, for your example, the algorithm loops until it hits the initial containing block, and then sets div11 to 100% of the height of that, i.e. it takes the height of the viewport.

Related

CSS gradient background-size in Chrome / IE 11

It seems that Chrome is not following the spec for interpreting the background-size property in CSS3.
Consider the following markup
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testing</title>
<style type="text/css">
html {height: 100%;}
body {height: 100%;}
div {
height: 100%;
background-image: linear-gradient(to bottom right,red,green,blue);
background-size: 30%;
}
</style>
</head>
<body>
<div/>
</body>
</html>
This should place a single div which fills the view and is decorated with a rainbow gradient. My understanding is that this gradient should be 30% of the view in width and 100% in height.
The specification for the background-size property states
The first value gives the width of the corresponding image, the second value its height. If only one value is given the second is assumed to be auto.
Thus, in this case, it is as if I had declared background-size: 30% auto.
and
An auto value for one dimension is resolved by using the image’s intrinsic ratio and the size of the other dimension, or failing that, using the image’s intrinsic size, or failing that, treating it as 100%.
and the specification for gradients states
The term intrinsic dimensions refers to the set of the intrinsic height, intrinsic width, and intrinsic aspect ratio (the ratio between the width and height), each of which may or may not exist for a given object... CSS gradients, defined in this specification, are an example of an object with no intrinsic dimensions at all.
Thus, auto should default to 100%, and it is as if I had declared background-size: 30% 100%. Currently, declaring this specifically is how I am working around this.
This is exactly how Firefox (56.0.1) seems to display the page.
However, Chrome (62.0.3202.62) does not. It gets the width right (I may have cut a little of the edge off in the screen capture, but the rightmost repetition looks like about 10% as it should), but seems to interpret the height as also being 30%. IE 11 looks exactly the same as the Chrome display.
So, my questions:
Am I interpreting the specification correctly? The newest edition (4th) of CSS: The Definitive Guide seems to support my interpretation as well as the page at developer.mozilla.org (which suggests that this property has changed at some point).
If so, is this a known bug in Chrome which is being worked on/fixed? caniuse.com does not list any known issues with Chrome.
If not, how do I go about reporting a bug in Chrome (as there will be no IE 12, it obviously can't be fixed there, but may or may not work in Edge)?
It seems that there is a bug report filed as Issue 711489 at the chromium bug page. There is also a bug report filed for this with WebKit as Bug 170834 for the same problem. Both reports contain a test case for the correct behavior according to the spec.

Resizing a container to a percentage of its content

Is there a way to resize a container to a percentage of its own content?
I'm having a tricky issue relating to scaled content. Doing a transform: scale(...) on something works as far as having it display as I'd like, but unfortunately, the content still has the same effective size of the original content. This is problematic when content needs to flow below the scaled content without vertical spacing.
For example, given this HTML:
<div class="scaled-preview">
<div class="content">...</div>
</div>
<div class="stuff-below">Stuff below</div>
...and this CSS:
.content {
transform: scale(0.4);
width: 250%; /* Inverse of the scale */
}
....stuff-below is spaced below it as though it was not scaled.
You can see this in this JSFiddle.
The size of the content being scaled is unknown, but the scale factor is known. Is there a way I can have .scaled-preview set to a height that is a percentage of its own content?
This might not be quite the solution you're looking for, but it may solve your problem in an unusual way.
By the time the browser is calculating transform information, the layout is sadly solidified, so I wasn't able to think of a way to have the content height reflect the transformed height. So, I tried working off of font-size instead. It transitions just as well, and you can even size elements off of it using em values. The only downside is, I had to specify a particular width: xxem value so that the varying font-size would not cause line breaks in the middle of the transition.
https://jsfiddle.net/07c7s83y/

CSS - "The sum of the horizontal components of a block-level element box always equals the width of the parent?"

I am reading CSS The Definitive Guide by Eric Meyer. On page 162, it says the following:
Almost as simple is the rule that says that the sum of the horizontal components of a block-level element box in the normal flow always equals the width of the parent.
I find a similar passage in the W3C specification:
The horizontal position and size of a non-floating, block-level element is determined by seven properties: 'margin-left', 'border-left', 'padding-left', 'width', 'padding-right', 'border-right' and 'margin-right'. The sum of these seven is always equal to the 'width' of the parent element.
However, I can think of a very simple case where the above rule does not hold true.
# HTML
<div><p>This is a paragraph.</p></div>
# CSS
div { width: 200px; }
p { width: 300px; }
Obviously I could set overflow to contain the p element. However I just want to know am I interpreting the rule incorrectly?
You shouldn't read the old specifications of CSS1, except for curiosity, as you can read in the red box on the page you linked. CSS2.1 defines well this situation: in paragraph 10.3.3 you can read that such configuration is called over-constrained, and one horizontal margin is ignored and set to a value in order to make the equality true. The right one will be choose if the writing mode is left to right, otherwise it'll be the left one.
I think it means that the "sub element at 100% always equals the width of the parent". Obviously if you set the width to anything smaller/bigger it will differ. But it inherits the same width unless specifically set.

How are the widths of nested absolutely positioned elements determined?

Example:
<style>
div {
position:absolute; left:auto; right:auto; width:auto;
margin:0; padding:0; border:0;
}
</style>
<div id="containingBlock">
foo
<div id="inner">this is my text</div>
</div>
To determine the widths of both divs, we need the shrink-to-fit algorithm in http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width *
Let's start with #inner:
get the preferred minimum width
this
is
my
text
|----| preferred minimum width
get the preferred width
this is my text
|---------------| preferred width
compare both to available width:
computed width = min(max(preferred minimum width, available width),
preferred width)
Easy. But what is available width? Since we got no margins/paddings/borders, it's simply the width of containingBlock. But now we get an infinite loop, since the same algorithm applies again:
get the preferred minimum width of containingBlock
foo
+-------+
| inner |
+-------+
|--?????--| preferred minimum width
In other words: to get the width of inner, we must know the width of containingBlock and vice versa.
In reality, it looks like browsers just assume available width = 0 in this case: http://jsfiddle.net/pxvJJ/6/.
But this is not covered by the specs, or am I missing something obvious?
* (note that this spec has not yet been superseded by CSS3)
If we read carefully through the specs, we'll find that
CSS 2.1 does not define the exact [shrink-to-fit] algorithm.
It's supposed to be
similar to calculating the width of a table cell using the automatic table layout algorithm
which, in turn, is implementation-dependent.
So, the above example shows that excluding #inner from the calculation of containingBlock's preferred minimum width may be a good idea when implementing a straight-forward algorithm, and we'd end up with this:
|---| preferred minimum width
foo
+-------+
| inner |
+-------+
|--?????--|
which is probably what browsers do.
That being said, the question is: Which elements do actually contribute to containingBlock's preferred minimum width?
Let's see what happens if #inner has position:static; width: auto. This case is even harder. Again, the specs give the constraint
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
with no shrink-to-fit allowed this time. And, again, it cannot be solved. Or can it? Funny enough, it can! Let's see what actually happens: http://jsfiddle.net/pxvJJ/12/
Apparently, the statically positioned divs are treated differently. So I suppose the algorithm to determine width of containing block goes like this:
determine the preferred width of all contained block boxes in normal flow.
set width of containing block = maximum of those preferred widths
calculate the width of all contained boxes, now that width of containing block is known
I am still confused as to why (all) browsers do this. There seems to be no reason for treating absolutely positioned elements differently in this regard.

If div has a line-height of 0 and its only child, span, has line-height:0, where's the div's height coming from?

Here's my doubt. I've got a parent div with a child which is a span. Both have line-height set to 0. The span has font-size set to many many pixels (198px).
The problem: the div gets a height. But, from what, if it should come from the spans line-height, which is 0?
I set up a tinkerbin. Check it out if if you're interested.
http://tinkerbin.com/0oCT7PRf
This happens at least in firefox and chrome, so this is almost definitely a standardized behavior.
Note!
This is a css behavior doubt. I'm interested in knowing what's happening, not on "fixing" an "issue".
Thanks in advance.
The text still has a size; the letter 'F' is expanding the div to fit.
Update from the spec:
On a block container element whose content is composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element.
http://www.w3.org/TR/CSS21/visudet.html#line-height
So the height of the box really is coming from the font-size, as the line-height is only defined as a minimum of 0, but not explicitly 0.
Yes, the is taking the height of its inner element. If you want it to correctly take its defined height/line height, you have to set it to behave as a block element ( display:block;)
Also, when hiding elements on IE using line height / height :0, IE won't collapse the element unless font-size is set to 0 as well.
The answer I've comeup with:
First facts backed by the spec:
When you have a line height greater than the font-size - what you usually see - it's pretty easy. Take the line height, subtract the font-size, divide it by 2. Apply the result to both the top and the bottom of the "glyphs box", and that's it. So if your font-size is 14px, and your line height 16px:
16px - 14px = 2px
2px / 2 = 1px
Add 1px above the "glyphs box", add 1px below it. The box gets a height of 16px, and that as expected becomes the height of the parent container (assuming, as in the case, that there's only one line-box in it).
When the line-height is less than the font-size (our case) the thing gets trickier. Lets use the same formula for a font-size of 54px and a line-height of 0.
0-154px = -154px (the spec allows a negative value here so we're alright)
-154px / 2 = -77px
So, our font has a size of 154px... and here's something else you need to know. A font has both a distance from the baseline to it's top and from the baseline to it's bottom. Pretty simple. The spec calls the first one height(A) and the second one depth(D). So A+D = distance from top to bottom.
Now here's what I think is happening in the case I presented in the question. This is what I concluded from "my fiddling" and not from the spec (since I couldn't find it there).
Let's continue with our formula.
We got -77px from dividing the result of the difference between the line-height and the font-size.
Our font-size is 154px.
Now we've got to add -77px to the top, and -77px to the bottom. Adding a negative is subtracting - so we're in fact subtracting 77px.
This is easier explained with a drawing.
So yeah, that's where I believe the height is coming from. It's at least related to it.

Resources