CSS: element has 'display: block' and doesn't start a new line - css

Please take a look on the following code:
.header {
display: flex;
width: 100vw;
height: 20vh;
}
div {
border: solid;
}
#first {
flex: 1
}
#second {
flex: 1
}
#third {
flex: 1
}
<header class="header">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</header>
This code gives three rectangles that lie one next to the other.
However, if you inspect each rectangle, you'll see in dev-tools
that these rectangles has display: block.
However, I know that when an element has a display: block property, it means that the element starts a new line. As you can see, it's not the case. All three rectangles are placed in the same line.
How can you explain this?

However, I know that when an element has a display: block property, it means that the element starts a new line.
Your information is wrong because the display property alone never tells us if we will have a new line or not.
Let's take another example without flexbox:
.box {
width:200px;
height:200px;
border:2px solid;
float:left;
}
<div class="box">
</div>
<div class="box">
</div>
You can clearly notice that the elements have the computed value of display equal to block but they don't start on a new line due to the float property. Same thing happen with flexbox, CSS grid, position:absolute and many others combination of properties.
All this is defined in the specification.
For float elements: https://www.w3.org/TR/CSS21/visuren.html#floats
If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.
For flexbox: https://www.w3.org/TR/css-flexbox-1/
The display value of a flex item is blockified: ...
The flex-direction property specifies how flex items are placed in the flex container, by setting the direction of the flex container’s main axis. This determines the direction in which flex items are laid out.
The default direction is row
You simply need to find the part of the specification dealing with the properties you are using to find how your elements will be placed in the document and you will clearly see that display alone isn't enough to define this.

Hi it's because your header display flex. If it displays flex, its all children will display in a line. You can change by add flex-direction: column or row (as default)

Your container div is set to be displayed as flex - so all of its children will inherit the display mode from the parent (and thus, display inline). You can set how they're displayed by specifying the flex-direction. Setting it to display as column will make all of the child elements display under one another.
.header {
display: flex;
width: 100vw;
height: 20vh;
/* Add this */
flex-direction:column;
}
div {
border: solid;
}
#first {
flex:1
}
#second {
flex:1
}
#third {
flex:1
}
<body>
<header class="header">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</header>
</body>

display: flex is tells your browser, "I wanna use flexbox with this container, please." A div element defaults to display:box.
An element with this display setting takes up the full width of the
line it is on. Here is an example of four colored divs in a parent
div with the default display setting:

Related

Internet Explorer 11: Children with floated elements inside have a lot of white space when contained in vertical flexbox div

I'm trying to fix strange behavior (in IE11) of vertical flexbox container children, which stretch in height too much leaving a lot of white space, when they contain floated elements.
You can also see it at: https://kinderhotel.info
So far, I've tried removing order: 6; on .content-5, setting different values of flex-grow\-shrink\-basis, height. I also moved .content-5-inside up one level in the DOM and then this element had a lot of white space at the bottom. Finally, when I turned off float on the divs, there was no superfluous white space.
It works perfectly in modern browsers.
<div class="home-page">
<div class="content-5">
<div class="content-5-inside">
<div class="float-left">...</div>
<div class="float-left">...</div>
<div class="float-right">...</div>
</div>
</div>
</div>
.home-page {
display: flex;
flex-direction: column;
}
.content-5 {
order: 6;
}
.content-5-inside::before, .content-5-inside::after {
content: "";
display: table;
}
.content-5-inside::after {
clear: both;
}
I cannot use any content managing rules like flexbox inside .content-5-inside block, since anything that is inside is provided by end users and can be or not floated. But I need, whenever user puts floated content inside, that there is no white space below.

css - flexbox inheriting parent width despite align-items: flex-start, justify-content: flex-start [duplicate]

