Float: Left with different display types - html

I am just learning some more about displays and floats, and noticed that when I apply a float left to all display types, they then all behave like a display: inline-block.
This is a jsfiddle without the float left:
https://jsfiddle.net/j3jjpaxr/
And here is one with the float left:
https://jsfiddle.net/xhhbgsu1/
CSS:
.first {
background-color: #435671;
}
.second {
background-color: #135671;
}
.third {
background-color: #935671;
}
.inlineblock {
display: inline-block;
}
.inline {
display: inline;
}
.block {
display:block;
}
.testDiv {
text-align: center;
float:left;
width: 33%;
height: 100px;
}
Can anyone explain why this happens, I would have expected the inline elements to at least keep their size?

For inline elements the width is ignored (MDN: "An inline element occupies only the space bounded by the tags that define the inline element.")
Also from MDN:
As float implies the use of the block layout, it modifies the computed
value of the display values in some cases:
Specified value: inline
Computed value: block
...
Thins means that when you set a float to an inline element, it's display value is forced to block. That's why you get the effect you described in your question.
https://developer.mozilla.org/it/docs/Web/CSS/float
https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements

It is not behaving like inline-block.
inline-block elements have a default spacing between them. Check your first fiddle.
float makes it behave like block element, which floats either left or right.

The float CSS property specifies that an element should be taken from
the normal flow and placed along the left or right side of its
container, where text and inline elements will wrap around it.
Src: https://developer.mozilla.org/en-US/docs/Web/CSS/float
This simply means that an element, inline or block, behaves like a inline block but without the white space an inline element has.

Related

Right floated element below regular paragraph with width

HTML:
<div id='container'>
<p>This is some text contained within a small-ish box. I'm using it as an example of how placing your floated elements in different orders in your HTML can affect your layouts. For example, take a look at this great photo placeholder that should be sitting on the right.</p>
<img src='image.gif'>
</div>
CSS:
#container {
width: 280px;
margin: 0 auto;
padding: 10px;
background-color: #aaa;
border: 1px solid #999;
}
p {
width: 100px;
}
img {
float: right;
}
Result: https://jsfiddle.net/y9Lqjm1f/
Why if the paragraph's width is small enough does the floated right element not appear at the top of the container div?
Because the img element is placed below the p element which follows the normal flow as a block element.
img's separate flow, which results from it having a float style applied, only begins below the p.
If you added another p below the img it would follow normal layout flow as if the img did not exist, like so: https://jsfiddle.net/mkarajohn/y9Lqjm1f/1/
In short, in order for the img to appear to the top, it has to be placed first in the markup, like so: https://jsfiddle.net/mkarajohn/y9Lqjm1f/2/
Also see this about float and block elements
In general:
Floated elements respect previous block elements' layout flow, meaning they appear below the previous block element
Block elements following the floated element disregard the floated element, and keep their normal layout flow as if the floated element did not exist.
p and img tags are block level elements. They create new line for next element. So, float: right; property in img apply in new line.
You can use display: inline-block; for both p and img tags.
codepen

Why anchor tag does not take height and width of its containing element

