JohnnyQ
JohnnyQ

Reputation: 5119

Flex box prevent overflow and keep the right item fixed width and left item shrink

I don't have problem keeping the left item having a fixed width using the flex-basis property. But I have a scenario wherein I don't want the left element to be fixed and keep the right element's width fixed instead. I tried putting flex-basis for the right element however, the problem is the flex items overflow its container.

Is there a way to achieve this? For example I have the layout below:

enter image description here

.flex-outer {
  display: flex;
}

.dashboard {
  flex-grow: 1;
}
.col {
  margin-left: 25px;
  flex-basis: 200px;
  background: orange;
}

.flex-container {
  display: flex;
  justify-content: space-around;
}
.flex-item {
  flex: 1 1 200px;
  background: tomato;
  padding: 5px;
  height: 150px;
  margin-top: 10px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="flex-outer">
  <div class="dashboard">
    <ul class="flex-container">
      <li class="flex-item">1</li>
      <li class="flex-item">2</li>
      <li class="flex-item">3</li>
      <li class="flex-item">4</li>
      <li class="flex-item">5</li>
      <li class="flex-item">6</li>
    </ul>
  </div>

  <div class="col">

  </div>
</div>

Question

What I want to do is keep the right element (orange) 200px in a fixed width and just shrink the left flex-item (red) based on the available space. However, the problem is the right element is overflowing the container when the viewport is too narrow see image below.

enter image description here

Upvotes: 2

Views: 9357

Answers (2)

Asons
Asons

Reputation: 87201

As flex-shrink defaults to 1, it means .col is allowed to shrink below the given 200px.

Add flex-shrink: 0 to the .col rule and it won't.

Stack snippet

.flex-outer {
  display: flex;
}

.dashboard {
  flex-grow: 1;
}
.col {
  margin-left: 25px;
  flex-basis: 200px;
  flex-shrink: 0;                       /*  added  */
  background: orange;
}

.flex-container {
  display: flex;
  justify-content: space-around;
}
.flex-item {
  flex: 1 1 200px;
  background: tomato;
  padding: 5px;
  height: 150px;
  margin-top: 10px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="flex-outer">
  <div class="dashboard">
    <ul class="flex-container">
      <li class="flex-item">1</li>
      <li class="flex-item">2</li>
      <li class="flex-item">3</li>
      <li class="flex-item">4</li>
      <li class="flex-item">5</li>
      <li class="flex-item">6</li>
    </ul>
  </div>

  <div class="col">

  </div>
</div>


If you also want to completely avoid the orange box being pushed out of view, and as min-width defaults to auto, which means the dashboard and the flex-container won't get smaller than their content, you also need to set min-width: 0 to both of them so they will.

Stack snippet

.flex-outer {
  display: flex;
}

.dashboard {
  flex-grow: 1;
  min-width: 0;                         /*  added  */
}
.col {
  margin-left: 25px;
  flex-basis: 200px;
  flex-shrink: 0;                       /*  added  */
  background: orange;
}

.flex-container {
  display: flex;
  justify-content: space-around;
}
.flex-item {
  flex: 1 1 200px;
  min-width: 0;                         /*  added  */
  background: tomato;
  padding: 5px;
  height: 150px;
  margin-top: 10px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="flex-outer">
  <div class="dashboard">
    <ul class="flex-container">
      <li class="flex-item">1</li>
      <li class="flex-item">2</li>
      <li class="flex-item">3</li>
      <li class="flex-item">4</li>
      <li class="flex-item">5</li>
      <li class="flex-item">6</li>
    </ul>
  </div>

  <div class="col">

  </div>
</div>


A second option to handle the left items is of course to set flex-wrap: wrap to the flex-container

Stack snippet

.flex-outer {
  display: flex;
}

.dashboard {
  flex-grow: 1;
}
.col {
  margin-left: 25px;
  flex-basis: 200px;
  flex-shrink: 0;                       /*  added  */
  background: orange;
}

.flex-container {
  display: flex;
  flex-wrap: wrap;                      /*  added  */
  justify-content: space-around;
}
.flex-item {
  flex: 1 1 200px;
  max-width: 200px;                     /*  added, to keep them max 200px  */
  background: tomato;
  padding: 5px;
  height: 150px;
  margin-top: 10px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  display: flex;
  justify-content: center;
  align-items: center;
}
<div class="flex-outer">
  <div class="dashboard">
    <ul class="flex-container">
      <li class="flex-item">1</li>
      <li class="flex-item">2</li>
      <li class="flex-item">3</li>
      <li class="flex-item">4</li>
      <li class="flex-item">5</li>
      <li class="flex-item">6</li>
    </ul>
  </div>

  <div class="col">

  </div>
</div>

Upvotes: 5

dommmm
dommmm

Reputation: 908

What I want to do is keep the right element (orange) in a fixed width and just shrink the left flex-item (red) based on the available space.

You can use the css calc function to achieve this.

https://developer.mozilla.org/en/docs/Web/CSS/calc

Based on the classnames you used, you can do something like this:

.col {
  width: 200px;
}

.flex-container {
  width: calc(100% - 200px);
}

Upvotes: 1

Related Questions