I am trying to vertically align elements within an ID wrapper. I gave the property display:inline-flex; to this ID as the ID wrapper is the flex container.
But there is no difference in presentation. I expected that everything in the wrapper ID would be displayed inline. Why isn't it?
#wrapper {
display: inline-flex;
/*no difference to display:flex; */
}
<body>
<div id="wrapper">
<header>header</header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
<footer>footer</footer>
</div>
</body>
display: inline-flex does not make flex items display inline. It makes the flex container display inline. That is the only difference between display: inline-flex and display: flex. A similar comparison can be made between display: inline-block and display: block, and pretty much any other display type that has an inline counterpart.1
There is absolutely no difference in the effect on flex items; flex layout is identical whether the flex container is block-level or inline-level. In particular, the flex items themselves always behave like block-level boxes (although they do have some properties of inline-blocks). You cannot display flex items inline; otherwise you don't actually have a flex layout.
It is not clear what exactly you mean by "vertically align" or why exactly you want to display the contents inline, but I suspect that flexbox is not the right tool for whatever you are trying to accomplish. Chances are what you're looking for is just plain old inline layout (display: inline and/or display: inline-block), for which flexbox is not a replacement; flexbox is not the universal layout solution that everyone claims it is (I'm stating this because the misconception is probably why you're considering flexbox in the first place).
1 The differences between block layout and inline layout are outside the scope of this question, but the one that stands out the most is auto width: block-level boxes stretch horizontally to fill their containing block, whereas inline-level boxes shrink to fit their contents. In fact, it is for this reason alone you will almost never use display: inline-flex unless you have a very good reason to display your flex container inline.
OK, I know at first might be a bit confusing, but display is talking about the parent element, so means when we say: display: flex;, it's about the element and when we say display:inline-flex;, is also making the element itself inline...
It's like make a div inline or block, run the snippet below and you can see how display flex breaks down to next line:
.inline-flex {
display: inline-flex;
}
.flex {
display: flex;
}
p {
color: red;
}
<body>
<p>Display Inline Flex</p>
<div class="inline-flex">
<header>header</header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
<footer>footer</footer>
</div>
<div class="inline-flex">
<header>header</header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
<footer>footer</footer>
</div>
<p>Display Flex</p>
<div class="flex">
<header>header</header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
<footer>footer</footer>
</div>
<div class="flex">
<header>header</header>
<nav>nav</nav>
<aside>aside</aside>
<main>main</main>
<footer>footer</footer>
</div>
</body>
Also quickly create the image below to show the difference at a glance:
flex and inline-flex both apply flex layout to children of the container. Container with display:flex behaves like a block-level element itself, while display:inline-flex makes the container behaves like an inline element.
Using two-value display syntax instead, for clarity
The display CSS property in fact sets two things at once: the outer display type, and the inner display type. The outer display type affects how the element (which acts as a container) is displayed in its context. The inner display type affects how the children of the element (or the children of the container) are laid out.
If you use the two-value display syntax, which is only supported in some browsers like Firefox, the difference between the two is much more obvious:
display: block is equivalent to display: block flow
display: inline is equivalent to display: inline flow
display: flex is equivalent to display: block flex
display: inline-flex is equivalent to display: inline flex
display: grid is equivalent to display: block grid
display: inline-grid is equivalent to display: inline grid
Outer display type: block or inline:
An element with the outer display type of block will take up the whole width available to it, like <div> does. An element with the outer display type of inline will only take up the width that it needs, with wrapping, like <span> does.
Inner display type: flow, flex or grid:
The inner display type flow is the default inner display type when flex or grid is not specified. It is the way of laying out children elements that we are used to in a <p> for instance. flex and grid are new ways of laying out children that each deserve their own post.
Conclusion:
The difference between display: flex and display: inline-flex is the outer display type, the first's outer display type is block, and the second's outer display type is inline. Both of them have the inner display type of flex.
References:
The two-value syntax of the CSS Display property on mozzilla.org
The Difference between "flex" and "inline-flex"
Short answer:
One is inline and the other basically responds like a block element(but has some of it's own differences).
Longer answer:
Inline-Flex - The inline version of flex allows the element, and it's children, to have flex properties while still remaining in the regular flow of the document/webpage. Basically, you can place two inline flex containers in the same row, if the widths were small enough, without any excess styling to allow them to exist in the same row. This is pretty similar to "inline-block."
Flex - The container and it's children have flex properties but the container reserves the row, as it is taken out of the normal flow of the document. It responds like a block element, in terms of document flow. Two flexbox containers could not exist on the same row without excess styling.
The problem you may be having
Due to the elements you listed in your example, though I am guessing, I think you want to use flex to display the elements listed in an even row-by-row fashion but continue to see the elements side-by-side.
The reason you are likely having issues is because flex and inline-flex have the default "flex-direction" property set to "row." This will display the children side-by side. Changing this property to "column" will allow your elements to stack and reserve space(width) equal to the width of its parent.
Below are some examples to show how flex vs inline-flex works and also a quick demo of how inline vs block elements work...
display: inline-flex; flex-direction: row;
Fiddle
display: flex; flex-direction: row;
Fiddle
display: inline-flex; flex-direction: column;
Fiddle
display: flex; flex-direction: column;
Fiddle
display: inline;
Fiddle
display: block
Fiddle
Also, a great reference doc:
A Complete Guide to Flexbox - css tricks
Display:flex apply flex layout to the flex items or children of the container only. So, the container itself stays a block level element and thus takes up the entire width of the screen.
This causes every flex container to move to a new line on the screen.
Display:inline-flex apply flex layout to the flex items or children as well as to the container itself. As a result the container behaves as an inline flex element just like the children do and thus takes up the width required by its items/children only and not the entire width of the screen.
This causes two or more flex containers one after another, displayed as inline-flex, align themselves side by side on the screen until the whole width of the screen is taken.
I'd like to add some details about screen reader behaviour, because there's some surprises here.
Some background first. Some screen readers like NVDA handle display: block and display: inline-block differently (and they should, as you will see later).
Comparison between different display attributes
display: block
A display: block element will always be announced in a separate "line", meaning NVDA will stop talking after its contents, and the user will manually tell NVDA to announce the next element (typically with Down arrow key).
<div>This is the first line</div>
<div>This is another line</div>
This will make NVDA announce This is the first line, and then This is another line.
The following yields the same result:
<span style="display: block">This is the first line</span>
<span style="display: block">This is another line</span>
display: inline-block
A display: inline-block element will be announced together with all preceding and following other inline elements (display: inline and display: inline-block).
<span style="display: inline-block">This is the first line</span>
<span style="display: inline-block">This is another line</span>
This will make the screen reader announce both elements in one go: This is the first line This is another line.
As said before, it doesn't matter whether it's an inline or inline-block element; the following yields the exact same result:
<span style="display: inline">This is the first line</span> <!-- Inline! -->
<span style="display: inline-block">This is another line</span> <!-- Inline block! -->
display: flex
This works exactly like display: block.
display: inline-flex
Surprisingly, this also works like display: block, not like display: inline-block!
display: grid / display: inline-grid
I didn't test this, but I expect the same like with flex / inline-flex here.
Why is that a problem?
Using display: inline-block, one can create elements that visually look very distinct, but semantically are treated "as one".
For example, consider the following headline in an online news platform:
<h2>
<span class="category">Rain forests</span>
They need our love
</h2>
You now want to visually style the category (Rain forests) very different to the "real" title ('They need our love'), i.e. by putting each in its own line, something like this:
If you'd make category a display: block element, then the screen reader would announce the heading in two separate lines like this: Rain forests, heading level 2, then They need our love, heading level 2. This is confusing to the user: are there two different headings on the page? Why is there no content for the first one (instead, immediately an apparent second heading seems to follow)?
If however you'd make category a display: inline-block element, then the screen reader would announce the heading in one go: Rain forests They need our love, heading level 2.
It is sad, that display: inline-flex (and probably inline-grid, too) does not mimic the behaviour. So if you want to offer perfect accessibility, you might want to use inline-block in such situations.
You can display flex items inline, providing your assumption is based on wanting flexible inline items in the 1st place. Using flex implies a flexible block level element.
The simplest approach is to use a flex container with its children set to a flex property. In terms of code this looks like this:
.parent{
display: inline-flex;
}
.children{
flex: 1;
}
flex: 1 denotes a ratio, similar to percentages of a element's width.
Check these two links in order to see simple live Flexbox examples:
https://njbenjamin.com/bundle-3.htm
https://njbenjamin.com/bundle-4.htm
If you use the 1st example:
https://njbenjamin.com/flex/index_1.htm
You can play around with your browser console, to change the display of the container element between flex and inline-flex.
You need a bit more information so that the browser knows what you want. For instance, the children of the container need to be told "how" to flex.
Updated Fiddle
I've added #wrapper > * { flex: 1; margin: auto; } to your CSS and changed inline-flex to flex, and you can see how the elements now space themselves out evenly on the page.
Open in Full page for better understanding
.item {
width : 100px;
height : 100px;
margin: 20px;
border: 1px solid blue;
background-color: yellow;
text-align: center;
line-height: 99px;
}
.flex-con {
flex-wrap: wrap;
/* <A> */
display: flex;
/* 1. uncomment below 2 lines by commenting above 1 line */
/* <B> */
/* display: inline-flex; */
}
.label {
padding-bottom: 20px;
}
.flex-inline-play {
padding: 20px;
border: 1px dashed green;
/* <C> */
width: 1000px;
/* <D> */
display: flex;
}
<figure>
<blockquote>
<h1>Flex vs inline-flex</h1>
<cite>This pen is understand difference between
flex and inline-flex. Follow along to understand this basic property of css</cite>
<ul>
<li>Follow #1 in CSS:
<ul>
<li>Comment <code>display: flex</code></li>
<li>Un-comment <code>display: inline-flex</code></li>
</ul>
</li>
<li>
Hope you would have understood till now. This is very similar to situation of `inline-block` vs `block`. Lets go beyond and understand usecase to apply learning. Now lets play with combinations of A, B, C & D by un-commenting only as instructed:
<ul>
<li>A with D -- does this do same job as <code>display: inline-flex</code>. Umm, you may be right, but not its doesnt do always, keep going !</li>
<li>A with C</li>
<li>A with C & D -- Something wrong ? Keep going !</li>
<li>B with C</li>
<li>B with C & D -- Still same ? Did you learn something ? inline-flex is useful if you have space to occupy in parent of 2 flexboxes <code>.flex-con</code>. That's the only usecase</li>
</ul>
</li>
</ul>
</blockquote>
</figure>
<br/>
<div class="label">Playground:</div>
<div class="flex-inline-play">
<div class="flex-con">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>
<div class="flex-con">
<div class="item">X</div>
<div class="item">Y</div>
<div class="item">Z</div>
<div class="item">V</div>
<div class="item">W</div>
</div>
</div>

Make sure a float:right element is vertically aligned to the top, even if next to a float:left element

I ran into a small problem with floats that i demonstrate in this fiddle.
I have a DIV which floats to the left, whose width is dynamic (unknown). I have another one that floats to the right in the same block, width dynamic as well.
The problem is that if the width of the first block extends so that it would collide with the right float, the right float will (correctly) drop downwards to make sure no collision is happening. However, i want it to stay on top (vertically, that is - not in terms of z-index).
Basically it seems that the text is prioritized as to "displace" the block on the right side. This should be the other way around, but with the text on the left using up the available space on the topmost line before it even starts to wrap.
I guess the solution is fairly simple. Its just that it doesn't come to my mind at all and any searches i did didn't find me what i was looking for.
You might want to try using css tables/ Just create both elements and make it a table, then make your right and left elements table-cells:
#wrapper {
display: table;
width: 100%;
}
#leftside, #rightside {
display: table-cell;
width: 50%; /* Both sides will be rendered on one line */
vertical-align: top;
}
/* Position elements within the cell */
#leftside { text-align: left; }
#rightside { text-align: right; }
#leftside > div, #rightside > div {
display: inline-block;
text-align: left; /* Reset text alignment */
}
Explanation: The table structure will keep the elements in one line with width 50%; The inner elements (divs in this case) will be inline-blocks so that they can be aligned left or right. Now when one of the inner divs exceeds the max width of 50% it will just make the other 'cell' side smaller
Float the label div inside the title div, that will wrap the title text around the label regardless of the width of either.
<div class="infoBox">
<div class="inner">
<div class="entry">
<div class="title">
<div class="type">
LABEL
</div>
If this text is longer, the LABEL will drop downwards.
I would like to have the LABEL float right (as it does here) but also be at the top of the block.
</div>
</div>
</div>
​

