Martin
Martin

Reputation: 1219

How to allow scrolling with overflow visible

I've got a grid with many elements, having 3 per row. The idea is that you can scroll through them all till you reach the last element. For that I simply add overflow-y: scroll

At the same time, I've got an onhover effect which scales the hovered element by 1.01. As I've set overflow-y: scroll it cuts off the scaled element.

Here's a fiddle: https://jsfiddle.net/9a5j173x/23/

Notice the shadow is also cut, I'd like for that to be fully visible too.

.gridParent {
  height: 300px;
  width: 100%;
  background-color: #abdbe3;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  overflow-y: scroll;
}

.child {
  height: 120px;
  background-color: #063970;
  color: white;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.child:hover {
  scale: 1.05;
}
<div class="gridParent">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
  <div class="child">5</div>
  <div class="child">6</div>
  <div class="child">7</div>
</div>

Upvotes: 2

Views: 2392

Answers (2)

Nikita Chayka
Nikita Chayka

Reputation: 2137

If you are allowed to have some padding you could use this solution

The trick is to have in .gridParent some padding to "allow content growth" and then use background-clip: content-box, padding-box; to not have colored background on the "padding pixels"

The padding though should be adjusted to your specific sizes, you could play around, 10px works great for fiddle and code snippet below, in real life you might want to calculate it more precisely.

If you are not allowed to have additional padding, then most likely you would need to go to javascript, you check out discussions here - Is it possible to have a popup div that 'breaks out' of an overflow:scroll or overflow:auto container?

.gridParent {
  height: 300px;
  width: 100%;
  background-color: #abdbe3;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
    padding: 10px;
  overflow-y: scroll;
  background-clip: content-box, padding-box;
}

.child {
  height: 120px;
  background-color: #063970;
  color: white;
  
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.child:hover {
  scale: 1.05;
}
  <div class="gridParent">
    <div class="child">1</div>
    <div class="child">2</div>
    <div class="child">3</div>
    <div class="child">4</div>
    <div class="child">5</div>
    <div class="child">6</div>
    <div class="child">7</div>
  </div>

Upvotes: 2

Adam
Adam

Reputation: 5909

Just add padding-bottom with a small value to the parent grid container and that works. I've also used the transform-origin with :child selectors so that the left and right elements don't get clipped and the top row moves down.

.gridParent {
  height: 300px;
  width: 100%;
  background-color: #abdbe3;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  overflow-y: scroll;
  overflow-x: hidden;
  padding-bottom: 1rem;
}

.child {
  height: 120px;
  background-color: #063970;
  color: white;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  transition-property: all;
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  transition-duration: 150ms;
}

.child:hover {
  scale: 1.05;
}

.child:nth-child(3n+1) {
  transform-origin: left;
}

.child:nth-child(3n+3) {
  transform-origin: right;
}

.child:first-child {
  transform-origin: top left;
}

.child:nth-child(2) {
  transform-origin: top;
}

.child:nth-child(3) {
  transform-origin: top right;
}
<div class="gridParent">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
  <div class="child">5</div>
  <div class="child">6</div>
  <div class="child">7</div>
</div>

Upvotes: 0

Related Questions