Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display only the number of items that will fit, and then expand to fit snugly

Tags:

css

layout

I have a container that I want to fit a number of children in horizontally, but I know I have more children than will often fit.

+-----------------------+
|                       |
|                       |
+-----------------------+

+----+ +----+ +----+ +----+ +----+ +----+ 
|    | |    | |    | |    | |    | |    | 
|    | |    | |    | |    | |    | |    | 
+----+ +----+ +----+ +----+ +----+ +----+ 

Using only CSS, how do I only display the items that can fit, and expand them to fit snugly?

Desired result:

+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |     |
+-----+-----+-----+-----+
like image 266
Nathan Arthur Avatar asked Aug 10 '17 20:08

Nathan Arthur


2 Answers

The solution can be broken into two pieces:

Hiding elements that don't fit

  • Give the container a defined width and height.
  • Define children's height to be the same as the container's height.
  • Set the container to overflow: hidden; so children that wrap disappear.

(Thanks to this answer for inspiring this part of the solution.)

Expanding children that do fit to take up available space snugly

  • Set your container as display: flex; so children can grow.
  • Set your container to flex-wrap: wrap; so children that won't fit can still wrap and disappear.
  • Set children to flex: 1 0 [desired minimum width]; so children can only grow, not shrink.

The result

ul {
  border: 1px solid red;
  width: 350px;
  height: 100px;
  overflow: hidden;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
}

ul > li  {
  border: 1px solid blue;
  display: block;
  flex: 1 0 100px;
  height: 100px;
  box-sizing: border-box;
}
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
  <li>Item 7</li>
</ul>
like image 133
Nathan Arthur Avatar answered Nov 02 '22 23:11

Nathan Arthur


@NathanArthur's solution is great for cases where you have a fixed height, however in the case you don't know your height things get a bit more hairy.

To do this without a fixed height you can use display: grid. Browser support for css grid currently is pretty limited to latest versions, but I believe this would be one of few (if not the only) way to do with without a fixed height.

But what you can do is set up a display: grid with auto-fit columns using the repeat() function combined with the minmax() function. This will give you columns with a minimum size set by you, which will fill the rest of the space needed. Combine this with grid-auto-rows: 0px which will hide any additional rows added by child auto placement which happens if they start to go outside the bounds of the defined grid-template parameters. Looks a little something like this, note no defined heights and variable widths:

ul {
  border: 1px solid red;
  width: 350px;
  overflow: hidden;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  grid-template-rows: 1fr;
  grid-auto-columns: 0px;
  grid-auto-rows: 0px;
}

ul.test2{
  width: 520px;
}

ul > li  {
  border: 1px solid blue;
  box-sizing: border-box;
}
  
<ul>
  <li>Item 1</li>
  <li>Item 2<br><br><br> with some extra height</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
  <li>Item 7</li>
</ul>
<ul class="test2">
  <li>Item 1</li>
  <li>Item 2<br><br><br> with some extra height</li>
  <li>Item 3</li>
  <li>Item 4</li>
  <li>Item 5</li>
  <li>Item 6</li>
  <li>Item 7</li>
</ul>
like image 25
Don Avatar answered Nov 02 '22 23:11

Don