Reputation: 3532
I want to align three items in a flexbox like this. The context is that these are unknown-length (but wrappable) labels for an unknown-width (unwrappable) slider/row of buttons in a survey.
[L] [R]
[variable width]
How do I align the top two items to the width of the lower/middle item without fixing the width of the container to the (in reality unknown width of the middle item)?
I considered putting left and right into another flexbox and using a column layout for the top container. I don't like that way, because I'd have to break with the true content order (left-middle-right), but I couldn't even make it work this way.
div {
border: 1px dotted;
}
.container {
display: flex;
flex-wrap: wrap;
width: 300px; /* I want to get rid of this */
}
.left {
order: 1;
flex: 1 0;
}
.right {
order: 2;
flex: 1 0;
text-align: right;
}
.middle {
order: 3;
flex: 2 0 auto;
}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
Some unknown-width unwrappable thing here.
</div>
<div class="right">
right label may wrap if it's wider than 50%
</div>
</div>
Upvotes: 2
Views: 927
Reputation: 14022
The only pure CSS possibility to align items as you want is CSS Grid.
div {
border: 1px dotted;
}
.container {
display: inline-grid;
grid-template-columns: min-content min-content;
}
.right {
grid-column: 2;
grid-row: 1;
}
.middle {
grid-column: 1 / span 2;
white-space: nowrap;
}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
Some unknown-width unwrappable thing here.
</div>
<div class="right">
right label may wrap if it's wider than 50%
</div>
</div>
Also if you need IE10+ support it's easy to achieve:
div {
border: 1px dotted;
}
.container {
display: -ms-inline-grid;
display: inline-grid;
-ms-grid-columns: min-content min-content;
grid-template-columns: min-content min-content;
}
.right {
-ms-grid-column: 2;
grid-column: 2;
grid-row: 1;
}
.middle {
-ms-grid-row: 2;
-ms-grid-column-span: 2;
grid-column: 1 / span 2;
white-space: nowrap;
}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
Some unknown-width unwrappable thing here.
</div>
<div class="right">
right label may wrap if it's wider than 50%
</div>
</div>
Upvotes: 1
Reputation: 1383
Use flex-basis: number%
it works very well and supported by IE 10+, and you can choose your breaking point in media query selectors if you want.
check my code:
div {
border: 1px dotted;
}
.container {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
.left {
flex-basis: 49.55%; /* change this to whatever you want */
}
.right {
flex-basis: 49.55%; /* change this to whatever you want */
}
.middle {
order: 3;
flex-basis: 100%;
}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
Some unknown-width unwrappable thing here.
</div>
<div class="right">
right label may wrap if it's wider than 50%
</div>
</div>
Upvotes: -1
Reputation: 273934
Here is an idea of solution without adding extra markup:
.container {
display: inline-flex;
flex-wrap: wrap;
max-width: 100%;
border: 1px solid;
margin: 20px;
}
.left {
order: 1;
min-width: 0;
width: 0.5px;
white-space: nowrap;
}
.right {
order: 2;
min-width: 0;
width: 0.5px;
margin-left: auto;
display: flex;
justify-content: flex-end;
white-space: nowrap;
}
.middle {
order: 3;
flex-basis: 100%
}
<div class="container">
<div class="left">
some left content
</div>
<div class="middle">
So in my real example, there is some unknown-width unwrappable thing here. there is some unknown-width unwrappable thing here.
</div>
<div class="right">
some right content
</div>
</div>
<div class="container">
<div class="left">
some left content
</div>
<div class="middle">
So in my real example, there is some unknown-width unwrappable thing here.
</div>
<div class="right">
right
</div>
</div>
<div class="container">
<div class="left">
left
</div>
<div class="middle">
So in my real example, there is.
</div>
<div class="right">
right
</div>
</div>
<div class="container">
<div class="left">
left
</div>
<div class="middle">
So in my
</div>
<div class="right">
right
</div>
</div>
But if you are ok to slightly adjust the HTML you can try something like this:
.container {
display: inline-flex;
flex-direction: column;
max-width: 100%;
border: 1px solid;
margin: 20px;
}
.sub {
display: flex;
justify-content: space-between;
}
<div class="container">
<div class="sub">
<div class="left">
some left content
</div>
<div class="right">
some right content
</div>
</div>
<div class="middle">
So in my real example, there is some unknown-width unwrappable thing here. there is some unknown-width unwrappable thing here.
</div>
</div>
<div class="container">
<div class="sub">
<div class="left">
some left content
</div>
<div class="right">
some right content
</div>
</div>
<div class="middle">
So in my real example, there is some unk
</div>
</div>
<div class="container">
<div class="sub">
<div class="left">
left
</div>
<div class="right">
right
</div>
</div>
<div class="middle">
So in my real example,
</div>
</div>
Upvotes: 3
Reputation: 14892
I don't think flex
can be configured like that. The effect you are looking for can be achieved using position:absolute
on the left/right elements:
.container {
position: relative;
padding-top: 1em;
display: inline-block;
}
.left,
.right {
position: absolute;
top: 0;
}
.left {
left: 0;
}
.right {
right: 0;
}
.middle {}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
So in my real example, there is some unknown-width unwrappable thing here.
</div>
<div class="right">
right
</div>
</div>
Upvotes: 1
Reputation: 734
You could change the flex
from auto
to 100%
, and add text-align: center
to .middle
, like so:
.container {
display: flex;
flex-wrap: wrap;
}
.left {
order: 1;
flex: 1 0;
}
.right {
order: 2;
flex: 1 0;
text-align: right;
}
.middle {
order: 3;
flex: 2 0 100%; /* change this to 100% instead of auto */
text-align: center; /* To center the text */
}
<div class="container">
<div class="left">
left
</div>
<div class="middle">
So in my real example, there is some unknown-width unwrappable thing here.
</div>
<div class="right">
right
</div>
</div>
Upvotes: 0