Border flows over table but not paragraph with inline display - html

Using HTML and CSS.
I have text surrounded by a border using display:inline to make the border just larger than the text. The problem is that the border overlaps certain surrounding block-level elements. It overlaps <table> and <form>, but not <p>.
CSS:
.bordered {
padding: 0.6em;
border-style: solid;
border-width: 2px;
background-color: #FFFFCC;
border-color:#E8E800;
display: inline;
}
HTML:
<p>Some paragraph text</p>
<div class="bordered">Some bordered text</div>
<p>Some paragraph text</p>
<div class="bordered">Some bordered text</div>
<table><tr><td>Table text</td></tr></table>
Result:
Why is this? And why is it inconsistent between different block-level elements? I would expect that the table cell text be vertically aligned the same as the paragraph's.
Follow up: The whole reason why I have display:inline is so that the border is only as wide as the text. If using display:block (the default for <p>) then the border is as wide as the parent element.

The P tag isn't a vanilla block level element. Its default state in most user agents specifies some top and bottom margins. The TABLE tag doesn't. So the P tag is pushing the inline DIVs farther apart.
margins on P tag http://homepage.mac.com/estranged/images/css01.png
margins on TABLE tag http://homepage.mac.com/estranged/images/css02.png

It is doing the block level elements the way you expect. None of the block-level elements are overlapping.
But the bordered text is not a block level element because you made it an inline box. If you put the bordered text inside the <p>, or inside it's own <p>, or get rid of the display: inline, then you will get a box-level layout as you expected.
Update: yet another way to fix this would be to put the stuff above the table inside a div (that isn't inline) and then style that div with identical but transparent margins and padding.
.blockMargin {
padding-bottom: 0.6em;
border-width: 2px;
border-color: transparent;
}

Related

Why does the browser include adjacent elements after selecting a block level element wrapped in <a> tag?

As shown in the figure below, when I select the first a tag, the browser will include the following a tag, and the margin of the P element in the A tag is also collapsed with the .box2.How to explain this ?
.box1 {
width: 100px;
height: 100px;
background-color: antiquewhite;
}
p {
margin-top: 10px;
}
<div class="box1"></div>
<div class="box2">
<a href="#">
<p>abc</p>
</a>
abc
</div>
You have a block element (the p) inside an inline element (the link) then an inline element right after (the second link).
Here is a better illustration with some padding and outline.
p {
margin-top: 10px;
}
a:first-child {
padding: 0 5px;
outline: 1px solid red;
}
<div class="box2">
<a href="#">
<p>abc</p>
</a>
abc
</div>
The use of a block element inside an inline one will activate a complex mechanism where you will have an inline content before the block element and another one after the block element (highlighted by the outline). And since you have another a which is also an inline element, it will be on the same line with the second inline content.
The Devtool will show you the rectangular region that contain both inline contents (in red) and the block content (the p) and also the next a because it happen to be at the same line.
When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box. ref

How do adjacent elements actually work around floated elements? CSS

From the CSS Specification, I can gather that:
Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist.
So it means that any non positioned, non floated adjacent elements around floated elements should act as if the floated element did not exist, right? And it works perfectly if the former element has no content. But once it has some text, the text appears below the floated element which it should not and should move under the floated element.
<head>
<style>
#left {
float: left;
width: 50%;
}
#right {
width: 40%;
}
div {
padding: 2px;
background-color: brown;
}
section {
margin-left: 5px;
padding: 2px;
background-color: dodgerblue;
}
</style>
</head>
<body>
<section id="left">
<h2>Content</h2>
<p>Good stuff</p>
</section>
<div id="right">
FOOBAR
</div>
</body>
Here the text "FOOBAR" appears below the floated section, and does not move under. Even if we remove the width of the FOOBAR div, it appears right of the floated element and not under it.
How do adjacent elements actually work around floated elements. I have tried a lot of videos but none seem to explain it.
YOUR ANSWER
A float element will never overlap inline elements , that is why FOOBAR is not displayed under the floated element. This is because float element was initially invented to give an effect of text wrapping around images and not overlapping them.
WHY AND HOW THINGS ARE DISPLAYED IN YOUR EXAMPLE ?
Every text is inside a line box in css. According to css specs a floated element may come between edge of a container and edge of a line box . In that case line box will accommodate as many words as it can inside it and give an effect of text wrapping the float element. In your case line box of FOOBAR can not accommodate FOOBAR inside it , besides floated element cause there is no space . So the line box breaks down below the floated element and hence FOOBAR is displayed inside its line box below the float. -

Why is the container div smaller that its content?

In the following example, the <div> is smaller then its content.
Why? And how do I fix it?
.switcher {
border: 1px dashed green;
}
.switcher a {
padding: 30px;
background: orange;
}
<div class=switcher>
<a href=#>first</a>
<a href=#>second</a>
</div>
From the specs:
9.4.2 Inline formatting contexts - 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.
Although padding can be applied to all sides of an inline element, but only left and right padding will have an effect on the surrounding content.
The <a> tag is an inline element by default. You can set it to inline-block, so that both horizontal and vertical padding will be respected. As an inline-block element is placed as an inline element (on the same line as adjacent content), but it behaves as a block element.
.switcher {
border: 1px dashed green;
}
.switcher a {
padding: 30px;
background: orange;
display: inline-block; /*new*/
}
<div class=switcher>
<a href=#>first</a>
<a href=#>second</a>
</div>
You can contain the the a elements by placing a overflow: hidden or overflow: auto to the switcher class
You can make <a> tags display block ... as anchor tags are not by default similar as <div> p h1 h2
<a> tag and span tag are inline tags. these elements remain inline until you apply some property to display as block.
so both display: inline-block and display: block will work.

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/

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