-2

A fairly common technique to achieve page layouts is to wrap absolutely positioned divs inside a relatively positioned one in order to make the absolute divs "relatively absolute. No issues thus far. However, as I have just discovered, this causes problems with placing what follows the relatively positioned div - unless I give the relative div a height.

I have used relative absolutes for quite some time now and always thought of them as being a fully legit CSS3 technique but I am now starting to wonder if it isn't too hacky after all. If that is the case what would be the legit way to position divs absolutely relative to a container and yet have document content following the container to flow properly (i.e. appear below the container?)

I should mention that the context here is modern browsers - ones that have no issues with CSS3 & HTML5. If there is a solution that works I would love to hear of it.

An edit appears in order here. Here is the offending markup

<div id='boxrel' style='position:relative'>
 <div style='position:absolute;height:100%'>
  <div id="boxscroll">
  Lorem ipsum ...
  </div>
 </div>
</div>
<div id='afterbox'>
This div, id = afterbox, should appear BELOW boxrel but does not
</div>

The full context here is this

  • I am using jQuery Mobile v 1.3 + jQuery v 1.8.2 (good reasons for not going to v 1.9)
  • I am experimenting with using nicescroll which I have found to be a neatly written jQuery plugin for creating scrolling content.
  • In order to make nicescroll work I need to place the scrollable content inside an absolutely positioned div.
  • And that in turn requires me to make that div relatively absolute or else...
  • The consequence though is that afterbox appears as though boxrel did not exist.
  • The only way to fix this is to give boxrel a height but I am not in a position to do that

I hope that makes the question clearer.

