orszaczky
orszaczky

Reputation: 15685

Issue with inline-block elements with unknown width

I'd like to line up two elements in a header:

<div class="col-md-3">
    <div class="header">
        <div class="icon"></div>
        <div class="title"><h1>This is the title row</h1></div>
    </div>
    <p>This is some content text. This is some content text. This is some content text. This is some content text. This is some content text. </p>
</div>

To the left is a fixed width icon, and I want to the title to fill up the remaining width. (The title is broken in two lines because of the narrow columns):

.col-md-3 {
    width: 200px; /*this width is just for illustrating the problem, in reality this is Bootstrap's 25% width column*/
}
.icon {
    display: inline-block;
    height:50px;
    width: 50px;
    background: red;
}
.title {
    display: inline-block;
}

I can't get them to line up using inline-block. Any ideas why?

PLUNKER

UPDATE

I added a new plunker (see above) to better demonstrate the problem.

I'm looking for an explanation why inline-block doesn't work in this case, and a possible solution how to make it work. Any workarounds posted are really appreciated, but I'd really like to find out what's the deal with inline-blocks in this case.

Upvotes: 9

Views: 4519

Answers (6)

Stickers
Stickers

Reputation: 78706

You could set .header as table, and set .icon and .title as table cell.

Updated JsFiddle

.header {
    display: table;
    width: 100%;
}
.header .icon, .header .title {
    display: table-cell;
    vertical-align: middle;
}
.header .icon {
    width: 60px;
}
.header .icon span {
    width: 50px;
    height: 50px;
    display: block;
    background: red;
}
.header .title h1 {
    margin: 0;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

<div class="col-md-3">
    <div class="header">
        <div class="icon"><span></span></div>
        <div class="title"><h1>This is the title row</h1></div>
    </div>
    <p>This is some content text. This is some content text. This is some content text. This is some content text. This is some content text. </p>
</div>

Upvotes: 2

Sleek Geek
Sleek Geek

Reputation: 4686

Just add display property value of just inline to .col-md-3 and adjust as needed, then inline-block to both .icon and .title

.col-md-3 {
    width: 200px;
    display: inline;
    vertical-align: middle;
}
.icon {
	display: inline-block;
	height:50px;
	width: 50px;
    background: red;

}
.title {
	display: inline-block;
    height: 50px;
    position: absolute;
   line-height: 5px;
    left: 70px; /* Width of the icon plus 10px for space */
}
<div class="col-md-3">
    <div class="header">
        <div class="icon"></div>
        <div class="title"><h1>This is the title row</h1></div>
	</div>
    <p>This is some content text. This is some content text. This is some content text. This is some content text. This is some content text. </p>
</div>

Note: You may need to further adjust it to suit your need.

Upvotes: 1

Laurent S.
Laurent S.

Reputation: 6947

I would try something like this instead :

HTML

<div class="col-md-3">
    <h2>This is the title row</h2>
    <p>This is some content text. This is some content text. This is some content text. This is some content text. This is some content text. </p>
</div>

CSS

.col-md-3 {   width: 200px; }
h2 { position: relative; padding-left: 50px;}
h2::before { content:''; position: absolute; height:50px; width: 50px; left: 0; background: red;}

Here's the fiddle

Upvotes: 1

Justus Romijn
Justus Romijn

Reputation: 16049

If the content of the inline-block does not fit on a single row, it will try to fit as a whole on the next line. This is different from regular inline elements, that most of the time is allowed to wrap to the next line.

You might want to read up on this behaviour at the W3C specification about the 'normal flow'.

Not sure why everyone makes it so complex, why not use a float?

.icon {
    float: left;
    width: 50px;
    height: 50px;
    background-color: red;
}
.title {
    padding: 0 10px;
    overflow: hidden;
}
.title h1 {
    line-height: 50px;
    margin: 0;
}
<div class="col-md-3">
    <div class="header">
        <div class="icon"></div>
        <div class="title"><h1>This is the title row erg erg erg erg erg erg er</h1></div>
    </div>
    <p>This is some content text. This is some content text. This is some content text. This is some content text. This is some content text. </p>
</div>

Upvotes: 2

llernestal
llernestal

Reputation: 566

If you do not specify the width of the inline-block element then the default value is auto. Then the browser will try to calculate a shrink-to-fit width based on the containing blocks width, in your case the .header element which bases its width on your .col-md-3 width. The browser does not take into account your .icon elements width when calculating the width of your .title element. So to get what you want, still using display: inline-block, you have to specify a width for your .title element.

.title {
    width: calc(100% - 50px);
}

You could also just use float on your .icon element. See this answer.

Another way is to use display: table for containing block and table-cell for child elements as mentioned in this answer.

From the W3C specification:

10.3.9 'Inline-block', non-replaced elements in normal flow
If 'width' is 'auto', the used value is the shrink-to-fit width as for floating elements.

...

Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.1 does not define the exact algorithm. Thirdly, find the available width: in this case, this is the width of the containing block minus the used values of 'margin-left', 'border-left-width', 'padding-left', 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.

Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

Upvotes: 1

anhamande
anhamande

Reputation: 36

Add a width to .title class

.title {
    with: calc(100% - 55px);
}

where 55px is from the .icon width plus 5px.

Upvotes: 0

Related Questions