handle
handle

Reputation: 6329

Responsive wrapping of columns with different width ratios (float, flex, grid)?

Is there a way to specify column width ratios and minimum widths to allow wrapping for narrow screens (responsive design)?

+-----+-----+-----+
| 1/3 |    2/3    |
|     |(1/3 | 1/3)|
+-----+-----+-----+

+-----+-----+
| 1/3 | 1/3 |       (actual ratio now 1/2)
|     | 1/3 |
+-----+-----+

+-----+
| 1/3 |             (actual ratio now 1 - full width)
+-----+
| 1/3 |
| 1/3 |
+-----+

Each 1/3 is a div, so is 2/3.
It should fill 100% of its parent's width (centered "main" container column).

I've tried the following:

div {
  box-sizing: border-box;
  border: 1px solid red;
  margin: 1px;
  padding: 0;
}

#container>div {
  float: left;
}

#container::after {
  content: "";
  display: block;
  clear: both;
}

.flex {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
}

.flex>div {
  flex-basis: 200px;
  flex-shrink: 0;
}

.fone {
  flex-grow: 1;
}

.ftwo {
  flex-grow: 2;
}

.gthree {
  display: grid;
  grid-template-columns: 1fr 2fr;
  grid-gap: 1rem;
}

.gtwo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 1rem;
}
float: not quite right
<div id="container">
  <div style="width:33%;">A</div>
  <div style="width:66%;">
    <div style="width:50%;">B</div>
    <div style="width:50%;">C</div>
  </div>
</div>

flex: wraps, uneven sizing, children overflow
<div class="flex">
  <div class="fone">A</div>
  <div class="ftwo flex">
    <div>B</div>
    <div>C</div>
  </div>
</div>

grid: nice sizing, but does not wrap
<div class="gthree">
  <div>A</div>
  <div class="gtwo">
    <div>B</div>
    <div>C</div>
  </div>
</div>

Intended result:
<div class="one">
  <div>A</div>
  <div>
    <div>B</div>
    <div>C</div>
  </div>
</div>

Upvotes: 1

Views: 674

Answers (3)

handle
handle

Reputation: 6329

Flex proportions work well in my application. The actual contents have (different) widths, so they may shrink and overflow at different screen widths. I have added minimum size values for flex in an attempt to simulate that. It does not work well here in the Snippet.

<div style="display:flex; flex-wrap: wrap; gap:1rem;">
  <div style="flex:1 250px;">AAA unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,</div>
  <div style="flex:2; display:flex; flex-wrap: wrap; gap:1rem;">
    <div style="flex:1 250px;">BBB unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,</div>
    <div style="flex:1 250px;">CCC unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,</div>
  </div>
</div>

Upvotes: 0

Sojo C Johny
Sojo C Johny

Reputation: 136

Try this:

div {
  box-sizing: border-box;
  border: 1px solid red;
  margin: 1px;
  padding: 0;
}

.container {
  display: flex;
  flex-wrap:wrap;
  justify-content:space-evenly;
  /* Or you can use any of the 
   following as per needs:
justify-content:space-between;
justify-content:space-around;
justify-content:space-evenly;
justify-content:center; */
}

.inner { 
  display: flex;
  flex-wrap:wrap;
  flex:1;
}
.middle { 
  display: flex;
  flex-wrap:wrap;
  flex:1;

}
.single{
/* For occupying equal space: */
  flex:1;
  
}


/* `Note: The flex-wrap works when you use a specific width, else the width will adjust automatically depends on screen size` */
<div class="container">
  <div class='single'>A</div>
  <div class='middle'>
    <div class='inner'>B</div>
    <div class='inner'>C</div>
  </div>
</div>

Upvotes: 0

Brother58697
Brother58697

Reputation: 3178

Not perfect, but you can get really close with grids and auto-fit (1) and minmax.

We set the min value in our min max to the width it'll wrap after, and the max to 1fr for the cells to flex with the grid.

The issue is repeat() with auto-fit sets an equal ratio between all columns, so A will be as big as B & C until everything wraps together. Which is fine for scenarios 2 and 3 but not 1.

This could be fixed by using flex and and setting the flex-grow's accordingly so that when everything's in one line, the ratios are correct, but then in the other scenarios the ratios would have to go change again, which is an issue.

div {
  box-sizing: border-box;
  border: 1px solid red;
  margin: 1px;
  padding: 0;
}

#container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.inner { 
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
<div id="container">
  <div class='single'>A</div>
  <div class='inner'>
    <div>B</div>
    <div>C</div>
  </div>
</div>

Upvotes: 2

Related Questions