Christoph Christoph - 2 months ago 6
CSS Question

Vertically center element with dynamic height in scroll container

I have a scroll container that's usually the size of the whole screen. Inside of it I place dynamic content. So I won't know which height it has or how many elements will be inserted.

Now I want to layout it like this:


  • if there is enough space, I want the whole content vertically centered inside the scroll container

  • if the total height of the content exceeds the height of the scroll container, I want the container to just scroll the contents like there was no centering.



I created an example where I tried to solve this problem with flexbox. With content height less than the container height it works like intended. But when the content exceeds the container height, due to
justify-content
, some elements of the content are cut off:

enter image description here

You can see on the image that the scroll container's scrollTop is all the way at the top, yet elements 1 & 2 aren't visible.

I'd like to know if there is a CSS only solution. A JS solution I could do myself but that's not what I'm after. If it's not possible, that's okay too.



.container {
display: inline-block;
width: 300px;
height: 300px;
border: 2px solid red;
overflow-y: auto;
margin: 1rem 0;

display: flex;
flex-direction: column;
justify-content: center;
}
.block {
width: 80%;
height: 3rem;
margin: 1rem auto;
background: blue;
flex-shrink: 0;
color: #fff;
text-align: center;
}

<div class="container">
<div class="block">1</div>
</div>

<div class="container">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
</div>

<div class="container">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
<div class="block">5</div>
<div class="block">6</div>
<div class="block">7</div>
<div class="block">8</div>
</div>




Answer

Try applying the overflow to an inner containing div like so:

.container {
  display: inline-block;
  width: 300px;
  height: 300px;
  border: 2px solid red;
  margin: 1rem 0;
  
  display: flex;
  flex-direction: column;
  justify-content: center;
}


.inner {
  overflow-y: auto;  
}

.block {
  width: 80%;
  height: 3rem;
  margin: 1rem auto;
  background: blue;
  flex-shrink: 0;
  color: #fff;
  text-align: center;
}
<div class="container">
  <div class="inner">
    <div class="block">1</div>
  </div>
</div>

<div class="container">
  <div class="inner">
    <div class="block">1</div>
    <div class="block">2</div>
    <div class="block">3</div>
  </div>
</div>

<div class="container">
  <div class="inner">
    <div class="block">1</div>
    <div class="block">2</div>
    <div class="block">3</div>
    <div class="block">4</div>
    <div class="block">5</div>
    <div class="block">6</div>
    <div class="block">7</div>
    <div class="block">8</div>
  </div>
</div>

Comments