Block-level elements within display: inline-block - html

I'm trying to put some (vertically-stacked) display:block elements within a display:inline-block element. According to the CSS specification, the inline-block element should be a containing block, so it can have display:block elements within it and those should not affect the rest of the layout.
However, the display:block elements inside the display:inline-block elements disrupt the rest of the page; so does having nothing at all within the inline-block, or even a basic element like a paragraph; only simple text avoids disruption of the rest of the page (by disruption I mean shifting other divs down, e.g. in this case the left red block moves down a line and has a blank white space above it). I'm using Firefox 3.0.6.
<html><head><style type="text/css">
#left {
display: inline-block;
background: red;
width: 20%;
height: 100%;
}
#right {
display: inline-block;
background: green;
width: 80%;
height: 100%;
}
</style></head><body>
<div id="left">Left</div><div id="right">Right</div>
</body></html>
The above shows as two panes, left red, right green, as expected. If I change "Right" to
<p>Right</p>
or remove it entirely, or (as I want to do) replace it with a couple of divs, I get the bad formatting.
Is this a Firefox bug, or am I doing something wrong, or are my expectations incorrect? (FWIW, IE 7 mangles them all equally, as if it doesn't understand inline-block; doesn't matter, this is an internal app. and I'm only using Firefox). I may be able to get the layout I want using float/margin, but I'd prefer not to have to do that.

Well display: inline-block can be a bit tricky to get cross-browser. It will require at minimum, a few hacks and, for Firefox 2, potentially an extra element.
CSS
.inlineBlock { display: -moz-inline-stack; display: inline-block; zoom: 1; *display: inline; }
display: -moz-inline-stack is for Firefox 2. All the immediate children will need to have display: block or otherwise be block level elements. Note if you need your inline-block element to shrink wrap I think you can use display: -moz-inline-box instead.
zoom: 1 gives hasLayout to the element (for IE 7 and below). Part 1 of the hack needed for IE7 and below compatibilty.
**display: inline* is a hack second part of the hack needed for IE7 and below compatibility.
I occasionally need to add overflow: hidden for IE compatibility as well.
For your specific situation i think what you need is:
<html><head><style type="text/css">
#left {
display: inline-block;
background: red;
width: 20%;
height: 100%;
vertical-align: top;
}
#right {
display: inline-block;
background: green;
width: 80%;
height: 100%;
vertical-align: top;
}
</style></head><body>
<div id="left">Left</div><div id="right"><p>Right</p><p>Right 2</p></div>
</body></html>

I get the bad formatting.
You are being bitten by margin collapsing, a CSS ‘cleverness’ which is a pain as often as it is a boon. The margin of the <p> collapses outwards to become a top margin on the inline-block; this then behaves as a margin would on an ‘inline’ element would, pushing the vertical-alignment of the text line out.
You can stop it happening by removing the margins from ‘p’ elements and using padding instead. Alternatively place a non-empty element with no top margin at the top of the block and one with no bottom margin at the bottom.
Is this a Firefox bug
I think possibly yes, according to the spec's:
Margins of inline-block elements do not collapse (not even with their in-flow children).

inline-block
This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
visual rendering model

Related

overflow working with display inline

Overflow doesn't appear to be working when I use display: inline. I need to have the text inline, because it's something that appears at the top right of the webpage with "Hello," in front of it and a drop down arrow behind the name. If I remove the display: inline, the overflow works, but then the word in front and the image behind the name drops to a new row. I tried using inline-block, but that causes the text to actually wrap, though it's hidden, the name looks like I superscript it.
How can I make this work property?
div.actualName {
display: inline;
width: 40px;
height: 20px;
overflow: hidden;
}
This is
<div class="actualName">Bobby Joe Sanders</div>computer.
<br/>
Use inline-block but add the vertical-align:top rule. The default vertical alignment for inline elements is baseline.
div.actualName {
display: inline-block;
width: 40px;
height: 20px;
overflow: hidden;
vertical-align:top;
}
This is
<div class="actualName">Bobby Joe Sanders</div>computer.
<br/>
Using a styled span might be more useful in this particular example versus applying a div and class to style a few words in your line of text. Spans are more similar to in-line elements while divs are more like block elements. Let me know if it helps! Good luck.

How the block element works inside a floated div?

This is a continuation of the following question:
CSS Float - The content stays in the default stack position
When I am adding a block element(p element) inside box1, (which comes after the floated box0), the p element wraps as expected. However, it is not starting from the edge of the container. Please see the image.
Also, the behaviour is different when I add display: inline-block, or float:left, or overflow:hidden to the paragraph element. Can someone please explain these scenarios?
http://jsfiddle.net/jintoppy/xGm5E/3/
<div class="box0">Box 0</div>
<div class="box1">Box1 should wrap with text elements.
<p>But, what about block elements? Why it is behaving like this</p>
</div>
.box0 {
width: 100px;
height: 100px;
background-color: green;
float: left;
opacity: .5;
}
.box1 {
width: 200px;
height: 100px;
background-color: red;
}
p {
border: 1px solid #000;
}
There isn't enough room for the text in the p to start a new line there, so it starts only at the right edge of the float, giving the appearance of a gap underneath the float. If you give the p a slightly bigger top margin, there will be enough room for the second line of text to start directly underneath the float:
p {
margin-top: 1.2em;
border: 1px solid #000;
}
You can also increase the line-height as mentioned by others; this will cause the first line to be tall enough for the second line to have room to start underneath the float.
The reason why the boundaries of the p element don't shift completely out of the float is because the p element behaves exactly like .box1, since neither of them are floating. The text wraps in the same way I've described in my previous answer.
The reason why it behaves differently when you add display: inline-block, float: left or overflow: hidden is given in the comments on my previous answer:
overflow: hidden causes the box to generate a block-formatting context, which makes it immune to surrounding floats. That causes the entire box to shift outside of the float and sit right next to it instead.
(Technically, display: inline-block also causes the p element to act like an inline element itself, in other words, it is rendered inline just like the first sentence in .box1, but this has the same effect.)
When neither .box1 nor p are generating block formatting contexts, they are both participating in the same context, which is actually that of the root element. This is what causes them to interact with the float the way you are observing.
Block formatting contexts are a very complicated and broad topic that I would rather not get into myself, but the answer to this question has a nice visual explanation on how they work and how elements interact with one another around them in various scenarios.
I would assume this is to do with the line height.
p {
border: 1px solid #000;
line-height:1.5;
}
This works :)
add overflow: hidden; in box1 class.Try this once.

