Luca Detomi
Luca Detomi

Reputation: 5716

Prevent shrinking in a scrollable flex container and space flex items vertically

I have a container with many items inside.

I would like to display them alternatively on a single row (with eventually an horizontal scrollbar on container) or wrapped in multiple rows.

I thought to use Flexbox Layout module. Two examples are visible in this here:

.single-line {
  border: solid 1px blue;
  width: 50%;
  overflow-x: scroll;
}
.wrap-line {
  border: solid 1px green;
  width: 50%;
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}
.single-line ul {
  flex-wrap: nowrap;
}
.wrap-line ul {
  flex-wrap: wrap;
}
li {
  display: block;
  width: 40px;
  height: 40px;
  background: gray;
  text-align: center;
  border: solid 1px red;
  line-height: 40px;
}
<div class="single-line">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
</div>

<br>

<div class="wrap-line">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
</div>

jsFiddle:

The most important code is the following:

ul {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}

.single-line ul {
  flex-wrap: nowrap;
}

.wrap-line ul {
  flex-wrap: wrap;
}

It is close to what I would like but there are some issues:

  1. First example shrinks inner blocks, so the container is not scrollable. How to solve that?

  2. In the second example, how do I add vertical separation between lines but not at the edges of the container? I thought about margin-bottom on each LI but this is not the right solution (and I can't set a fixed height for container)

Upvotes: 4

Views: 2186

Answers (2)

Ula
Ula

Reputation: 624

I've made something like this: https://jsfiddle.net/yduhj30L/18/ flex-shrink: 0 makes that flex element can overflow.

On second I set margin-top only to one element and set position to flex-end for each.

Edit: align items to flex-start makes scrolled items accessible.

Upvotes: 2

vals
vals

Reputation: 64194

You have already answers for the first question.

About the second, all you need is a little trick.

Set margin top on all the items.

To hide this margin for the first row, set a negative margin of the same amount for the ul. Since you have an outer container, the ul sits outside this container in the amount needed for the upper magin to be invisible

hover the ul to shrink it and test it

.wrap-line {
  border: solid 1px green;
  width: 70%;
  transition: width 5s;
}

.wrap-line:hover {
  width: 30%;  
}
ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}
.wrap-line ul {
  flex-wrap: wrap;
  margin-top: -10px; /* added */
}
li {
  display: block;
  width: 40px;
  height: 40px;
  background: gray;
  text-align: center;
  border: solid 1px red;
  line-height: 40px;
  margin-top: 10px; /* added */
}
<div class="wrap-line">
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
</div>

Upvotes: 1

Related Questions