Is this a bug in CSS? [duplicate] - html

This question already has answers here:
Why my inline-block divs are not aligned when only one of them has text? [duplicate]
(4 answers)
Why does this inline-block element have content that is not vertically aligned
(4 answers)
My inline-block elements are not lining up properly
(5 answers)
Why is this inline-block element pushed downward?
(8 answers)
Understand inline-element, vertical-align, line-box and line-height
(1 answer)
Closed 4 years ago.
This might sound like an outdated topic since no one still uses inline-block property thanks to flex-box and grid but I was wondering about it and I would like to inquire about it.
When creating two divs and assigning them both to display as inline-block and then adding any element inside one of them, the result is quite strange, where the div which contains that element will slide down to the bottom of the other div minus the height of the added element.
div {
display: inline-block;
width: 100px;
height: 150px;
background: gray;
}
<div id="left">
<span>Text</span>
</div>
<div id="right"></div>
To fix the issue it's only enough to align the div vertically to the top, but what is strange too is that we get the same result even if we align the other div which is not affected without aligning the affected one, so what exactly is happening here?
div {
display: inline-block;
width: 100px;
height: 150px;
background: gray;
}
#left{
vertical-align: baseline;
}
#right{
vertical-align: top;
}
<div id="left">
<span>text</span>
</div>
<div id="right"></div>
UPDATE:
To clarify things more I removed the child element and added a text outside the two divs, and added two more divs, now all divs are without a flow content, but the first two both of them have a top property while the last two are different, one top and the other is baseline:
div {
display: inline-block;
width: 100px;
height: 150px;
background: gray;
}
.right{
vertical-align:baseline;
}
.left{
vertical-align:top;
}
Text
<div class="right"></div>
<div class="left"></div>
<br>
Text
<div class="left"></div>
<div class="left"></div>
In the first case the Text aligned to the top and in the next aligned to the baseline of the divs even they don't have a flow content.

The reason this happens, is because the default vertical-align value for inline elements is baseline.
Then the question becomes: what is the baseline of an inline-block element? Here, we have to make a distinction between elements with and without flow content:
For elements with flow content, such as the left div in your question, the baseline is the same as the baseline of the last content element.(*) For the left div, this corresponds to the baseline of the inner span.
(*) There are some additional considerations when setting the element's overflow, but I'll leave that out of scope.
For elements without flow content, such as the right div in your question, the baseline is the bottom of the element's margin box. For the right div, this corresponds to the bottom of the div itself.
So, to summarize: the reason you're seeing a vertical shift is because the elements are vertically aligned according to their baseline, and the baselines for elements with and without content are calculated differently.
To test this out, just try adding some text to the right div, and you'll see how both baselines are now the same.
div {
display: inline-block;
width: 100px;
height: 100px;
background: gray;
}
<div id="left">Text</div>
<div id="right">Other text</div>
By animating the font size, the example below demonstrates even more clearly how changes in the baseline affect vertical positioning:
div {
display: inline-block;
width: 100px;
height: 100px;
background: gray;
}
#left {
transition: all 2s ease;
animation: anim 2s infinite linear alternate;
}
#keyframes anim {
0% {font-size: 100%;}
100% {font-size: 300%;}
}
<div id="left">Text</div>
<div id="right"></div>

The display: inline-block Value
Compared to display: inline, the major difference is that display: inline-block allows to set a width and height on the element.
Also, with display: inline-block, the top and bottom margins/paddings are respected, but with display: inline they are not.
Compared to display: block, the major difference is that display: inline-block does not add a line-break after the element, so the element can sit next to other elements.
and
excuse me textarea is inline-block, but what line is correct,
the browser think the bottom of second inline-block is position of line so
when he go to draw children he see the textarea must be inline and change position of it to the bottom of second inline-block is position of line and because it is any padding and it position are relative it cause to parent div move to bottom just for textarea be inline

Related

Why when i specified a width property in my p element the text doesn't flow around the div element? Using floats

