Align div that are inline-block - html

Can anyone explain the behaviour of the divs here http://jsfiddle.net/Z7z5Q/ ? I wonder, why they are not aligned on one line ? And why adding text to div moves other divs ?
Here is html and css:
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
<title>My Social Network</title>
</head>
<body>
<!--Add your HTML below!-->
<div class="friend">Some text in more than two line, actually in 3</div>
<div class="family">Some text in two line</div>
<div class="friend" id="best_friend"></div>
<div class="enemy" id="archnemesis"></div>
<div class="friend">Some text</div>
<div class="family"></div>
<div class="friend"></div>
<div class="family"></div>
</body>
</html>
Css:
div {
display: inline-block;
margin-left: 5px;
height:100px;
width:100px;
border-radius: 100%;
border: 2px solid black;
}
.friend {
border: 2px dashed #008000;
}
.family {
border: 2px dashed #0000FF;
}
.enemy {
border: 2px dashed #FF0000;
}
#best_friend {
border:4px solid #00C957;
}
#archnemesis {
border: 4px solid #CC0000;
}
Thanks. Will appreciate links to docs or articles.

The elements are aligned... but not in the way you intended it, obviously ;)
The key to your problem is the property vertical-align.
First remove border-radius in order to better see the boxes.
Then add vertical-align: middle;: problem solved (see fiddle)
Content or not, each box is now aligned relatively to its fixed height (you fixed it to 100px).
What happened in the first place without vertical-align: middle;? Change the value for baseline: you're back to the original problem. This is the default value, the one you do want when displaying text in spans for example or a label and the text of a text field, whatever the padding and margin on both. But with text forced to occupy 2 or 3 lines (boxes are 100px wide whatever their content), the baseline is very different from what you'd expect, it's the baseline of the content aka the last line of text.
Same with empty div: as they lack content to align with, their baseline is their bottom side (not so sure about this one, but that's what seems to happen).
Add a single character or a non-breakable space in some empty div: their baseline is now completely different from an empty div. See other fiddle
The same phenomenon happens with a tall image lost in a paragraph of text; you can align it with vertical-align but the difference is that it's easier to see what's happening. Here you haven't a single occurence of "normal" text so spotting it is a bit harder.
Why float: left; does work here? It'll take each box, all of the same height, and align it relative to the box, not to its content. But then you've to manage clearing and 1px more on a box can break the alignment of all the following boxes...

inline-block is an attribute with a number of curiosities. In this example, you can plainly see that removing height: 100px from the div CSS rules will result in the elements having their text aligned, which isn't so obvious with the flashy circle-shaped dashed multicolored borders. So to fix this, you would apply vertical-align: top. (source)
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.
(from a great answer from another thread)
In comparison, floats align at the top by default.

align on one line
div {vertical-align: middle;}

Adding a float:left; will solve this problem see here: http://jsfiddle.net/Z7z5Q/5/
Also adding vertical-align:top; will solve it as well: http://jsfiddle.net/Z7z5Q/7/
This is because inline-block behaves weird with white spaces in html.

Related

css block within block float right

Most embarassed to be coming to others for help with this if i'm honest, but i have reached my 1 1/2 hr sanity limit.
I want to have a block (with a coloured border) postioned on the right of the page with width suitable to the text content + padding. I want it to reserve the whole row for itself without other element below creeping into the space left on the left.
I realised early on that any width = 100% would mean that the whole row would have the border rather then just the content I wanted and various experiments with float lead to the space on the left being occupied with elements creeping into the space from below. To remedy i have created a containing block with 100% width and display = block and put the border round the child div. Still doesn't work! I have the #costblock being the container and the #costs being the content:
#costsblock {
display: block;
width: 100%;
}
#costs {
border: 1px solid #008eaf;
padding: 10px 5px;
width: auto;
text-align: right;
}
<div id="costsblock">
<div id="costs">The text</div>
</div>
I have experimented with virtually all combinations of display and width and float on both the parent and the child and nothing works - I either get the whole row surrounded by the border or, if I dare to put a float: right anywhere at all then the space on the left gets filled wih elements creeping in from below.
I think that I need to contrain the child width to what is necessary to hold the text only, but I can't seem to get that working!
Your approach with the extra container element did not work, because #post is a block element, and as such still takes the whole width (unless you tell it otherwise). Anyway, there is no need for an extra element.
I want it to reserve the whole row for itself without other element below creeping into the space left on the left.
Then all you have to do is clear the float on the next element:
#costs {
float:right;
border: 1px solid #008eaf;
padding: 10px 5px;
}
#next {
clear:right;
}
<div id="costs">The text</div>
<div id="next">I am the next element following the floating one.</div>
You can use float, but be sure to have an element that has clear: both below the floating element to prevent any elements 'creeping into the space left'.
For example:
<div id="costsblock">
<div id="costs">The text</div>
<div style="clear: both"></div>
</div>
Full example: http://jsfiddle.net/thijs_s/xxc9nk1t/
You should be able do solve this by changing display to inline-block for the child and then setting text-align to right for the parent element:
#costsblock {
text-align:right;
}
#costs {
border: 1px solid #008eaf;
padding: 10px 5px;
display:inline-block;
}
It is not necessary to set display:block for a div element, since they are defined as block level elements by default.