A div with relative position over a div float

I don't understand why a div with float right or left is not above a div with relative position or defined with a background color when the last one is declared after.
Here is the html:
<html>
<body>
<div class="container">
Main container <br/><br/>
<div class="header">This is the header</div>
<div class="text-right">Right text</div>
<div class="footer">This is the footer</div>
</div>
</body>
And here is the css:
.header {
background-color:blue;
border: solid;
color: white;
border-color:black;
height: 100px;
}
.text-right{
float: right;
border: solid;
background-color: green;
}
.container{
padding: 10px;
border: solid;
}
.footer{
padding-top: 50px;
border: solid;
background-color: yellow;
position: relative;
}
I know that I can use a .clear: both rule to correct this problem but my main point is: why when I set the background-color or the position or both in the .footer rule, the float div is under the footer?
Thank you very much!
While reading this very good post, at the end of the post, the author talks about the z-order internal working but also say that if you want to learn more, this next one will be a much more detailed article
The key point is that the order in the z-axis where are put the elements.
Here is what the author says:
If we do not specify any z-index values, the default stacking order
from closest to the user to furthest back is as follows:
1. Positioned elements, in order of appearance in source code
2. Inline elements
3. Non-positioned floating elements, in order of appearance in source code
4. All non-positioned, non-floating, block elements in order of source code
5. Root element backgrounds and borders
As we can see, the positioned elements(1) are always on top of non-positioned elements(3-4). If I put a div with just a float property, this element will not be "positioned" onto the surface.
In this case, the second element, my footer div, that is positioned with a relative property value will be at the top of the previous one not just I don't add a clear: both property after the float div property or because the last one is added after the floating element but because it is positioned!
Like powerbuoy said, you must set add a position relative to the float element to be able to go top of the stack the floating element. But it's not enough. Because these two elements are now at the same level and because they are both crossing each other, you must tell the engine which one will be the first and this is why you must set the z-order to 1 to the floating element again like said powerbuoy.
I'm not a very good writer and for this reason, I strongly suggest you to read the referenced articles that I mentioned previously. I think you will have a very deep explanation of the case.
Since the footer comes after the text-right it will be rendered on top of text-right. To avoid this you can give text-right a z-index (and a position other than static):
http://jsfiddle.net/wxMhx/
Edit: hmmm... no that's not entirely correct. If you remove position: relative; from the footer text-right will be rendered on top of it. TBH I'm not sure why that happens. But the solution in either case is to either remove position: relative; from the footer, or add it (as well as a z-index) to text-right.
Because position: relative. If you delete this line you will see div with text-right class. You can set z-index: -1; to footer class and this should work as well.