Why when I specify a width property in my p element, the text doesn't flow around the div element ?
I know one the solution to this is to have float: left; in my p element too. Just looking for explanation, not finding for solution
div {
width: 200px;
height: 100px;
background-color: green;
opacity: 0.2;
float: left;
}
p {
background-color: yellow;
width:10px;
}
<div></div>
<p>Lorem Ipsum</p>
Block elements don't wrap around floats, their contained line boxes do. But since the width of the p element is less than that of the div element, there's no space for the line boxes of the p element to go beside the div element, so the first opportunity for the line box to be placed is below the div element. So wrapping around is exactly what the line box of the p element is doing.
It's probably a display issue.
You can try to set a display:inline-block to your <p> tag.
But I think to put one aside another you can better use flex-box:
Wrap your two or more elements inside a div or a section, and give this div a property display: flex.
By default, it will align those elements horizontally, and the property align-items: center is to align those elements based on the div's center.
<div id="container">
<div>One</div>
<p>Another</p>
</div>
<style>
#container {
display: flex;
align-items: center;
}
#container div {
/* ... Your previous div style */
margin-right: 15px;
}
</style>

How can I easily align an element with "display: inline-block" and "overflow: hidden"?

inline-block elements using overflow: hidden position themselves so their bottom margin is the baseline. From http://www.w3.org/TR/CSS2/visudet.html#leading:
The baseline of an 'inline-block' is the baseline of its
last line box in the normal flow, unless it has either no
in-flow line boxes or if its 'overflow' property has a
computed value other than 'visible', in which case the
baseline is the bottom margin edge.
In practice this means these elements are shifted up unexpectedly; e.g., inside a <td> the element will not be vertically centered. A simpler example:
div {
border: 1px solid red;
text-decoration: underline;
}
.ib {
display: inline-block;
}
.h {
overflow: hidden;
}
<div>
<div class="ib">Visible</div>ABgjh</div><br>
<div>
<div class="ib h">Hidden</div>ABgjh</div>
the div with overflow: hidden doesn't share the same baseline as its surrounding line.
I'm looking for a simple way to make that div align itself as if it was following the normal rules for inline-block elements. Basically I want to write a custom element that "just works" whether its consumer applies a vertical-align style, or places it inside a <td>, etc.
This table has an example where I want the element to vertically center itself but instead it pushes itself up (and the rest of the line down).
This fiddle has more examples showing how different pairings of vertical-align behave unexpectedly when one element is display: inline-block; overflow: hidden.
To be clear, this question is asking whether a <div style="overflow: hidden"> can be wrapped in such a way that it can be treated as a regular inline-block element, positioning itself intelligently, without JS or font-based pixel adjustments. I'd want to be able to apply styling to the final component in order to position or align it as I please, as if it were a regular inline-block element.
I am not sure what browsers you are looking to support but if you wrap your DIV with display: flex; you wont get that vertical offset. You can see it here:
div {
border: 1px solid red;
text-decoration: underline;
}
.ib {
display: inline-block;
}
.h {
overflow: hidden;
}
.flex {
display: flex;
}
<div>
<div class="ib">Visible</div>
ABgjh
</div>
<div class="flex">
<div class="ib h">Hidden</div>
ABgjh
</div>
I normally don't use flexbox because of the lack of browser support but perhaps this is the simple solution you're looking for. Hope that helps.

Empty div vs div with text having inline-block property

