Skip to content
Advertisement

Avoid vertical scrollbar shift in container

In html, I have a panel with a fixed height which contains cards. It can contain one card or many cards. Hence, because the panel has a fixed height, it can be needed to have a scrollbar displayed in order to visualize all cards. This works properly with the property overflow: auto.

However, when the scrollbar is displayed, cards are shift. I would like to avoid that or at least hide this shift with a trick. I checked a lot of similar questions that suggests to use padding-left: calc(100vw - 100%); but it did not work since it is not the body scrollbar. The width of the card needs to be responsive according to the container’s width.

Something that could work is to set the overflow: overlay and add a padding-right. However, this is not a standard and not compatible with firefox.

Here, you can find a reproduce example:

let flag = true;

const setHeight = () => {
  if (flag) {
    document.getElementById('container').style.setProperty('height', '100%');
  } else {
    document.getElementById('container').style.removeProperty('height');
  }
  flag = !flag;
};

document.getElementById('button').addEventListener('click', setHeight);
setHeight();
.panel-container {
  height: 300px;
  width: 510px;
  padding: 8px 20px 0;
  background-color: blue;
  overflow: auto;
}

.card {
  height: 86px;
  width: 100%;
  background-color: grey;
  border-radius: 3px;
  border: 1px solid red;
  margin-bottom: 10px;
  cursor: pointer;
}

.scrollbar::-webkit-scrollbar-track {
  width: 14px;
}

.scrollbar::-webkit-scrollbar-thumb {
  border-radius: 8px;
  border: 4px solid green;
}

.scrollbar::-webkit-scrollbar-corner {
  background-color: transparent;
}

.scrollbar::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
<button id="button">With/Without overflow</button>
<div id="container" class="panel-container scrollbar">
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
</div>

Advertisement

Answer

In fact, it was quite simple. Just play with the margin and set the overflow to scroll.

let flag = true;

const setHeight = () => {
  if (flag) {
    document.getElementById('container').style.setProperty('height', '100%');
  } else {
    document.getElementById('container').style.removeProperty('height');
  }
  flag = !flag;
};

document.getElementById('button').addEventListener('click', setHeight);
setHeight();
.panel-container {
  height: 300px;
  width: 510px;
  padding: 8px 12px 0 20px;
  background-color: blue;
  overflow: scroll;
}

.card {
  height: 86px;
  width: 100%;
  background-color: grey;
  border-radius: 3px;
  border: 1px solid red;
  margin-bottom: 10px;
  cursor: pointer;
}

.scrollbar::-webkit-scrollbar-track {
  width: 14px;
}

.scrollbar::-webkit-scrollbar-thumb {
  border-radius: 8px;
  border: 4px solid green;
}

.scrollbar::-webkit-scrollbar-corner {
  background-color: transparent;
}

.scrollbar::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
<button id="button">With/Without overflow</button>
<div id="container" class="panel-container scrollbar">
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
  <div class="card">
    <div class="card-left-container"></div>
    <div class="card-middle-container"></div>
    <div class="card-right-container"></div>
  </div>
</div>
Advertisement