CSS: How to position two elements on top of each other, without specifying a height?

I have two DIVs that I need to position exactly on top of each other. However, when I do that, the formatting gets all screwed up because the containing DIV acts like there is no height. I think this is the expected behavior with position:absolute but I need to find a way to position these two elements on top of each other and have the container stretch as the content stretches:
The top left edge of .layer2 should be exactly aligned to the top left edge of layer1
<!-- HTML -->
<div class="container_row">
<div class="layer1">
Lorem ipsum...
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>
/* CSS */
.container_row {}
.layer1 {
position:absolute;
z-index: 1;
}
.layer2 {
position:absolute;
z-index: 2;
}
Actually this is possible without position absolute and specifying any height. All You need to do, is use display: grid on parent element and put descendants, into the same row and column.
Please check example below, based on Your HTML. I added only <span> and some colors, so You can see the result.
You can also easily change z-index each of descendant elements, to manipulate its visibility (which one should be on top).
.container_row{
display: grid;
}
.layer1, .layer2{
grid-column: 1;
grid-row: 1;
}
.layer1 span{
color: #fff;
background: #000cf6;
}
.layer2{
background: rgba(255, 0, 0, 0.4);
}
<div class="container_row">
<div class="layer1">
<span>Lorem ipsum...<br>Test test</span>
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>
First of all, you really should be including the position on absolutely positioned elements or you will come across odd and confusing behavior; you probably want to add top: 0; left: 0 to the CSS for both of your absolutely positioned elements. You'll also want to have position: relative on .container_row if you want the absolutely positioned elements to be positioned with respect to their parent rather than the document's body:
If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed' ...
Your problem is that position: absolute removes elements from the normal flow:
It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants. However, the contents of an absolutely positioned element do not flow around any other boxes.
This means that absolutely positioned elements have no effect whatsoever on their parent element's size and your first <div class="container_row"> will have a height of zero.
So you can't do what you're trying to do with absolutely positioned elements unless you know how tall they're going to be (or, equivalently, you can specify their height). If you can specify the heights then you can put the same heights on the .container_row and everything will line up; you could also put a margin-top on the second .container_row to leave room for the absolutely positioned elements. For example:
http://jsfiddle.net/ambiguous/zVBDc/
Here's another solution using display: flex instead of position: absolute or display: grid.
.container_row{
display: flex;
}
.layer1 {
width: 100%;
background-color: rgba(255,0,0,0.5); /* red */
}
.layer2{
width: 100%;
margin-left: -100%;
background-color: rgba(0,0,255,0.5); /* blue */
}
<div class="container_row">
<div class="layer1">
<span>Lorem ipsum...</span>
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>
Great answer, "mu is too short".
I was seeking the exact same thing, and after reading your post I found a solution that fitted my problem.
I was having two elements of the exact same size and wanted to stack them.
As each have same size, what I could do was to make
position: absolute;
top: 0px;
left: 0px;
on only the last element. This way the first element is inserted correctly, "pushing" the parents height, and the second element is placed on top.
Hopes this helps other people trying to stacking 2+ elements with same (unknown) height.
Here's some reusable css that will preserve the height of each element without using position: absolute:
.stack {
display: grid;
}
.stack > * {
grid-row: 1;
grid-column: 1;
}
The first element in your stack is the background, and the second is the foreground.
I had to set
Container_height = Element1_height = Element2_height
.Container {
position: relative;
}
.ElementOne, .Container ,.ElementTwo{
width: 283px;
height: 71px;
}
.ElementOne {
position:absolute;
}
.ElementTwo{
position:absolute;
}
Use can use z-index to set which one to be on top.
Due to absolute positioning removing the elements from the document flow position: absolute is not the right tool for the job. Depending on the exact layout you want to create you will be successful using negative margins, position:relative or maybe even transform: translate.
Show us a sample of what you want to do we can help you better.
Of course, the problem is all about getting your height back. But how can you do that if you don't know the height ahead of time? Well, if you know what aspect ratio you want to give the container (and keep it responsive), you can get your height back by adding padding to another child of the container, expressed as a percentage.
You can even add a dummy div to the container and set something like padding-top: 56.25% to give the dummy element a height that is a proportion of the container's width. This will push out the container and give it an aspect ratio, in this case 16:9 (56.25%).
Padding and margin use the percentage of the width, that's really the trick here.
After much testing, I have verified that the original question is already right; missing just a couple of settings:
the container_row MUST have position: relative;
the children (...), MUST have position: absolute; left:0;
to make sure the children (...) align exactly over each other, the
container_row should have additional styling:
height:x; line-height:x; vertical-align:middle;
text-align:center; could, also, help.

Resources