8

I'm trying to get an element to have items aligned to the right, and all overflowing elements to be hidden but accessed by scrollbar.

But it seems like the scrollbar disappears when specifying justify-content: flex-end. Why is that, and how do I fix it?

Here is demo: https://jsfiddle.net/efguz4mp/1/

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  overflow: auto;
  justify-content: flex-end;
}

.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

...and here is demo without justify-content: flex-end;: https://jsfiddle.net/efguz4mp

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  overflow: auto;
}

.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Jacob
  • 1,933
  • 2
  • 20
  • 30

3 Answers3

9

When an overflow occur to the left (or top), a scroll doesn't get rendered, and the reason is that a HTML document's normal flow is left-to-right (top-to-bottom).

Flexbox has a row-reverse direction, which will solve that, thought 2 things comes with that:

  • One need to reorder the items or use an inner wrapper

  • I.a. Firefox and Edge doesn't show the scroll (possible bug)

Stack snippet

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  flex-direction: row-reverse;
  overflow: auto;
}
.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}

/* no wrapper */
.row > .box:nth-child(1) { order: 6; }
.row > .box:nth-child(2) { order: 5; }
.row > .box:nth-child(3) { order: 4; }
.row > .box:nth-child(4) { order: 3; }
.row > .box:nth-child(5) { order: 2; }
.row > .box:nth-child(6) { order: 1; }

/* wrapper */
.inner {
  display: flex;
}
<div class="row">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
</div>

<div><br><br></div>

<div class="row">
  <div class="inner">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
    <div class="box">6</div>
  </div>
</div>

Possible workarounds are:

  • Use direction: rtl to change the flow direction

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  overflow: auto;
  direction: rtl;
}
.inner {
  display: flex;
  direction: ltr;
}
.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="inner">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
    <div class="box">6</div>
  </div>
</div>
  • Use transform to flip the row element

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  overflow: auto;
  transform: scale(-1,1);        /*  flip horizontally  */
}
.inner {
  display: flex;
  transform: scale(-1,1);        /*  reset so items is not backwards  */
}
.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="inner">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
    <div class="box">5</div>
    <div class="box">6</div>
  </div>
</div>
  • Use a script on page load to scroll to the right

window.addEventListener("load", function(e) {
  var el = document.querySelector(".row");
  el.scrollLeft = el.scrollWidth;
});
.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  display: flex;
  overflow: auto;
}
.box {
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="box">1</div>
  <div class="box">2</div>
  <div class="box">3</div>
  <div class="box">4</div>
  <div class="box">5</div>
  <div class="box">6</div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
3

The main problem is that you're dealing with a contradiction:

  • The justify-content property is designed to distribute extra space in the container.

  • However, an overflow condition occurs when there is no space left in the container.

Basically, justify-content and overflow have no association. The former applies only inside the container. The latter applies only outside the container.

With justify-content: flex-end, the flex items must be packed at the end of the container (not the end of the flex-start overflow area).

If the end-aligned items are too big to fit in the container, they will overflow on the start side, which is what you're seeing in your layout. But because the overflow property only applies in the direction of the writing mode (LTR, in this case), scrollbars are not rendered (more details).

So I would suggest forgetting about justify-content to make this layout work.

Instead, consider this: Use an invisible spacer item to push your content items to the right.

.row {
  display: flex;
  overflow: auto;
  max-width: 500px;
  background: #DADADA;
}

.box {
  flex: 0 0 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
}

.row::before {
  content: "";
  flex: 0 0 400px;
  visibility: hidden;
}
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

You'll notice that the last item margin collapses. That issue is explained here:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
-2

Here's how I would recommend you do it

.row {
  width: 100%;
  max-width: 500px;
  background: #DADADA;
  flex: 1;
    display: flex;
    overflow: auto;
}
.box {
  display: flex;
  width: 200px;
  height: 40px;
  margin: 4px 10px;
  background: red;
  flex-shrink: 0;
}
<div class="row">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
LOTUSMS
  • 10,317
  • 15
  • 71
  • 140