css margin-top effecting image and paragraph at same time [duplicate] - javascript

I have a very simple html. The red div is inside the blue div and has a 10 px top margin. On non-ie browsers, the blue box is 10 px apart from the top of viewport and the red div is at the very top of the blue div. What I expect is the ie behavior: red div must be 10 px apart from the top of the blue div. Why does non-ie browsers render like this? (I suppose the wrong behavior is the IE's but why?)
And, what is the correct way to do this?
why blank? http://img92.imageshack.us/img92/7662/blankmr7.jpg
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>

As much as strager's answer already explains about as much as you need to know as to why it happens – namely that it happens the way it does in browsers other than IE because the specs say so – I think he picked the wrong quote from the section of the CSS 2.1 specification about collapsing margins.
The point he quoted explains how margins can collapse, not how they can "move" to a parent element.
This is rather what explains it:
If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it. In this case, the position of the element depends on its relationship with the other elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as the parent's.
Or, in slightly more human-readable form in the Mozilla developer documentation:
Parent and first/last child:
If there is no border, padding, inline content, or clearance to separate the margin-top of a block with the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block with the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.
As for how to fix it, I'd probably go for the overflow: auto solution Chris Lloyd suggested (as much as that may have side-effects).
But then that really depends on what exactly the rest of your code looks like. In this simple example you could easily just change the margin on the child element to a padding on the parent element.
Or you could float the child element, or absolutely position it...
Or how about an inverse clearfix if you want to get really fancy:
.outer:before {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}

The margins are being merged. The output produced by IE is probably incorrect.
In the specifications (which are down for me at the moment):
Two or more adjoining vertical margins of block boxes in the normal flow collapse. The resulting margin width is the maximum of the adjoining margin widths.
You can use borders instead of margins, with border-color set to transparent.

There is a pretty fitting answer to this question: overflow: auto;
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
overflow: auto;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>

Could it be IE sees the DOM as div.inner having div.outer as it's parent node(and calculates offset from it),
and that other browsers instead has both of them answering to the body element?

Ok, solution without overflow auto:
<html>
<head>
<style>
body { margin:0; padding:0; }
.outer
{
background-color: #00f;
height: 50px;
border: 1px solid transparent;
}
.inner
{
height: 20px;
width: 20px;
background-color: #f00;
margin: 10px 0 0 10px;
padding: 0;
}
</style>
</head>
<body>
<div class="outer">
<div class="inner">
</div>
</div>
</body>
</html>
The inner element is wanting something to push against, and providing a boder (or forcing the browser to consider the overflow) does this.

Related

span with position:absolute won't create scrollbar on container overflow

I want absolute-positioned SPANs inside a container show scrollbars on the container when its position overflows the container.
However, even with overflow:auto on the container, the SPAN flies outside the container div, as if it does not belong to the container.
I will append many SPANs, so other values of position (like relative) will mess the independent positioning desired for each SPAN, albeit making the scrollbars.
Here is the fiddle:
https://jsfiddle.net/v8x2bot4/1/
CSS:
.container {
background-color: #AFF;
width: 500px;
height: 500px;
overflow: auto;
}
.fly {
border: solid black 1px;
background-color: #0F0;
position: absolute;
}
HTML:
<div class="container">
<span class="fly" style="left:450px; top:100px">blablablablabla</span>
<span class="fly" style="left:300px; top:200px">blablabla2</span>
</div>
How can I hide the overflowing part of the SPAN and make a scrollbar appear as needed?
Hope HTML+CSS can do it without javascript. But solutions with javascript that work regardless of the number of SPANs should be very easy to maintain and suitable.
Add position: relative to .container
https://jsfiddle.net/xfmrtx3s/

Div to fill remaing vertical space

I have a complex HTML application, so unfortunately cannot really provide a code sample. We are trying to get the div (highlighted in red) to fill the remaining vertical space (see image).
The application consists of a header (in black), a sidebar on the left which can be dismissed or resized (note: the horizontal components resize correctly). To the right of the sidebar is another div (mainDiv). mainDiv contains a div at the top for the controls, and a div underneath it for the table of data (highlighted in red).
This table can potentially contain lots of data, so it needs its own scrollbar if the data doesn't fit on the screen.
We just want the table to fill all of the available horizontal and vertical space. We just can't seem to make it work.
We have created a jsfiddle example to demonstrate our layout as best we can. This can be seen here. We just want this div (in jsfiddle the div is called "tablewrap") to take up all of the remaining space.
Code (from jsfiddle) is as follows:
html
<div class="header">Header</div>
<div class="sidebar">This is the sidebar</div>
<div class="tablewrapper">
<div class="tableheader-controls-etc"></div>
<div class="tablewrap">table</div>
</div>
css
.header { height: 50px; background:black; color:white; }
.sidebar { height:100%; position:fixed; width 200px; background:gray; color:white; }
.tablewrapper{ float:right; width:75%; border:1px solid; margin-top:30px; margin-right:30px;}
.tableheader-controls-etc { height:150px; background:blue; color:white; }
.tablewrap { height: 200px; border: 2px solid red; width:100%; overflow:auto;}
If anyone can provide a solution that would be great. We would prefer CSS but can cope with Javascript.
Thanks,
Phil
The trick is to set position: absolute, then adjust the top, bottom, left and right properties as needed. See fiddle and explanation.
.tablewrap {
position: absolute;
top: 240px;
bottom: 0;
left: 150px;
right: 40px;
height: auto;
width: auto;
...
}
You can try this:
.tablewrap { height: 200px; border: 2px solid red; width:100%; overflow:auto; min-height:300px}
(Set the min-height as you want)
Well, it's time to say what you probably don't want to hear hehe: you can't do this with CSS.
You have to use javascript in order to find out two things:
Viewport height
Controls div height
Once you know those two heights, you can set your table height to:
finalHeight = viewport - (controls+header+footer)
If header and footer have also dynamic heights, use javascript to calculate them.
You will also need to recalculate this height on window resize. And of course your layout won't work if javascript is disabled.

Vertical Alignment

Please take a look at this: http://sources.freehosting.bg/landing.html
I am trying to vertically align #content so it looks good on larger (1920x1200) and smaller (1024x768) resolutions. By that I mean it does not have a scrollbar.
As you see there is plenty of free space so a scrollbar is unneeded.
The only solution I came up with is to calculate the height of #content with JS and to set a padding, but I realize it is the lamest possible solution.
Please advise me on how to achieve that.
See if this fiddle is what you are looking for. Simple solution IMO.
It works by forcing the containing div to behave as a table-cell, and making use of the vertical-align: middle style. It doesn't require you to know the heights of any elements at all.
Code used in the fiddle are below.
HTML:
<div class="a">
text inside div a
<div class="b">
text inside div b
</div>
</div>
The important styles are:
display: table-cell
vertical-align: middle
The rest are only there for demonstration. CSS:
div.a {
border: 1px solid red;
}
div.b {
border: 1px solid blue;
height: 200px;
display:table-cell;
vertical-align:middle;
}
If your content height is fixed put a div before the content
<div id="distance"></div>
<div id="content">
Vertically centered :D
</div>
and style it like:
html, body {
height:100%;
margin:0;
padding:0;
}
div#distance {
width:1px;
height:50%;
margin-bottom:-300px; /* half of website height */
float:left;
}
div#content {
text-align:left;
margin:auto;
position: relative;
width: 950px;
height: 600px;
clear: left;
}
​
The only way I know of that works using pure CSS, no JS and no hacks requires you to know the height of the thing you're trying to position:
<html>
<head>
<style type="text/css">
/* Give your document height */
body, #content {
height: 100%;
}
/* Give your element height */
.thing {
width: 20px;
height: 300px;
background: #000;
}
/* Position thing */
#content .thing {
position: absolute;
top: 50%;
margin-top: -150px; /* half the height of the thing */
}
</style>
</head>
<body>
<div id="content">
<div class="thing"></div>
</div>
</body>
</html>
EDIT: Updated height of item, container id. Still works just fine.
There is one way to do this without javascript and without knowing the height of the content - but purists will not like it. Then again, sometimes it doesn't matter if it's not approved by the trendy people. Sometimes all you need is to get the job done because you boss wants it that way.
And the solution is: use a table (told you purists wouldn't like it). Do layout the old school way and abuse the fact that HTML specifies lots of capabilities to tables.
A table cell is the only HTML element that has a vertical alignment attribute that does what most people expect it to do. Just give the table 100% width and height (so that is expands with the window size) and use cell alignment to position the content you want.
I've only ever had to use this trick once and it still makes me feel dirty* but when you really need it it works better than anything else.
*note: I'm a purist myself but understand that sometimes a man's got to do what a man's got to do.

Cross browser div center alignment using CSS

What is the easiest way to align a div whose position is relative horizontally and vertically using CSS ? The width and the height of the div is unknown, i.e. it should work for every div dimension and in all major browsers. I mean center alignment.
I thought to make the horizontal alignment using:
margin-left: auto;
margin-right: auto;
like I did here.
Is this a good cross browser solution for horizontal alignment ?
How could I do the vertical alignment ?
Horizontal centering is only possible if the element's width is known, else the browser cannot figure where to start and end.
#content {
width: 300px;
margin: 0 auto;
}
This is perfectly crossbrowser compatible.
Vertical centering is only possible if the element is positioned absolutely and has a known height. The absolute positioning would however break margin: 0 auto; so you need to approach this differently. You need to set its top and left to 50% and the margin-top and margin-left to the negative half of its width and height respectively.
Here's a copy'n'paste'n'runnable example:
<!doctype html>
<html lang="en">
<head>
<title>SO question 2935404</title>
</head>
<style>
#content {
position: absolute;
width: 300px;
height: 200px;
top: 50%;
left: 50%;
margin-left: -150px; /* Negative half of width. */
margin-top: -100px; /* Negative half of height. */
border: 1px solid #000;
}
</style>
<body>
<div id="content">
content
</div>
</body>
</html>
That said, vertical centering is usually seldom applied in real world.
If the width and height are really unknown beforehand, then you'll need to grab Javascript/jQuery to set the margin-left and margin-top values and live with the fact that client will see the div quickly be shifted during page load, which might cause a "wtf?" experience.
"Vertical centering is only possible if the element is positioned absolutely and has a known height." – This statement is not exactly correct.
You can try and use display:inline-block; and its possibility to be aligned vertically within its parent's box. This technique allows you to align element without knowing its height and width, although it requires you to know parent's height, at the least.
If your HTML is this;
<div id="container">
<div id="aligned-middle" class="inline-block">Middleman</div>
<div class="strut inline-block"> </div>
</div>
And your CSS is:
#container {
/* essential for alignment */
height:300px;
line-height:300px;
text-align:center;
/* decoration */
background:#eee;
}
#aligned-middle {
/* essential for alignment */
vertical-align:middle;
/* decoration */
background:#ccc;
/* perhaps, reapply inherited values, so your content is styled properly */
line-height:1.5;
text-align:left;
}
/* this block makes all the "magic", according to http://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align specification: "The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge." */
#container .strut {
/* parent's height */
height:300px;
}
.inline-block {
display:inline-block;
*display:inline;/* for IE < 8 */
*zoom:1;/* for IE < 8 */
}
Then #aligned-middle will be centered within #container. This is the simplest use of this technique, but it's a nice one to be familiar with.
Rules marked with "/* for IE < 8 */" should be placed in a separate stylsheet, via use of conditional comments.
You can view a working example of this here: http://jsfiddle.net/UXKcA/3/
edit: (this particular snippet tested in ie6 and ff3.6, but I use this a lot, it's pretty cross-browser. if you would need support for ff < 3, you would also need to add display:-moz-inline-stack; under display:inline-block; within .inline-block rule.)
Check this Demo jsFiddle
Set following two things
HTML align attribute value center
CSS margin-left and margin-right properties value set auto
CSS
<style type="text/css">
#setcenter{
margin-left: auto;
margin-right: auto;
// margin: 0px auto; shorthand property
}
</style>
HTML
<div align="center" id="setcenter">
This is some text!
</div>
"If the width and height are really unknown beforehand, then you'll
need to grab Javascript/jQuery to set the margin-left and margin-top
values and live with the fact that client will see the div quickly be
shifted during page load, which might cause a "wtf?" experience."
You could .hide() the div when the DOM is ready, wait for the page to load, set the div margin-left and margin-top values, and .show() the div again.
$(function(){
$("#content").hide();
)};
$(window).bind("load", function() {
$("#content").getDimSetMargins();
$("#content").show();
});