DroidOS
  • 7,220
  • 11
  • 70
  • 142
  • 4
    It's not a hack, it's how it's supposed to work. In what cases is the content after the relatively positioned container not flowing properly? – robertc Jun 05 '13 at 13:28
  • 4
    Plus, absolute and relative positioning aren't new to CSS3 in any way. – BoltClock Jun 05 '13 at 13:29
  • 1
    The "Legit" way to do this is probably the flex-box model. Good luck with browser support though. Like both BoltClock and robertc said, what you're doing is common and well known. – Benjamin Gruenbaum Jun 05 '13 at 13:32
  • Please provide some more information what layouts you want to achieve. @BenjaminGruenbaum [flex-box browser support](http://caniuse.com/#feat=flexbox). – kleinfreund Jun 05 '13 at 13:34
  • See my edits. I hope they place the question better in context. I should mention that I tried this markup after commenting out all the nicescroll bits just in case the issue was arising from a conflict with that code. – DroidOS Jun 05 '13 at 13:40
  • Also it would be great, if you could provide as with a working example from jsfiddle.net or something else. – kleinfreund Jun 05 '13 at 13:44
  • `style='relative'` isn't valid, you mean `style='position:relative'` – robertc Jun 05 '13 at 13:46
  • @robertc Why have you not edited the correct version, then? – kleinfreund Jun 05 '13 at 13:55
  • @kleinfreund I'm not sure what you mean? – robertc Jun 05 '13 at 13:56
  • @robertc You say `style='relative'` is no valid CSS. Right. But you just could've put the valid version in the authors post instead of commenting. – kleinfreund Jun 05 '13 at 13:57
  • @kleinfreund Why can't the author correct his own mistakes? – robertc Jun 05 '13 at 14:00
  • @robertc That's how SO works – people help each other, give useful tips, correct mistakes, improve formatting if necessary. Commenting instead of editing takes the same time, but is not helpful in this case. – kleinfreund Jun 05 '13 at 14:01
  • @kleinfreund It's helpful in that the author is more likely to see it, and doesn't have to look at a diff in order to work out what mistake I was correcting – robertc Jun 05 '13 at 14:03
  • 2
    @kleinfreund This site is about correcting mistakes via answers. If we correct the mistakes by editing the original post, the answers are useless and/or confusing. This is the reason that your attempted edits continue to be rejected. – George Cummins Jun 05 '13 at 14:07
  • Robertc - the missing position in style='position:relative' was a typo in this posting rather than in my code. Well spotted though! – DroidOS Jun 05 '13 at 14:38

5 Answers5

1

If you want the container to take up space, assign a height to it:

<div id='boxrel' style='position:relative; height:200px'>
 <div style='position:absolute;height:100%'>
  <div id="boxscroll">
  Lorem ipsum ...
  </div>
 </div>
</div>
<div id='afterbox'>
This div, id = afterbox, should appear BELOW boxrel but does not
</div>
robertc
  • 69,665
  • 18
  • 184
  • 170
  • This, as I have mentioned, certainly does the trick - but then you need to know the height to assign. – DroidOS Jun 05 '13 at 14:27
1

The problem you're experiencing is not a hack, but rather the way absolute positioning works. The problem you're experiencing is caused by two things:

  1. #boxrel is a block container, meaning it will contain other block-level boxes within it by default. Content will flow as expected in a vertical fashion, unless some of its content is taken out of normal flow and placed into another context, which leads us to point 2...
  2. Your unnamed div with style = "position: absolute" creates a new block formatting context which applies to itself and its descendant elements.

Therefore, if you want your #afterbox div to appear underneath #boxscroll, you must simply include it within the block formatting context created by the div with position: absolute.

Here is an example on jsFiddle.

More info on absolute positioning.

Joey
  • 1,551
  • 12
  • 28
  • Thanks. I guess I have been under the impression that absolutely positioned elements are taken out of normal flow but normal = document UNLESS the absolute is inside a relative in which case normal means parent relative div. Clearly, there are more nuances to this that are worth understanding - though the problem at hand has now been resolved in another way. – DroidOS Jun 05 '13 at 14:34
0

Perhaps a little confusion here, what you're describing is correct behaviour, it's also not part of CSS3 (it's been part of the specification far longer), nor really 'hacky' unless misused.

When you position:absolute an element, the browser takes the element completely out of the document flow, and positions it where you've specified (against the closest position: relative parent).

This means that any elements in the document flow beneath it will behave as if it doesn't exist.

Try reading this article on A List Apart, it's a great read and very informative!

If you're able to post a preview link or a Fiddle members on here might be able to help you further.

johnkavanagh
  • 4,416
  • 2
  • 23
  • 37
0

I run into this problem a lot. My usual solution is to have a class called clear in my css (across all my web projects I use this class) and when I run up against this problem I simply add clear to the classes of new relatively positioned div I need to appear below the previously relatively positioned div. The clear class contains simply:

clear:both;

So, my afterbox would look like this:

<div id='afterbox' class='clear'>
smilebomb
  • 3,883
  • 8
  • 36
  • 71
-1

I'd ditch the relative/absolute dance altogether - CSS Flexbox is what the doctor ordered, more details here: http://css-tricks.com/using-flexbox/ Setting your inner content to flex 1 will cause it to expand to the size of the parent that has flex display applied to it. The minimum height of the parent, unless you set it to something else, will be the natural size of the inner content's height.

This is what your CSS would look like:

.outer-container {
  display: -webkit-box;  /* OLD - iOS 6-, Safari 3.1-6 */
  display: -moz-box;     /* OLD - Firefox 19- (buggy but mostly works) */
  display: -ms-flexbox;  /* TWEENER - IE 10 */
  display: -webkit-flex; /* NEW - Chrome */
  display: flex;         /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

.inner-content  {
  height: 100%;
  -webkit-box-flex: 1;   /* OLD - iOS 6-, Safari 3.1-6 */
  -moz-box-flex: 1;      /* OLD - Firefox 19- */
  -webkit-flex: 1;       /* Chrome */
  -ms-flex: 1;           /* IE 10 */
  flex: 1;               /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
csuwldcat
  • 7,103
  • 1
  • 35
  • 31
  • Thank you for all the comments and answers. The big issue I thought I was trying to circumvent was that of assigning an em height value to boxscroll - the div that gets converted to a scrolling box by nicescroll. However, I managed to modify some of my peripheral code to allow for em height assignments to boxscroll (rather than % as I had originally planned. The entire relative-absolute dance (I like that way of putting it csuwldcat) was being triggered by that %age height assignment. As I have learnt in this game - when you can't find the answer, seek another question :-) – DroidOS Jun 05 '13 at 14:26
  • csuwldcat I am "accepting" your answer because you would have put me on the right track re ditching the relativly absolute dance had I not done it already in the mean time. Flexbox looks interesting and I might well have a need to use it one day - however, from the brief glance I gave it, it sounds like it does not support IE9. – DroidOS Jun 05 '13 at 14:36
  • @DroidOS - yeah, no IE9- support for Flexbox (I was unsure about your specific compatibility range). Good news is, when you can shift to IE10, this whole use-case is just a few lines of CSS! :) – csuwldcat Jun 05 '13 at 16:28