How to center things - display:block/inline-block

When centering things in html and css, I find two approaches - either applying on the element :
display:block;
margin:0 auto;
or using:
display:inline-block;
text-align:center; (on the parent element)
I always wonder which is better and why. Thanks!!
This is a classic and important question.
Elements can either be inline (meaning they all sit next to each other - like a span tag) or they can be block (meaning the stack up on top of each other - like a div tag).
Margin: auto, while a bit odd when you first see it, is the best and only way to center a block level (position static), element.
For anything that is display: inline (like a span tag) - the only way to center it is if you specify text-align: center on the parent. This will center everything display: inline inside it that is position: static;
Display: inline-block is a hybrid of the two that is relatively new (but supported as far back as ie7 if you use the hack mentioned in another answer). With inline-block, you get the benefits of inline, in that you can you stick a bunch of things next to each other and have them all be centered (think of a nav where all nav items are all centered), but ALSO have each item take advantage of some of the stuff you get with display: block - the most important one being HEIGHT.
Imagine a scenario where each nav item has a background image that is 80px tall - you can't make an inline element have a height of 80 - so you'd have to make each element display: block - only then can you give it a height. So to make them all appear next to each other, you'd float them. The problem is if you float them, you can't have them all be centered on the page unless you give a fixed width to the nav and margin: auto THAT. This means the nav has a fixed width - might be okay, but there are times when the nav has to have dynamic elements, different widths for different languages, etc.
Enter display: inline-block.
Block elements should always be centered using
.block {
margin-left: auto;
margin-right: auto;
width: 600px;
}
as stated by the w3c: http://www.w3.org/Style/Examples/007/center.en.html#block
text-align: center;
is well-named: use it to center texts.
Update
You can also use display: flex now:
.parent {
display: flex;
justify-content: center;
}
.block {
width: 200px;
}
There is no better way in this situation both approach will work and both are corrected. Just one thing display:inline-block doesn't work on IE7 (if you support this browser) you will need a hack to make it work
display: inline-block;
*display: inline;
zoom: 1;

Nested inline-block element is pushed up in FF / IE when overflow is set to hidden

This doesn't occur in Chrome. I am trying to implement an Ellipsis for the nested element. Has anyone else come across this and, if so, were you able to work around?
<span>bar <span class="foo">foo</span> bar</span>
span.foo {
display: inline-block;
overflow: hidden;
}
Fiddle
bar <span class="foo">foo</span> bar
span.foo {
display: inline-block;
text-decoration: inherit;
overflow: hidden;
}
Fiddle
Add vertical-align: top where you have display: inline-block.
This is due to the specification on overflow, which works only on block element and how line-height work.
Your outer span is by default display:inline. An inline element should not contains block elements. Although, setting it to display:block won't fix the problem.
The problem is the baseline for the text (outer element) is the same for the box of the inner element. So the box sit at the same height it should start the text (which leave a bit of white space underneat).
Anyway, it might be easier to understand with a demo.
If you set the line-height of the inner-span to lower than the text actual height, the box will conserve its size. Of course thirtydot solution is also valid.

Why does <span> break outside <div> when margin and padding is applied?

I know this is very basic CSS. How do I keep the span contained within the div? At the moment, the span extends outside the top and bottom of the div.
div {
width: 200px;
margin: 10px;
background-color: #ff0;
}
span {
margin: 5px;
padding: 5px;
background-color: #fc0;
}
<body>
<div>
<span>span</span>
</div>
</body>
To answer your question, this isn't just an issue with padding or margin, but also with width, display, and the box model.
jsFiddle
span {
display: inline-block;
}
This will honor any padding, margins, or widths you apply to the span.
Inline elements will not consume vertical padding and margin space. You can make the span display: block, but without more detail I don't know if that will achieve your goal.
The vertical padding, border and margin of an inline, non-replaced box (e.g. span) start at the top and bottom of the content area, and has nothing to do with the 'line-height'. But only the 'line-height' is used when calculating the height of the line box. Therefore you see an overlapping here: http://jsfiddle.net/Q9AED/
If you want to use a straightforward solution, you can use line-height rather than display: inline-block: using line-height.
display: inline-block works in Safari >= 2, Opera >= 9, IE >= 8, Firefox > 3. But you can imitate an inline-block in IE < 8: display: inline; zoom: 1.