Let's say I have a display: inline container with some text children, and some inline-block children:
If I give the container the following CSS... (and change inline-block to inline-flex)
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
... then it treats the text element as an entire element of its own and wraps the whole thing, rather than breaking it up.
Is there a "flexbox" way of achieving this, or do I really have to fall back to display inline?
Once you create a flex container (display: flex or display: inline-flex), all in-flow children become flex items.
Flex items are, by definition, "blockified", which means they are block-level boxes (source).
Text elements represent inline-level boxes (source).
Therefore, you cannot make flex items wrap in the same way as text (or floats).
Related
I have a nested flex layout.
Here is my codepen link https://codepen.io/mendoncafiles/pen/oNoGbPa
There is a flex container, inside which I have list items. Each list item is a flex, with I tag and SPAN tag as flex items. The I tag has flex-basis of 30px.
The text in last list-item is wrapped to next line.
The text is displayed in single line with two options:
remove display: flex from wrapping DIV
Change flex-basis: 30px to width: 30px to I tag.
Expected:
Issue:
It looks like the problem is that the browser is establishing the size of the container before factoring in the full length of the spans.
You can disable flex-shrink or use white-space: nowrap on the spans. But that will cause an overflow.
Consider setting a minimum width on the top level flex container or the ul.
These two ways to move a button to the right of its parent seem completely equivalent to me. Is there a reason to choose one over the other? Are there circumstances in which flex works to align content to the right where text-align might not suffice?
.parent {
text-align: right;
}
<div class="parent"><button>Awesome button!</button></div>
.parent {
display: flex;
justify-content: flex-end;
}
<div class="parent"><button>Awesome button!</button></div>
I'm curious because I noticed that Bootstrap changed from text-align: right to flex between versions 3 and 4 for aligning buttons in a modal's footer section.
To illustrate further:
Yes there is a big difference. Flexbox is about boxes and block level element whearas text-align is about text and inline level element.
When having one element we won't notice the difference but when it comes to multiple element we can see a clear difference.
Here is a basic example where we have text and button inside a container:
.parent-flex {
display: flex;
justify-content: flex-end;
margin-bottom:10px;
}
.parent-normal {
text-align:right;
}
<div class="parent-flex">some text here <button>Awesome button!</button></div>
<div class="parent-normal">some text here <button>Awesome button!</button></div>
Note how in the flex container we no more have white space between the text and the button because the text will become a block element1 and the button too which is not the case in the second example where both are inline element. Until now, it's ok because we can rectify this with margin.
Let's put more text and see the difference again:
.parent-flex {
display: flex;
justify-content: flex-end;
margin-bottom:10px;
}
.parent-normal {
text-align:right;
}
<div class="parent-flex">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here<button>Awesome button!</button></div>
<div class="parent-normal">some text here some text here some text here some text here some text here some text here some text here some text here some text here some text here<button>Awesome button!</button></div>
Now we have a clear difference and we can see that the flex container consider all the text as a block element and the button will not follow the text like in the second container. In some case it can be an intended result but not in all the cases.
Let's add a link inside our text:
.parent-flex {
display: flex;
justify-content: flex-end;
margin-bottom:10px;
}
.parent-normal {
text-align:right;
}
<div class="parent-flex">some text here some text here some text here some text here some text here some text here some text link here some text here some text here some text here<button>Awesome button!</button></div>
<div class="parent-normal">some text here some text here some text here some text here some text here some text here some text link here some text here some text here some text here<button>Awesome button!</button></div>
The flexbox container is getting worse! because the link is also blockified1 and now we have 4 block elements. The text before the link, the link, the text after and the button. We can clearly see that this behavior is not intended at all.
Basically flexbox is useful when it comes to align element that we can consider as block element or container or boxes, etc but not when it comes to text container. text-align is more useful to align text inside the previous block/box/container element.
In other words, text-align should be used at text level to align text, images, etc and flexbox should be considered at an upper level to align block element and create layouts.
In your case, there is no big difference since we can consider button as boxes or inline-element. the only difference will be the whitespace between the button that you will face if you consider them as inline element when using text-align.
1 Loosely speaking, the flex items of a flex container are boxes representing its in-flow contents.
Each in-flow child of a flex container becomes a flex item, and each contiguous sequence of child text runs is wrapped in an anonymous block container flex item. However, if the entire sequence of child text runs contains only white space (i.e. characters that can be affected by the white-space property) it is instead not rendered
The display value of a flex item is blockified
A related article I wrote around the same subject: https://dev.to/afif/never-make-your-text-container-a-flexbox-container-m9p
https://www.w3.org/TR/css-flexbox-1/#flex-items
flex-box system provides more powerful features when it comes to aligning your content. If you have three buttons and you want them to be placed equally distant from each other, or equally distant from each other and container boundary you can give space-between or space-evenly value to justify-content property to the container. You cannot do that with text-align or float.
Yes, the reason is vertical centering. The align-items: center is the key here, which allows the buttons to be vertically centered in the modal footer. This is hard to do without flex-boxes - you would need to resort to "hacks" like using position:absolute, or adding some precalculated amounts of padding on both sides, etc. Flexes (and Grids) allow developers to define layouts more succinctly.
To answer your question - they didn't opt for justify-content:flex-end instead of text-align:right - instead, they opted for flex instead of block as the display box model (for vertical centering), and the justify-content usage comes naturally from that decision.
If a previous sibling is set to float with a width of 100% and the following sibling set to display: flex, the latter overflow the parent container instead of wrap to a new line.
With any other display value but flex (or grid) it wraps, as it should, so how come it won't when set to flex
.float-left {
float: left;
width: 100%;
}
.display-flex {
display: flex;
background: yellow;
}
/* Demo css */
.container {
max-width: 80%;
margin: auto;
background: white;
}
<div class="container">
<div class="float-left">I'm floating left, with a width of 100%.</div>
<div class="display-flex">'Floating left' takes up 100% of the space, but still i don't go onto a new line?</div>
</div>
The reason a block box appears to wrap when its previous sibling is a float with 100% width is because it's not actually the box that's wrapping, it's its inline content that's wrapping.
The reason this doesn't happen with a flex container is because floats cannot intrude into flex formatting contexts. In fact, the same thing happens with block formatting contexts — if you apply overflow: auto or overflow: hidden to the following sibling without display: flex the following sibling will seem to disappear altogether. (This implies that the first paragraph is true only when the block box does not establish a block formatting context.)
Since your float is 100% width, the flex container's (auto) width is reduced to 0. Its inline descendants don't wrap underneath the float, because those inline descendants are participating in an inline formatting context that's within an anonymous flex item, which itself doesn't wrap since it's the only flex item in the flex container. This flex item is overflowing the flex container; however the flex container itself doesn't overflow the containing block since its used width is 0, allowing it to sit next to the float.
The reason the flex container will wrap if it is display: inline-flex instead of display: flex is because an inline-level flex container behaves just like any other inline-level content, wrapping around a float. In this case, it's the flex container itself that wraps — its inline content is still formatted as an anonymous flex item, because flex layout is identical regardless of whether the flex container itself is inline-level or block-level.
The problem is that the element .display-flex is not a flex item. It is a child element in a standard block container.
Therefore, the flex shorthand property, and its longhand component properties, which apply only to flex items, are having no effect.
However, the width property works on both flex items and containers.
More details here: What are the differences between flex-basis and width?
If I want to make a div in-line with other inline elements of the container div, and my purpose is to just that and nothing else, should I prefer using inline-block or display property or inline-flex? Cannot use spans as there are some overriding styles on span in the project and I'm prohibited from inline-styling. Are there any pros and cons between inline-flex and inline-block? What should be the standard to follow to do this?
I don't see any difference in the output from both. Maybe I'm working on a very simplistic model to see any difference. I read some questions regarding box model, inline-block and inline-flex but couldn't find any content emphasizing on pros and cons of using inline-flex vs inline-block.
Sample code to be something like:
.contentContainer {
height: 40px;
padding: 10px;
}
.contentLabel {
margin-left: 10px;
color: red;
display: inline-flex;
width: 25%;
}
.content {
margin-left: 10px;
display: inline-flex;
width: 70%;
}
<div class="contentContainer">
<div class="contentLabel">Name</div>
<div class="content">Some Random Name</div>
</div>
If all you want to do is display a run of text inline with other text, use display: inline. (This is where a span should be used over a div, but you have your limitations...)
If you want to display a block of text inline, but still have its text flow independently within the block as though it were still a block-level element, use display: inline-block.
You won't see any difference between inline-block and inline-flex if the only thing in your div is a single run of text, because the text in an inline flex container is converted into a block box anyway, but inline-block is the idiomatic way of formatting inline content as an atomic box — inline-flex is intended for when you're actually trying to create a flex layout.
If you're trying to format a Web form with each label on the same row as its field, consider table layout, floats, or a complete flex layout instead of just displaying each label as an individual flex container.
I am a beginner trying to do the following in css / html:
I have two floating elements, one on the left, one on the right. I want these two elements to be vertically centered in a wrapper that has no defined height. I only found a solution for the case when the wrapper has a defined height, but my wrapper can have various heights as the text content is dynamically added.
Thank you for helping me.
You're best of using flex box. On the parent element, i.e. the div, do the following:
display: flex;
flex-direction: column;
justify-content: center;
This will then ensure no matter how many items you have in the child element they are always aligned vertically. You can then align them horizontally with align-items: center;
A visual representation is shown here:
http://codepen.io/pauljohnknight/pen/oZLJPG
Paul.