8

I have two panels side by side. The right-hand one contains species names, which should not wrap (they're small enough to occupy only a small part of the screen). The left-hand panel contains more things, and occupy most of the screen. Here's my code.

html,body {
  height: 100%;
}
body {
  display: flex;
  margin: 0;
  overflow-y: hidden;
}
#left {
  background-color: skyblue;
  flex-grow: 1;
  padding: 1em;
}
#right {
  background-color: indianRed;
 white-space: nowrap;
  padding: 1em;
  display: flex;
  flex-direction: column;
}
<div id='left'>
Some text wide enough to compete with the red panel -- some more words needed.
</div>
<div id='right'>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
</div>

When there's no scrollbar, the width of the right-hand panel is correct. But as soon as I add a vertical scrollbar (overflow-y: auto), it's width gets much smaller, creating also a horizontal scrollbar. Why? And how to solve it? I only want the vertical scrollbar. The width of the panel should be enough to contain all the words on it.

html,body {
  height: 100%;
}
body {
  display: flex;
  margin: 0;
  overflow-y: hidden;
}
#left {
  background-color: skyblue;
  flex-grow: 1;
  padding: 1em;
}
#right {
  background-color: indianRed;
  white-space: nowrap;
  padding: 1em;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
<div id='left'>
Some text wide enough to compete with the red panel -- some more words needed.
</div>
<div id='right'>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
</div>
TylerH
  • 20,799
  • 66
  • 75
  • 101
Rodrigo
  • 4,706
  • 6
  • 51
  • 94

5 Answers5

3

Your current flex properties are as follows:

div#left

flex-grow:1;
flex-shrink:1;
flex-basis:auto;

This means:

The div's width will be content first flex-basis:auto; then fill the remaining space flex-grow:1;

div#right

flex-grow:0;
flex-shrink:1;
flex-basis:auto;

This means:

The div's width will be content first flex-basis:auto; And shrink to fit flex-shrink:1;

This is why you see horizontal scrollbar when the vertical scroll is added, because it eats from the overall width.


Solution #1

flex-basis:0; on the left div which will make it fill the remaining space first then lay down the content

html,
body {
  height: 100%;
}

body {
  display: flex;
  margin: 0;
  overflow-y: hidden;
}

#left {
  background-color: skyblue;
  flex-grow: 1;
  flex-basis: 0;
  padding: 1em;
}

#right {
  background-color: indianRed;
  white-space: nowrap;
  padding: 1em;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
<div id='left'>
  Some text wide enough to compete with the red panel -- some more words needed.
</div>
<div id='right'>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
</div>

Solution #2

flex-shrink:0; on the right div which will prevent it from shrinking

html,
body {
  height: 100%;
}

body {
  display: flex;
  margin: 0;
  overflow-y: hidden;
}

#left {
  background-color: skyblue;
  flex-grow: 1;
  padding: 1em;
}

#right {
  background-color: indianRed;
  white-space: nowrap;
  padding: 1em;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
<div id='left'>
  Some text wide enough to compete with the red panel -- some more words needed.
</div>
<div id='right'>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
</div>

Issue with this solution is that if the content in the left div is too long there will be overflow

html,body {
  height: 100%;
}
body {
  display: flex;
  margin: 0;
  /* removed to illustrate the problem */
  /* overflow-y: hidden; */
}
#left {
  background-color: skyblue;
  flex-grow: 1; 
  padding: 1em;
}
#right {
  background-color: indianRed;
  white-space: nowrap;
  padding: 1em;
  display: flex;
  /* if you remove this there will be no overflow because the right div will shrink to fit*/
  flex-shrink:0; 
  flex-direction: column;
  overflow-y: auto;
}

#left>div{
    /* I eyeballed this value to fit the snippet in SO*/
    width:500px; 
    background-color:Red;
    height:100px;
}
<div id="left">
  <div>
    <div>
    </div>
  </div>
</div>
<div id="right">
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
  <p>Some names.</p>
  <p>Some names a little larger.</p>
</div>
</body>
Rainbow
  • 6,772
  • 3
  • 11
  • 28
  • Great solution and explanation. Hit the nail on the head. For anybody wanting more details see [the difference between `flex-basis: auto` and `flex-basis: 0`](https://stackoverflow.com/q/43520932/3597276). – Michael Benjamin Dec 10 '19 at 17:45
2

Its because of long text inside your div and you set white-space: nowrap; which prevent it to overflow

Use

#right {
    white-space: normal;
}
Awais
  • 4,752
  • 4
  • 17
  • 40
  • The text is not so long. If I can have `nowrap` without the vertical scrollbar, why not with it? – Rodrigo Dec 10 '19 at 12:57
  • Dear static width of that container prevent it to adjust its size according to the viewport so you need to overflow that text. You can also use media quries for that. – Awais Dec 10 '19 at 16:25
-1

Define both scrollbars.

body {
  display: flex;
  margin: 0;
  overflow-x: hidden;
  overflow-y: scroll; /* not auto */
}
bron
  • 1,457
  • 1
  • 9
  • 18
-1

It was browser's default functionality. If you add any of one attribute value auto then default it will add both scrollbars.

If you want to add specific then you must need to add in your code.

overflow-x: hidden;
overflow-y: scroll;
Mayur Jotaniya
  • 304
  • 1
  • 18
-1

If set overflow-y explicitly you might need to set overflow-x as well.

Or you can set width value or right div.

html,body {
  height: 100%;
}
body {
  display: flex;
  margin: 0;
}
#left {
  background-color: skyblue;
  flex-grow: 1;
  padding: 1em;
}
#right {
  background-color: indianRed;
  white-space: nowrap;
  padding: 1em;
  display: flex;
  flex-direction: column;
  overflow: auto;
  width: 100%;
}
<div id='left'>
Some text wide enough to compete with the red panel -- some more words needed.
</div>
<div id='right'>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
<p>Some names.</p>
<p>Some names a little larger.</p>
</div>
Akash Shrivastava
  • 1,365
  • 8
  • 16
  • I don't want any horizontal scrollbar. As I said, the species names (on the right) are small, and fit perfectly on the screen (I'm not considering smartphones). – Rodrigo Dec 10 '19 at 13:15
  • oh, missed there, updated snippet, setting the width might get you what you want. – Akash Shrivastava Dec 10 '19 at 13:24