HTML/CSS: Why is body not stretching to its contents? - html

Take this trivial example and open it:
<html>
<body style="background-image:url(http://upload.wikimedia.org/wikipedia/commons/2/21/Mandel_zoom_00_mandelbrot_set.jpg);background-repeat: no-repeat; background-position: top center;">
<div style="width: 8000px; border: 3px solid red;">Demo</div>
</body>
</html>
The page is made so that the body has a top-centered background picture and a containing element which overflows window boundaries so there is horizontal scrolling (if you have a monitor wider than 8000px then you're really cool, please make the window smaller and refresh).
The problem is that for some reason the <body> doesn't stretch to contain the <div>. It just stays the same width as the viewport and the <div> overflows it. This in turn causes the background to be centered at the wrong place and crops it to the size of the viewport. Quite ugly when you scroll to the right.
I've already found a solution to this problem, but I'm wondering WHY this is so? It seems to be consistent across browsers too. But in my opinion this is quite counter-intuitive and basically plain wrong. The container element should be big enough to contain it's children - unless they are absolutely positioned of course in which case they don't participate in the layout calculations.

Blocks simply do not stretch horizontally to accomodate their child content, at all; never have.(1) That's something that only happens in the vertical axis.(2) Logically, both dimensions can't be stretchy; one has to be fixed (wrt parent). In CSS, the width of a block element in normal flow is derived solely from the parent (minus paddings, margins, borders), and then the height follows on from that, seeing how much content you can fit in the block's width and flowing it.
The background image can appear in a confusing place that misleads you to what is actually happening because of this quirk of CSS:
For documents whose root element is an HTML "HTML" element or an XHTML "html" element that has computed values of 'transparent' for 'background-color' and 'none' for 'background-image', user agents must instead use the computed value of the background properties from that element's first HTML "BODY" element or XHTML "body" element child when painting backgrounds for the canvas, and must not paint a background for that child element. Such backgrounds must also be anchored at the same point as they would be if they were painted only for the root element.
This is a nasty hack put in place because people were used to putting backgrounds on ‘body’ and having it fill the viewport, even though the <body> element itself does not represent the viewport.
(1) except in a few special cases, like float and position: absolute elements without a declared width.
(2) unless you deliberately stop that by setting height/overflow.

The exception to expanding is the viewport. Nothing expands the viewport unless its direct or attached contents require it -- this includes that div and table elements (eg, display: table-cell on body) -- but not a block container.

Related

Set the body width to 100% of document's

So i have:
<body style="border:1px solid red;width:100%;">
<div style="position:absolute;left:2000px;">
1
</div>
<body>
Is there any way to make body width to be 100% of document (including "scrolling space") instead of 100% of inner window width in this case?
I mean i need the result as if i applied "width:2000px;" to the body, but without knowing this number.
I know, that it will take one line of code in js and still i wonder, if i can do this with pure css.
To clarify:
When i write "width:100%;" i expect, that body width will stretch up to 2000px (to include that absolutely positioned div), but it stretches only to 1024px (browser window width).
There is a logical puzzle with this layout.
<body style="background:red;width:100%;">
<div style="position:absolute;left:2000px;">
1
</div>
<body>
Because the inner div is positioned absolutely, it is out of the document flow, and therefore, the parent block container, <body>, cannot compute a width based on the absolutely positioned child element.
By assigning a percentage width of 100% to <body>, the width is actually being computed based on the width of the root element, in this case, <html>, which may in turn, inherit its height from the viewport.
This effect cannot be achieved by CSS alone.
If you need the inner div to be absolutely positioned, then you will need some JavaScript/jQuery functionality to determine the width of <body> based on some custom rules that you want to specify.
The problem is position: absolute what you can do is wrapping your div inside another one like this:
<body style="border:1px solid red;width:100%;">
<div style="width:2000px;">
<div style="position:absolute;left:2000px;">
1
</div>
</div>
<body>
because when you make any element absolute is not belongs to is parent anymore and it becomes separate element in document (in document flow). If this answer is not what you want, tell me what you want exactly to do (what is your design decision) then I can give you alternative designs to solve your problem.
The width property doesn't have anything to do with the objects' child elements. Additionally, by absolute positioning that element, it actually causes the parent to COMPLETELY ignore any size parameters of that particular child element. But even with a relatively positioned object with an offset, only the initial position of the element would have an impact on its parent and not the offset location of it.
Setting width to 100% will cause it to fill 100% of its parent container, in this case the <html> element. And by explicitly stating a width, even if you had a large amount of unwrapped content inside that container, your width would actually be locked at 100% (or the width of the browser window) regardless of said child content.
You could TRY and set the width to 200%, which would cause it stretch to the right beyond its parent container. But this width would not be driven by the absolute positioned child element, and may not be responsive enough for your needs.
As was already stated above, there is no pure CSS solution for what you're trying to do and you'll need to use at least some javascript to accomplish what it sounds like you're trying to accomplish.

Display:block + overflow:auto, how do they work

Posted some times ago on SO Span to take full height on a TD, as I tried some workaround, I've found a suitable code to do what was expected (the accepted one), but wasn't able to determine why this is working, so why
<td style="padding:0px;">
<span style="height:100%; width:5px; background-color:pink;"> </span>
</td>
make so much difference with
<td style="padding:0px;">
<span style="height:100%; width:5px;
background-color:pink;display:block;overflow:auto">
</span>
</td>
Here's a jsfiddle to explain more http://jsfiddle.net/7kkhh/2/
Can someone who know in depth the mechanism behind display and overflow explain this? (is it related to this particular situation or is it commonly used ?)
EDITED:
This seems to only happen on Chrome
A span element is, by default, rendered as an inline-block, just like text-nodes. They collapse around their child elements (or: they take up as much space as their child elements need, but nothing more than that).
A div element is, by default, rendered as a block. They expand to the size of their parent element, unless their child elements don't fit in it. If overflow (actually a shorthand for overflow-x and overflow-y) is auto (default), the element will expand until it's child elements fit. That will in turn expand it's parent elements, unless they have an other value set for overflow. If overflow is scroll, the element will not be expanded if the child elements don't fit in this element, but instead scroll bars will be displayed. If overflow is hidden, the element will not be expanded, but the (parts of) the child elements that are outside the parent element will be hidden (this doesn't mean that you can't scroll the element, but no scroll bars will be visible).
As inline-block conflicts with height: 100%;, the CSS style is ignored while rendering. A table cell has a display value of table-cell or something similar. I am not sure about it's behaviour. Tables and layout are always a troublesome combination to get a consistent layout in different browsers. Validating your document in xhtml-strict will usually help with displaying your document consistently across browsers.
overflow determines what happens if your block does not fit it's given dimensions. This is especially important if you are loading a picture as well.
For display you might want to read up on this :
SPAN vs DIV (inline-block)
Now the difference:
prepare the size of whatever I estimate to be in here and make it pink
vs
background-color:pink;display:block;overflow:auto">
make it pink now this was actually a block not a span and it it does not fit increase size until it does.
But seems you code shows unwanted behaviour on firefox as well and only works on chrome suggesting that maybe this is not the solution you are after.

Nested Div not fitting nicely into container Div

I have a dojox chart (chartDiv) that gets created within another container div (panelContainer).
Even though I have the width and height of the chartDiv set to be 90%, it either introduces scroll bars into the chartDiv, or if I dtart altering the padding and margin settigns for the ChartDiv, it will spill outside of the parent container.
I know this is going to be a basic issue, but I have been playing with lots of different CSS settings but nothing seems to solve keeping the chartDiv within the confines of the panelContainer (taking up 95% of the space)
This fiddle might help you spot where I have gone wrong.
When you make a chart (or a dojox.gfx canvas) without width/height, it will try its best to determine its dimensions from the container you put it in. It can get confused though!
In your fiddle's case, #chart has a known width, because it's a block element and inherits its width from panelBG which is 100% of panelContainer's width.
The #chart div doesn't really have a height though, since a block element is 0px tall until you put something in it (or add some style to it). As a consequence, (I think) the chart simply assumes a height of some proportion to the width.
In your CSS, I see you have a #chartDiv rule with width and height 90%. I'm guessing you intended that to be #chart. That wouldn't actually have resolved the problem entirely though!
Assuming you changed that, the chart would now use 90%x90% as width/height, but if you try it, you'll see that the labels/axis are still positioned incorrectly.
Because you've floated the title container to the left, the chart container starts on the same "line" and tries to have its content "float" around the title container. This skews the axis labels out of place (green), while the actual chart (svg/canvas, pink) drops down below the title container.
To fix this, tell the chart container to stay clear of floats on both sides:
#chart {
width: 90%;
height: 90%;
clear: both;
}
It isn't really necessary to float anything though, and setting the height to 90% isn't always ideal. I made a suggestion in an updated fiddle: http://fiddle.jshell.net/froden/WsrHs/4/ .
The differences are just that the title container is a div spanning across the top, while the chart container is absolutely positioned so that it fills whatever space is left underneath. You can then just set width/height on panelContainer.
Absolutely positioned elements are taken out of the normal flow. This is why some of the elements are expanding beyond their containers. I have a feeling your floats are involved in that, too, but the fiddle is a little too complicated and a simpler version needs to be made.