Fixed padding in contenteditable element

The padding of a textarea is always fixed. When the text content of the textarea is scrolled, the padding remains near the edges.
The padding of a contenteditable element behaves differently. When the text content of the element is scrolled, the padding moves with it.
This demo illustrates the difference.
Can a contenteditable element by styled so its padding behaves more like textarea padding, staying in place while the text content is scrolled?
The answer to your specific question of whether a non-textarea "contenteditable" block level element's padding can behave like a textarea's is "no."
There is likely a way to achieve this look by adding additional elements to your div, but the padding of your div will always behave as padding is designed to.
Your padding issue has nothing to do with the "contenteditable" property. You could take the "cnotenteditable=true" off of your div, and the padding behaves the same way. Padding "clears an area around the content" of the element, which in this example is the text in your div. The padding will always remain around the text, not around the inside of the div.
<style type="text/css">
contenteditable] {
outline: 0px solid transparent;
}
</style>
<body>
<div style="padding:20px">
<div contenteditable="true"></div>
</div>
</body>
A reply in 2019. Set:
border: 10px solid black;
background: black;
color: white;
Works perfectly.
fiddle: https://jsfiddle.net/shill/2k81acux/

Difference in spacing between display block and inline-block

Came across something very curious today I can't figure out the reason for.
For this HTML:
<div class="a"><div class="b"></div></div>
And CSS:
.a {
background: blue;
}
.b {
display:inline-block;
height: 30px;
width: 30px;
background: red;
}
I would expect the outer "a" div to be just as tall as is needed to contain "b", 30px tall. But when rendered "a" is 35px tall. There are 5 pixels of emptiness below "b". Why?
See http://jsfiddle.net/Pb2q9/
I've tried this on Chrome and Firefox and they both give the same output.
Curiously if you change "b" to be display:block that extra space at the bottom goes away. Can anyone explain why these two scenarios render differently? What is it about inline-block that dictates that 5px of space should exist?
EDIT:
Stranger still I found that if you change the HTML to
<div class="a"><div class="b">x</div></div>
Note the single "x" character in the b div the extra 5px at the bottom goes away!
The vertical white space you see is due to the line-height property in play. If you set line-height: 0 on the parent element, you can see that the spacing goes away - http://jsfiddle.net/Pb2q9/9/
When working with inline-block elements and yet wanting to achieve the layout behavior of block-level elements, remember to set both font-size and line-height to 0.
It is a normal behaviour of inline block elements. There is always white space.
If you want to remove white space of element, change fontsize of parent container to 0px
.a{font-size:0px;}
.b{font-size:16px;}
Fiddle

Baseline shifts for block-level element when no content inside

