CSS: display:inline-block and positioning:absolute
Asked Answered
R

3

40

Please consider the following code:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
    <style type="text/css">
        .section {
            display: block;
            width: 200px;
            border: 1px dashed blue;
            margin-bottom: 10px;
        }
        .element-left,
        .element-right-a,
        .element-right-b {
            display: inline-block;
            background-color: #ccc;
            vertical-align: top;
        }
        .element-right-a,
        .element-right-b {
            max-width: 100px;
        }
        .element-right-b {
            position: absolute;
            left: 100px;
        }
    </style>
    <title>test</title>
</head>
<body>
    <div class="section">
        <span class="element-left">some text</span>
        <span class="element-right-a">some text</span>
    </div>
    <div class="section">
        <span class="element-left">some text</span>
        <span class="element-right-a">some more text to force line wrapping</span>
    </div>
    <div class="section">
        <span class="element-left">some text</span>
        <span class="element-right-b">some text</span>
    </div>
    <div class="section">
        <span class="element-left">some text</span>
        <span class="element-right-b">some more text to force line wrapping</span>
    </div>
    <div class="section">
        <span class="element-left">some text</span>
        <span class="element-right-b">some more text to force line wrapping</span>
    </div>
</body>
</html>

The element with absolute positioning apparantly makes the containing box "forget" which height he needs.

I need the absolute positioning inside the "section" box, is there another solution for this?

edit

Using tables is not really an option, I need some sort of "multi-level"/"nested" layout, where the second col is always on the same position:

| some text in first column       | some text in 2nd column
  | some indented text            | 2nd column
  | also indented                 | 2nd col
    | even more indent            | 2nd column with a lot of text that
                                  |  makes it wrap
  | text                          | ...
| blah blah                       | ...

(of course whithout the "|"s)

Ramillies answered 18/2, 2011 at 14:28 Comment(1)
Gah, it's hard to visualize what that does check this out :) jsfiddle.net/Kyle_Sevenoaks/YTUnM What is your desired result?Loehr
G
67

When you use position:absolute;, the element is taken out of the normal page flow. Therefore it no longer affects the layout of its container element. So the container element does not take into account its height, so if there's nothing else to set the height, then the container will be zero height.

Additionally, setting display:inline-block; does not make any sense for an element that is position:absolute;. Again, this is because absolute positioning takes the element out of the page flow. This is at odds with inline-block, which only exists to affect how the element fits into the page flow. All elements that are position:absolute; are automatically treated as display:block, since that's the only logical display mode for absolute positioning.

If you need absolute positioning, then the only solution to your height problem is to set the height of the container box.

However, I suspect that you could do without the absolute positioning.

It looks like what you're trying to do is position the second <span> in each block to a fixed position in the block, so that they line up.

This is a classic CSS problem. In the "bad-old-days", web designers would have done it using a table, with fixed widths on the table cells. This obviously isn't the answer for today's web designers, but it is something that causes a lot of questions.

There are a number of ways to do it using CSS.

The easiest is to set both the <span> elements to display:inline-block;, and give them both a fixed width.

eg:

<div class='section'>
    <span class="element-left">some text</span>
    <span class="element-right">some text</span>
</div>

with the following CSS:

.section span  {display:inline-block;}
.element-left  {width:200px;}
.element-right {width:150px;}

[EDIT]after question has been updated

Here's how I would achieve what you're asking now:

<div class='section'>
    <span class="element-left"><span class='indent-0'>some text</span></span>
    <span class="element-right">some text</span>
</div>
<div class='section'>
    <span class="element-left"><span class='indent-1'>some text</span></span>
    <span class="element-right">some text</span>
</div>
<div class='section'>
    <span class="element-left"><span class='indent-2'>some text</span></span>
    <span class="element-right">some text</span>
</div>

with the following CSS:

.section span  {display:inline-block;}
.element-left  {width:200px;}
.indent-1 {padding:10px;}
.indent-2 {padding:20px;}
.element-right {width:150px;}

A small amount of extra markup, but it does achieve the effect you want.

Guru answered 18/2, 2011 at 14:46 Comment(11)
tables and defining width of "left" element doesn't work for me -- see edited part in my question...Ramillies
Hmm, seems a useful idea. I'll try if it works for my "real" problem (since I don't know in advance how many levels I have, and my HTML is generated from an XML using XSLT). :-)Ramillies
@Ramillies - at a practical level, you can only have so many levels before your indentation means you run out of screen space. And it's not likely to be very many, really - five or six at the most before it starts looking silly, so I would say you can probably get away with a bunch of numbered classes like that.Guru
after I finally had time to work on this again, I can say your solution works fine for me. I indeed made some numbered classes on beforehand. Thanks a lot!Ramillies
Thank you! I was working on a CSS-generated table containing 6 rows of data, where much of the data needed to have absolute position within the confines of the individual row. Your "inline-block" solution was perfect!Ilbert
"When you use position:absolute;, the element is taken out of the normal page flow. Therefore it no longer affects the layout of its container element." Bull. My "position:absolute" color picker inside a position:relative div is definitely messing with the other elements in my container that uses "column-count:2". Elements shift between columns as though the absolutely positioned div is taking up space.Cutinize
@Cutinize - as others have commented on the question you asked about this, you need to show an example of the problem; your description doesn't sound right, but without being able to see it in action, nobody can tell you what is actually happening. Post some code and/or a jsFiddle link that shows the problem in action.Guru
@Guru : Does the w3c has anything that says it will happen this way? how did you figure this out?Tout
@Tout - this answer was posted seven years ago. Please be aware that there are additional solutions to the question that may be more appropriate today than the answer given.Guru
"All elements that are position:absolute; are automatically treated as display:block, since that's the only logical display mode for absolute positioning."Romaine
Just to salt the wound, combining position: absolute and display: inline-block is undefined in the CSS spec, so, Firefox does it one way and Chrome does it another. Firefox renders it like display: inline-block, position: static and Chrome renders it like display: block, position: absolute. In other words, combining them introduces a (rare nowadays) cross-browser bug, is harmful and should be avoided.Midnight
E
4

No.

You could position absolutely then have a copy of the element inside the section box with visible: none but absolute positioning by definition makes it a "floating" element that doesn't interact with elements above it.

Assuming your page layout is fixed you could use padding-left: #px; to achieve your goal, as I don't think relative positioning is what you want.

Alternatively, you could use display: table-* to force it to retain a stricter form without affecting the document structure as shown here

However depending on whether you want the cells to be fluid you may need to alter the .section divs into display: table-row if you don't like a predetermined width setup and want the separate .section's to line up.

Extroversion answered 18/2, 2011 at 14:34 Comment(0)
D
2

This can in fact be done easily and simply with divs. You just need to place a div with position:relative inside the inline or block display div. Set its width and height to the same as the containing div. You will then find you can position another div absolutely inside it.

Dehumidifier answered 29/5, 2014 at 15:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.