Reputation: 3079
I have 4 elements to be displayed on a mobile screen. I want to have them display in 2 columns of 2 elements each on portrait view and a single row for all 4 of them on landscape view.
Portrait view:
Plan 1 Plan 2
Plan 3 Plan 4
Landscape view:
Plan 1 Plan 2 Plan 3 Plan 4
This is my html code:
<div class="flex">
<label>Plan 1</label>
<label>Plan 2</label>
<label>Plan 3</label>
<label>Plan 4</label>
</div>
my css:
.flex {
display:flex;
flex-direction:column;
}
I can pull out only 1 column. What should I do?
Upvotes: 5
Views: 15688
Reputation: 8205
You could make use of vmin
and vmax
here.
To make items wrap to the next line, use flex-wrap: wrap
.
If the flex container does not take up the full width of the screen, replace these values with .flex
's corresponding dimensions
.flex {
display: flex;
flex-wrap: wrap;
}
.flex label {
max-width: 50vmin;
min-width: 25vmax;
}
body {
margin: 0;
width: 100vw;
height: 100vh;
}
<div class="flex">
<label>Plan 1</label>
<label>Plan 2</label>
<label>Plan 3</label>
<label>Plan 4</label>
</div>
Upvotes: 4
Reputation: 371163
Use flex properties and media queries to make the adjustment between screen orientations / sizes.
article {
display: flex;
width: 75%;
margin: 0 auto;
}
section {
flex: 1; /* see Note 1 */
}
h3 {
text-align: center;
}
h3:first-child {
display: none;
}
@media ( max-width: 600px ) {
h3:first-child {
display: block;
}
h3:nth-child(2) {
display: none;
}
article {
flex-wrap: wrap; /* see Note 2 */
}
section {
flex: 1 0 34%; /* see Note 2 */
}
}
/* can ignore styles below; decorative only */
article { padding: 5px; background-color: #f5f5f5; border: 1px solid #ccc; }
section { height: 50px; background-color: lightgreen; border: 1px solid #ccc;
display: flex; justify-content: center; align-items: center; font-size: 1.2em; }
<h3>Portrait View</h3>
<h3>Landscape View</h3>
<article>
<section>Plan 1</section>
<section>Plan 2</section>
<section>Plan 3</section>
<section>Plan 4</section>
</article>
Notes.
flex: 1
assigns an equal proportion of container space to each item, causing all to be equal width. More details here: Make flex-grow expand items based on their original size
With flex-grow: 1
defined in the flex shorthand, there's no need for flex-basis
to be 50%, which can result in one item per row due to the margins. Since flex-grow
will consume free space on the row, flex-basis
only needs to be large enough to enforce a wrap. In this case, with flex-basis: 34%
, there's plenty of space for the margins, but never enough space for a third item.
Upvotes: 0
Reputation: 18520
You might want to use CSS grid if you can, as that supports multiple columns natively.
That being said, this is possible with flexbox, it's just a little counter intuitive. Instead of using flex-direction: column;
, you should leave it in flex-direction: row;
and set flex-wrap: wrap;
to enable elements to wrap to new lines. Then, if you set flex: 0 0 50%;
(meaning don't grow, don't shrink, and use 50% as the basis width), you'll get two columns with additional elements wrapping below.
To change this to stack on portrait view, you can use a media query to change the flex-basis
to 100% (the third parameter in the flex
property).
.flex {
display: flex;
flex-wrap: wrap;
}
.flex label {
flex: 0 0 50%;
}
@media (orientation: portrait) {
.flex label {
flex-basis: 100%;
}
}
<div class="flex">
<label>Plan 1</label>
<label>Plan 2</label>
<label>Plan 3</label>
<label>Plan 4</label>
</div>
Upvotes: 3
Reputation: 1358
You need to set the width for each column. You can set the width for the children of the .flex
class or you can create another one. For example, if you want 4 columns you'll have to set width: 25%
for each label
. For the different sizes you'll have to use the @media
to set the sizes, like:
/* Phone landscape and bigger */
@media (min-width: 640px) {
.label {
width: 25%;
}
}
Upvotes: 0