Expanding body with content

I have a problem regarding relative positioning. I want the body to have a background color of say, blue. Initially the page should be just of height 100% (that may vary from computer to laptop, of course, hence I can't specify a fixed height in pixels), thus the entire page should appear blue. In the middle of the page is an element, that has been set to that position by relative positioning (it can't be absolute, can it, in order to expand with its content). The element can expand vertically. If the height exceeds the boundary of the page, the page also should expand, the background of the expanded portion being still blue.
Now how do I achieve this? The only solution I can think of is to use relative positioning for the background element (which is blue and should remain blue on expansion). But for that, I must set it to the available height (relatively positioned elements cannot be assigned height through percentage value, so that rules out height: 100%). But the height itself will vary depending on the browser, viewport size, etc (and I can't use Javascript!). So how do I do this?
Is the height of the element in the middle known?
You might want to take a look at this http://css-tricks.com/centering-in-the-unknown/
A live demo that might help http://jsfiddle.net/thebabydino/7N4Xx/
The JavaScript is just for changing the height of the div in the middle.

Keep an element visible, but prevent from overflowing its parent?

Is there a way to make an element not contribute to parent overflow, but keep it visible? Let me clarify
There is a watermark-like logo to be applied to a page in the manner below. It is supposed to be positioned partly outside the main content (dashed blue line)
I'm not aware of the option to set an element background in such a manner that it would persist as the browser window is resized horizontally, so I've just added a <div> with the logo as its background and position:absolute with the necessary offset relative to main content container.
Previously, the page would not get a horizontal scrollbar as long as the browser was wider than W1. Now, with an additional "watermark" element added outside of the main content box, the scrollbar would appear whenever the browser is narrower than W2
Is there something obvious I'm missing? A background setting, or possibly a neat margin workaround/
Update:
I've added a rough jsfiddle to illustrate the issue
Unfortunately, just because you nested the "watermark" div and positioned it absolutely doesn't make it outside of the document. If you put it outside of the document, the page will scroll (as you see).
To me, the first solution I think of is to move the watermark outside of the "content" div and apply the watermark to its parent container. I'm guessing you haven't done that because you need it to be relative to the "content" div, but it's something to try.
Also, the reason it scrolls is because the document has been overflow. The quick fix, yet not recommended, is to use "overflow-x: hidden;" on the parent container of the "content" div.
It's harder to give you a solution since you've stripped the rest of your HTML, and some "fixes" may not be as applicable if your structure is complicated in certain ways.
Remember that the width of your elements is greater than the actual "width" it includes padding & margins, if you have padding on your div reduce the "width" by the equivalent amount.
does that make sense? if you post the actual css & html it might be easier to give you a more detailed answer
additionally could you not assign the image as the background of the actual body element and set it to centered?
I've had a play with the code and come up with a possible solution for you.
set
body{overflow-x:hidden;}
then add
#media all and (max-width: 400px)
{
body{overflow-x:auto; }
}
as soon as your screen is smaller than 400px (the width of the div) your overflow:hidden will be overridden and you'll be given you scroll bars.
at this point you may also want to reduce the width of your watermark.