Static elements after position:absolute
I have the following markup:
<html>
<body style="margin:0;padding:0">
<div>
<div style="border:3px solid red; width:70%; position:absolute; left:2.5%">Left</div>
<div style="border:3px solid开发者_StackOverflow中文版 blue; width:25%; position: absolute; left:72.5%">Right</div>
<div style="border:3px solid black; width:95%; margin: 0 auto">Bottom</div>
</div>
</body>
</html>
What I am trying to achieve here is three divs layed out like this:
+---------------------------+--------+
|Left |Right |
+---------------------------+--------+
|Bottom |
+------------------------------------+
However, with my markup the "bottom" div is overlapping with the "left" & "bottom" ones.
How should I style those 3 elements to achieve this effect?
Note that "bottom" is not the last element on the page. I would simply like "left" and "right" to be in one line and for the page flow to continue with default positioning from the following lines.
EDIT: In addition to the accepted answer... If you don't have static heights or for some reason don't want to hardcode it, you can achieve similar effect with:
<div style="border:3px solid red; width:70%; position:absolute; left:2.5%">Left</div>
<div style="border:3px solid blue; width:25%; margin-left:72.5%">Right</div>
<div style="border:3px solid black; width:95%; margin: 0 auto">Bottom</div>
I think the problem is that when you have elements positioned absolutely, they are taken out of the document flow. So the elements that come after can't see them, assume they aren't there, and jump up. To just get your "bottom" div to be under your "left"/"right" divs, you have to give it a margin-top
equal to their heights (or something similar to that).
This is going to be a philosophical rant. The other answers provide concrete workarounds, this one looks at the bigger picture. I’ve been asking myself “why” on this issue and similar recently.
CSS is Cascading Style Sheets. It was designed to do styling. And it also does some layout, almost.
Two ways to achieve the desired effect are given in the other anwers.
With the position:absolute answer (see also this technique that uses position:absolute
within position: relative
) it is possible to have the "Left" div a fixed width and the "Right" div take up the rest of the width (or use percentages for both if you prefer) by giving width and left on both divs. However the bottom div doesn't flow properly below it since the absolute div is outside the page flow. You can supply a fixed height, if the height of the content is fixed. If not, you are out of luck and must try a different technique.
With the float + margin
technique from Projapati the flow is fine – but having one of the 2 divs a fixed width in pixels and the other one take up the rest of the container width is not possible – you can specify percents, or width in pixels for both divs, but there is no way to tell a div to take up "the rest of it" Also, if you make the page very narrow, the "Right" div falls down to the following line, indicating that these divs are only provisionally next to each other.
In short, both approaches are complex hacks that re-purpose constructs not designed for this task, and both do a limited subset of what people want to do. There are a lot of questions here on StackOverflow (e.g. this one) that ask similar minutia, all mired in the tar pit of trying to fine-tune a particular CSS technique to approximate the desired layout, and so many answers along the lines of "why do that?", "don't use that technique, it doesn't do what you want" and "you don't understand CSS properly".
The thing is, you don’t want float: left
. You don’t want position: absolute
. Those are the possible means to the end, which is the simple layout that anyone can sketch and understand, and find it difficult to grasp why CSS just does not handle well. There is a basic mismatch between what CSS does and what people expect it to do. True, people really don't understand CSS when they start out with it. But CSS was built for our benefit, and it fails us. The fault is in CSS not in the users of it.
The desired layout looks like a grid. Two columns, two rows. The height expands to fill the content. "Left" is in the first row and first column, with width that is either a percent of the total width, or a fixed width, and the "right" is the first row and second column, takes up the rest of the width. The "bottom" is second row content, which spans both columns. Or "bottom" is outside the grid entirely, just after it in the page.
Grid layouts as proposed here are needed in CSS, since they map very closely to how people think about page layout, and cover all the cases that a wide variety of CSS hacks are now used for.
You can just specify a CSS grid this simply: "I want a grid with two columns. The left takes up 100 pixels, the right takes up the rest of the container width. The height expands to contain the content. The rest of the page flows on below it." Done.
If you want to change that to the left column taking up 20% of the width, or fix the right-hand column instead, or fix the height, change one line of ccs and you’re done. With current techniques, when you reach the limits of the css hack that you’re currently using, you start from scratch with a different hack which has different but equally severe limits.
IMHO CSS grids are a bigger deal than most people realise, they will make all of this stupid CSS layout hackery finally just go away.
The good news is that this will be doable in IE10 and the browsers that will compete with it. The bad news is that you’ll be supporting IE8 and IE9 for a long, long time to come. By my guess until at least 2016.
Not sure why are you using position:absolute
If you need the layout given, can you try this?
<div style="clear:both;">
<div>
<div style="border:3px solid red;width:70%;float:left;padding:3px">Left</div>
<div style="border:3px solid blue;width:25%;float:left;padding:3px">Right</div>
</div>
<div style="clear:both;border:3px solid black;width:96%;padding:3px">Bottom</div>
</div>
It might difficult to control with % in the width.
Can you try this as well? You can adjust the width as you need.
Typically i keep this in my master page. That way all child pages are fine.
<div style="clear:both;width:532px">
<div>
<div style="border:3px solid red;width:350px;float:left;padding:5px">Left</div>
<div style="border:3px solid blue;width:150px;float:left;padding:5px">Right</div>
</div>
<div style="clear:both;border:3px solid black;width:516px;padding:5px">Bottom</div>
</div>
You can generate this kind of flexible columns layout using the Yahoo YUI CSS Grid builder.
The output is not something that I would want to hand-code, it has divs nested 5 deep, and references the YUI CCS library which is 6kb when minified. I'm not happy that this is not easy to handcode, despite being easy to describe.
Here's the generated html. This may not mean much without the CSS.
<html>
<head>
<title>YUI Base Page</title>
<link rel="stylesheet" href="http://yui.yahooapis.com/2.8.0r4/build/reset-fonts-grids/reset-fonts-grids.css" type="text/css">
<style type="text/css">
#custom-doc { width: 100%; min-width: 250px; }
</style>
</head>
<body class="yui-skin-sam">
<div id="custom-doc" class="yui-t1">
<div id="hd" role="banner"><h1>header content</h1></div>
<div id="bd" role="main">
<div id="yui-main">
<div class="yui-b"><div class="yui-g">
Main content. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</div>
</div>
</div>
<div class="yui-b">Left bar. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. </div>
</div>
<div id="ft" role="contentinfo"><p>footer content.Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p></div>
</div>
</body>
</html>
It seems to work fine in current Chrome and Firefox, and in Internet Explorer 9.
Note that the right column comes before the left one in the mark-up - float: right
is used on <div id="yui-main">
. The use of :after
css rules is interesting, and may be important.
精彩评论