I'm working through a CSS problem at http://www.codecademy.com/courses/web-beginner-en-jNuXw/0/1?curriculum_id=50579fb998b470000202dc8b (actually, just helping a friend learn HTML/CSS) and came across a curious issue. If you erase the content in any of the <p> tags within a <div>, the div shifts upward. For example, delete the word 'Mom' without deleting the <p>. As best as I can figure out, this is because the element is set to vertical-align: baseline and for some reason the baseline is changing. I just can't figure out exactly why it's changing or what is causing it to change.
To be clear, I'm not asking for help to get the div's to align. That's simply a matter of setting their vertical-align to 'top'. I'm just trying to understand how the document flow is calculated. The specific question is: why does the empty div shift upwards?
DEMO: jsFiddle
UPDATE: Here is a new jsFiddle - http://jsfiddle.net/tonicboy/2DtTw/3/ which removes a lot of rules to boil the problem down to a simplified use case. From this, we can see that when a <p> tag has text in it, the baseline of the parent <div> is set at the baseline of the text. When you remove the text, the baseline of the parent <div> is set to the bottom of the <div>. Why is that?
HTML:
<div class="friend" id="best_friend"><p>Arthur</p></div>
<div class="friend"><p>Batmanuel</p></div>
<div class="friend"><p>Captain Liberty</p></div>
<div class="friend"><p>The City</p></div>
<div class="friend"><p>Justice</p></div>
<div class="family"><p></p></div>
<div class="family"><p>Dad</p></div>
<div class="family"><p>Bro</p></div>
<div class="family"><p>Sis</p></div>
<div class="family"><p>Rex</p></div>
<div class="enemy"><p>Baron Violent</p></div>
<div class="enemy"><p>The Breadmaster</p></div>
<div class="enemy"><p>The Deadly Nose</p></div>
<div class="enemy"><p>Dinosaur Neil</p></div>
<div class="enemy" id="archnemesis"><p>Chairface</p></div>
CSS:
div {
position: relative;
display: inline-block;
height: 100px;
width: 100px;
border-radius: 100%;
border: 2px solid black;
margin-left: 5px;
margin-top: 5px;
text-align: center;
}
div p {
position: relative;
margin-top: 40px;
font-size: 12px;
}
.friend {
border: 2px dashed green;
}
.family {
border: 2px dashed blue;
}
.enemy {
border: 2px dashed red;
}
#best_friend {
border: 4px solid #00C957;
}
#archnemesis {
border: 4px solid #cc0000;
}
I think I've mostly figured out the reason, after digging through W3C specs. Here are three key items from the spec which may explain this behavior:
"Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose."
When you delete the text, the <p> element is no longer in-flow.
"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."
Because there are no in-flow elements within the parent div, the baseline becomes the bottom margin.
Because the div's are set to display: inline-block, their default vertical alignment is 'baseline'
Because the other div's have in-flow elements (the <p> tags), their baseline is set to the text baseline.
And that is why the empty box's bottom margin aligns with the baseline of the <p> tags in the other div's.
The baseline of the element is shifting because the text inside the <p> determs the baseline height:
In an inline formatting context, boxes are laid out horizontally, one
after the other, beginning at the top of a containing block.
Horizontal margins, borders, and padding are respected between these
boxes. The boxes may be aligned vertically in different ways: their
bottoms or tops may be aligned, or the baselines of text within them
may be aligned.
source: http://www.w3.org/TR/CSS2/visuren.html#block-formatting
The height of each inline-level box in the line box is calculated. For
replaced elements, inline-block elements, and inline-table elements,
this is the height of their margin box; for inline boxes, this is
their 'line-height'.
source: http://www.w3.org/TR/CSS2/visudet.html#line-height
CSS assumes that every font has font metrics that specify a
characteristic height above the baseline and a depth below it. In this
section we use A to mean that height (for a given font at a given
size) and D the depth. We also define AD = A + D, the distance from
the top to the bottom.
source: http://www.w3.org/TR/CSS2/visudet.html#inline-box-height
So with this block being a inline-block and baseline is calculted based on the line-height which is calcuted by different font types. Because this <p> has no font/text the baseline will not be positioned.
place all the line-height: 0; and you will see that the one with no text/font doesn't react like the other does:
jsFiddle
So why are the other two elemets shifting that have text in them?
Well it's because the text excist of two lines of text. The margin of the text is bigger and uses more space, thus the baseline is pushed further

CSS vertical-alignment - what am I not understanding?

I'm messing around with everyone's favorite CSS topic, vertical alignment. I found a little case that makes no sense to me, which probably means I'm failing to understand something about CSS.
I have the following HTML (it's for exploration code, so please excuse the inline styles):
<div style="height: 40px; line-height: 40px; vertical-align: middle; border: 1px solid blue; margin: 1em 2em;">
<span style="background-color: Blue; height: 30px; width: 30px; margin: 5px 1em; display:inline-block;"> </span>
<span>Some text</span>
</div>
This displays a blue box and some text, both vertically centered. But if I replace the with a regular space character, the text in the other span is no longer centered. I created a JSFiddle that demonstrates this.
My question is - why does changing from an to a space character in the first span change the vertical alignment of the second span?
You are confused how the vertical-align property works. It doesn't apply to block-level elements. When it is set on a non-table-cell and non-inline element, the property is actually applied to all the inline text inside that element, not to the element itself.
When you use a regular space, the space isn't actually "rendered" by the browser because it's not really content. Therefore, the entire box becomes the line of text (since you're displaying it as inline-block) and the baseline is set at the very bottom of the parent against the black border at the bottom, which is why the text appears way down there.
When you use a non-breaking space, the space is content and does get render, which moves the baseline for the text up to where the text would actually appear inside the blue box. It's not actually centering the text. It's nowhere near centered on my screen. The baseline has just moved based on the content. You'll notice from this example that it also changes the line-height of the continuing text.
An easy way to fix this is to float the blue box to the left and then manually set a line-height for the rest of the text to follow. See the jsFiddle.
<div style="height: 40px; line-height: 40px; vertical-align: middle; border: 1px solid blue; margin: 1em 2em;">
<span style="background-color: Blue; height: 30px; width: 30px; margin: 5px 1em; float: left;"></span>
<span>Some text that continues on and on and on sothat you can see what is actually happening here blah blah blah blah blah</span>
</div>​
The entity stands for non breaking space and is a variant of the space char.
They aren't the same.
In fact the entity prevents an automatic line break
Read more about at wikipedia
Moreover, the white space result as an "empty" span and that will cause that "bad behaviour"
May help?:
http://jsfiddle.net/mFryV/18/