Force <div></div> to the bottom of the web page centered

I have a <div>...</div> section in my HTML that is basically like a toolbar.
Is there a way I could force that section to the bottom of the web page (the document, not the viewport) and center it?
I think what you're looking for is this: http://ryanfait.com/sticky-footer/
It's an elegant, CSS only solution!
I use it and it works perfect with all kinds of layouts in all browsers! As far as I'm concerned it is the only elegant solution which works with all browsers and layouts.
#Josh: No it isn't and that's what Blankman wants, he wants a footer that sticks to the bottom of the document, not of the viewport (browser window). So if the content is shorter than the browser window, the footer sticks to the lower end of the window, if the content is longer, the footer goes down and is not visible until you scroll down.
Twitter Bootstrap implementation
I've seen a lot of people asking how this can be combined with Twitter Bootstrap. While it's easy to figure out, here are some snippets that should help.
// _sticky-footer.scss SASS partial for a Ryan Fait style sticky footer
html, body {
height: 100%;
}
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -1*($footerHeight + 2); /* + 2 for the two 1px borders */
}
.push {
height: $footerHeight;
}
.wrapper > .container {
padding-top: $navbarHeight + $gridGutterWidth;
}
#media (max-width: 480px) {
.push {
height: $topFooterHeight !important;
}
.wrapper {
margin: 0 auto -1*($topFooterHeight + 2) !important;
}
}
And the rough markup body:
<body>
<div class="navbar navbar-fixed-top">
// navbar content
</div>
<div class="wrapper">
<div class="container">
// main content with your grids, etc.
</div>
<div class="push"><!--//--></div>
</div>
<footer class="footer">
// footer content
</footer>
</body>
If I understand you correctly, you want the toolbar to always be visible, regardless of the vertical scroll position. If that is correct, I would recommend the following CSS...
body {
margin:0;
padding:0;
z-index:0;
}
#toolbar {
background:#ddd;
border-top:solid 1px #666;
bottom:0;
height:15px;
padding:5px;
position:fixed;
width:100%;
z-index:1000;
}
I just want to be clear on what your saying here:
bottom of the web page (the
document, not the viewport)
Naturally, a div will be at the bottom of the "document", depending on your layout.
If it's not going to the bottom of a document, or not paying attention to how tall your columns are, is it because your floating? Clear: both; would be in order to solve that.
The sticky footers are what I think your looking for, but when you say document, and not the viewport, I get a bit confused. Sticky footers typically do this: Watch for short pages, and if its shorter than the view port, the sticky footer tacks the footer div to the bottom.
Here's some sticky footers (there's gajillions of em, but this is in order of my favorites):
http://www.cssstickyfooter.com/
http://css-tricks.com/sticky-footer/
http://ryanfait.com/sticky-footer/ (listed previously)
http://brassblogs.com/blog/sticky-footer
http://alistapart.com/ (theres one there I just can't find it)
Maybe if you gave a quick illustration or were a bit more specific on what you want? Hope this helps :D
-Ken
Try this: Fixed footers without Javascript. I don't know if it will be a perfect fit, but I think it's close enough.
You can just give the div a:
clear:both; text-align:center;
and put the div as the last element before the closing body statement. That would force it to be the last element without anything next to it.
Your best bet is to use javascript to determine the size of your page. You can get the height with window.innerHeight with non-IE browsers and document.documentElement.clientHeight with IE. With that value you should be able to absolutely position your element on the page setting top to that value minus the height of your div. If the height of your div is variable you will need to check the div's offsetHeight property to get the real height.
For centering use the following example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
.wrapper
{
width: 100%;
padding-left: 50%;
}
.test
{
width: 400px;
margin-left: -200px;
border: 1px solid black;
padding-left: -200px;
}
</style>
</head>
<div class="wrapper">
<div class="test">This is a test</div>
</div>
</html>
You have a wrapper div around the div you want centered. The wrapper div has a width of 100% the inner div has a width set to whatever you want it to be. Give the wrapper div a left padding of 50% and the inner div a negative left margin equal to half of its width.

Categories