Want to know the reason for this behavior.
CSS
div {
display: inline-block;
margin-right: 2px;
width: 20px;
background-color: red;
}
Empty div
<div style="height:20px;"></div>
<div style="height:40px;"></div>
<div style="height:60px;"></div>
<div style="height:80px;"></div>
behavior: element increases from bottom to top (height)
div with text
<div style="height:20px;">20</div>
<div style="height:40px;">30</div>
<div style="height:60px;">40</div>
<div style="height:80px;">50</div>
behavior: element increases from top to bottom (height)
see it in action: http://jsfiddle.net/8GGYm/
Basically it got to do with the way that vertical-align: is calculated. So if you put vertical-aling:bottom; attribute in the css then you will notice it will be the same with and without text.
you can read the this for more details.
When the div has no content, padding is not drawn in the box (i.e. when when 0, if there is content, the browser calculates where the padding would be). so there is a little difference in calculating with and without text.
Hope this is helpfull.
please see here: http://jsfiddle.net/dd24z/. By default text is vertical-align: top, but you can change that behavior:
div {
display: inline-block;
margin-right: 2px;
width: 20px;
background-color: red;
vertical-align: bottom;
}
http://www.w3.org/TR/2008/REC-CSS2-20080411/visudet.html#line-height
'vertical-align': baseline
Align the baseline of the box with the baseline of the parent box. If the box doesn't have a baseline, align the bottom of the box with the parent's baseline.
Add
vertical-align: bottom;
to your CSS. Hope it works as you want.
I guess this can be explained by the text alignment, independently from divs.
Text, when placed in a div, is vertically aligned to top-left by default. Those divs without text align beside each other (inline-block) expanding the page downwards. If you add another div, you'll see the second header going further down.
<h1>Empty div</h1>
Some text
<div style="height:20px;"></div>
<div style="height:40px;"></div>
<div style="height:60px;"></div>
<div style="height:80px;"></div>
continuing here
<h2>Div with text</h2>
Some text
<div style="height:20px;">20</div>
<div style="height:40px;">40</div>
<div style="height:60px;">60</div>
<div style="height:80px;">80</div>
continuing here
...
div {
display: inline-block;
margin-right: 2px;
width: 20px;
background-color: red;
}
Fiddle
In the above fiddle, you can see that the text line is the "guideline".
Maybe this is the explanation: once the divs have text in them, they will align it with the surrounding text and, if inexistent, then they align their bottom line.
I'm sorry, maybe not very clear but I hope you understand my view.

Why are these two identical inline divs misaligned when one has text and the other doesn't?

So here are two identical divs:
HTML
<div id="left"></div>
<div id="right"></div>
CSS
#left, #right
{
width: 100px;
height: 40px;
border: 1px solid gray;
display: inline-block;
}
These render just fine, as two identical boxes side-by-side (fiddle: http://jsfiddle.net/URy59/).
But with text in one div, and none in the other, they're misaligned! (fiddle: http://jsfiddle.net/URy59/1/)
This...
<div id="left"></div>
<div id="right">Right</div>
...results in:
This behaviour is reproducible using <span> as well.
What causes this, and why? What's a good solution to this?
The short answer: set the vertical-align property to top.
The longer answer: An inline element's default vertical alignment is baseline. When your divs have no content, they line up fine. However when you added the text, the browser then will move the div downward so that the text sits on the baseline:
By changing the alignment to top, you align the divs the way you need.
jsFiddle example
You need to vertically align your elements:
#left, #right {
...
vertical-align: top;
}
JSFiddle demo.

display: inline-block not working unless first div floated:left

I am a relative novice in the world of CSS so please excuse my ignorance! I am attempting to use the following CSS to align two divs horizontally:
.portrait {
position: relative;
display:inline-block;
width: 150px;
height: 200px;
padding: 20px 5px 20px 5px;
}
.portraitDetails {
position: relative;
display:inline-block;
width: 830px;
height: 200px;
padding: 20px 5px 20px 5px;
}
Unfortunately, unless I remove the display: inline-block from the .portrait class and replace it with float:left the .portraitDetails div block appears underneath the first div block. What on earth is going on?
Since you provided a working example, the problem seems to be more clear now.
What you have to do is simply remove display: inline-block and width: 830px properties from the right div. Of course remember to NOT add the float property to it.
People sometimes forget what is the purpose of the float property. In your case it is the image which should have float property and the image only. The right div will remain 100% wide by default while the image will float it from the left.
HINT: If the text from the div is long enough to float underneath the image and you want to keep it "indented" at the same point then add the margin to the div with a value equal to the image's width.
The problem with display: inline-block; is that the siblings having this property are always separated by a single white-space but only if there are any white-spaces between their opening and closing tags.
If the parent container has fixed width equal to the sum of the widths of these two divs, then they won't fit because this tiny white-space pushes the second div to the next line. You have to remove the white-space between the tags.
So, instead of that:
<div class="portrait">
...
</div>
<div class="portraitDetails">
...
</div>
you have to do that:
<div class="portrait">
...
</div><div class="portraitDetails"> <!-- NO SPACE between those two -->
...
</div>