Here is my JsFiddle
When I inspect the size of the anchor tags with Chrome developer tools it shows me 144px*18px for the 1st element and 310px*18px for the 2nd element.
I want to know why it does not take the height and width of the containing element and how it is being calculated.
.gallery {
background-color: #abcdef;
}
.gallery img {
display: inline-block;
margin-left: 20px;
margin-top: 20px;
}
.normal {
height: 160px;
width: 110px;
border: 5px solid black;
}
.wide {
height: 160px;
width: 280px;
border: 5px solid black;
}
<div class="gallery">
<img class="normal" src="">
<img class="wide" src="">
</div>
The CSS 2.1 spec says
The dimensions of the content area of a box — the content width and
content height — depend on several factors: whether the element
generating the box has the 'width' or 'height' property set, whether
the box contains text or other boxes, whether the box is a table, etc.
Box widths and heights are discussed in the chapter on visual
formatting model details.
The <a> element defaults to a display value of inline. Its contents participate in the layout so it is a non-replaced element.
For height, the spec says:
10.6.1 Inline, non-replaced elements
The 'height' property does not apply. The height of the content area
should be based on the font, but this specification does not specify
how.
So 18px is arrived at from a single line of text, taken from the font metrics. Neither the larger image content, nor the containing block size plays any part.
For width, the spec says
10.3.1 Inline, non-replaced elements
The 'width' property does not apply. A computed value of 'auto' for 'margin-left' or 'margin-right' becomes a used value of '0'.
in other words, the width is determined by the <a> element's contents, paddings, borders and margins.
For the first <a> element that's 114px (contents - image plus one space) + 20px (left margin) + 2x5px (left and right border) = 144px
For the second <a> element that's 280px (contents - image) + 20px (left margin) + 2x5px (left and right border) = 310px
Just need to account for the spaces. The elements are being laid out in a line box in a inline context, so the spaces at the start of the first <a> element and at the end of the second <a> element are being dropped. The spaces at the end of the first <a> element and the start of the second <a> element are being collapsed into one space. When spaces are collapsed, it's always the first space which remains, which in this case is the one at the end of first <a> element, so that's why a space participates in the width of the first <a> element but not in the width of the second one.
use display:inline-block in anchor
.gallery a{
display:inline-block;
}
here is updated jsFiddle File
also remove margin from image and add it to anchor
.gallery a{
display: inline-block;
margin-left: 20px;
margin-top: 20px;
}
anchor is always display: inline by default. To make anchor took it's child space, you must give him a display:block, or in this case, display:inline-block so that they will be inlineand block.
a{
display:inline-block;
}
JSFiddle
Read this question for more info.
The a tag's need to be styled as well
I added
.gallery a {
display: inline-block;
}
I had the same issue, for example, I have HTML generated by GitHub flavored markdown, so I can have paragraphs containing anchor with images inside.
Actually setting display: inline-block in anchors did not work for me; I did also set display: block in images. Using Sass nested something it looks like this:
.gallery {
a {
display: inline-block;
img {
display: block;
}
}
}
Instead of applying {display: inline-block} on <a>
, try applying {float: left} on the child of <a>. The height of the <a> would now match the height of the child.
Another solution is to use a negative margin-bottom attribute with the img element (the size depends on the font, so, it's better to be sure of the used font by using an #font rule, 0.2em was fine for the font I use, moreover, using em units is a good idea as the size depends on the font, so, if you change the font-size later, you won't have to change this CSS code):
HTML:
Something, <img src="whatever.png" alt="Whatever" />, something else.
CSS:
a:link {
display: inline-block;
}
img {
margin-bottom: -0.2em;
}
That way, all the texts are well aligned with the image, whatever it's in a link or not, I've done that to have all image + text blocks displayed the same way, but you might use a > img instead of just img in the above code.
By the way, I came up with this solution because I had something like:
a[something]:link::after {
content=" something to add"
}
so, the img {display: block;} was not an option for me as the “ something to add” would have been under the image and the rest of the text after, this would have cut the reading flow.

CSS: div p, a not applying to a tag

I have a very simple HTML with CSS code, don't understand why, the css rule isn't applied to the a tag, but it works on p tags. If I wrap the a tag inside a p tag, the css works, but I can't understand why it doesn't work without wrapping it.
Here's a full example http://jsfiddle.net/juaning/84Xn2/
css: div p, a {
margin-top: 35px;
font-size: 24px;
}
html: <div class="family">
Luigi
</div>
The box model of an a tag is different than the box model of a p tag. Add this one line:
div p, a {
display: inline-block;
By default, an a tag has the display: inline box model, so that you can easily place it in the same line as regular text (i.e. inside a p). The p tag is more of an entity on it's own, always being a 'block' or 'box' of text, therefore the p has display: block; by default.
Fiddle: http://jsfiddle.net/ECAbd/1/
a tag is an inline element, and p is a block level element, margin won't apply to inline element, and hence you need to make your a tag, block or inline-block.
div p, a {
margin-top: 35px;
font-size: 24px;
display: block;
}
Now, here, again it depends, what you want your a tag to be, if you want multiple a tags to line up inside your div you will have to use inline-block and if you use display: block; it will take entire horizontal space and will render another element below it.
Take for example you've a horizontal menu, where you line up your elements, you will probably use ul and li but suppose you take div for each menu item, you may need display: inline-block;, this will have all properties of block level element, but it will render them inline leaving the other space empty for other elements to take up, but if you want to render each element below one another, you need to use display: block;(not for div tag or p tag, they are block level elements by default, inorder to change their behavior, you need to mention that in your CSS)
List of block level elements
List of inline elements
Anchors have display: inline by default, while paragraphs are (if I recall) display: inline-block. Margins do not apply to inline elements. You can easily fix this by explicitly setting display to inline-block in your CSS.
Add this rule to the css -
display: block;
Another solution replace your code "div p, a" by following
div p, div a {
font-size: 24px;
line-height: 100px;
display: inline; }
Notice I used line-height (same as box height) to make vertical align center rather than margin-top. But this is not the solution for multi line.

Why isn't width:200px applied to this label?

In this example, I'm setting width:200px on form labels.
This is not being applied for some reason, and the field appears 0 width when viewed in Chrome Dev Tools.
Any idea why?
label is an inline element, like a span. It does not have width, but flows with its content. To get it to behave like a div, you would have to instruct it to act like a block-level element:
display: block
From there, you could add width:
width: 200px;
float: left;
As above, you need to get your label to behave like a block element to get it to respect your width declaration. The simplest way to do this is to set it to inline-block like this:
#form label {
width:200px;
display: inline-block;
}
Or, as #David mentions, float it left. This article describes getting this to work cross-browser.
This is because the label is an inline element so does not have a width property. To set the width you need to make it a block or inline-block element:
#form label {
display: block;
width: 200px;
}
Label is an inline element, so you cannot apply a fixed width to it (unless you change its display behavior). See here for a quick map of options/browser compatibility
http://www.quirksmode.org/css/display.html

Block-level elements within display: inline-block

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