1

In the interface below, the (parent) .panel (styled using flex) won't scroll below the bottom edge of the last (child) .item even though the last .item (like the all the others) should have a margin-bottom of 12px.

That's what I'm trying to achieve:

When I scroll down, I want to see the 12px bottom margin of the last .item.

Here's the interface:

.interface {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  padding: 60px 0;
  font-family: sans-serif;
  color: rgb(255, 255, 255);
  background-color: rgb(159, 0, 0);
  opacity: 1;
}

.header,
.footer {
  position: fixed;
  left: 0;
  z-index: 12;
  width: 100%;
  height: 60px;
  line-height: 60px;
  text-align: center;
  background-color: rgb(159, 0, 0);
  box-shadow: 0 0 6px rgba(15, 0, 0, 0.4);
}

.header {
  top: 0;
}

.heading {
  margin: 0;
  padding: 0;
}

.footer {
  bottom: 0;
}

.credit {
  margin: 0;
  padding: 0;
}

.intro {
  height: 60px;
  margin: 0;
  padding: 0;
  line-height: 60px;
  font-size: 20px;
  text-transform: uppercase;
  text-align: center;
  background-color: rgba(127, 0, 0, 0.4);
  box-shadow: 0 0 6px rgba(15, 0, 0, 0.4);
}

.panel {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  height: calc(100vh - 180px);
  padding-top: 12px;
  overflow-y: scroll;
  box-sizing: border-box;
  transform: translateY(0);
}

.item {
  flex: 0 1 30vw;
  height: 160px;
  margin: 12px;
  line-height: 160px;
  text-align: center;
  text-shadow: 1px 1px 1px rgba(31, 0, 0, 0.4);
  background-color: rgba(47, 0, 0, 0.4);
  border: 1px solid rgb(95, 0, 0);
}


@media only screen and (max-width: 906px) {

  .item {
    flex: 0 1 44vw;
  }
}


@media only screen and (max-width: 590px) {

  .item {
    flex: 0 1 96vw;
  }
}
<aside class="interface">

<header class="header">
<h2 class="heading">Title</h2>
</header>

<p class="intro">Text-based introduction here.</p>

<div class="panel">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
</div>

<footer class="footer">
<p class="credit">Credit</p>
</footer>

</aside>

N.B. Open the Code Snippet above to Full page.

Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 1
    I suppose you are testing on Firefox because in Chrome it's fine – Temani Afif Apr 15 '20 at 11:03
  • Hah! Yes. I do all of my CSS design work on Firefox. I haven't tested it on Chrome yet. – Rounin Apr 15 '20 at 11:09
  • 1
    It may have something to do with elements being "over-constrained". The pseudo element is one potential workaround (btw, you don't need to add `display: block`). You can also use a transparent bottom border. https://stackoverflow.com/q/38993170/3597276 – Michael Benjamin Apr 15 '20 at 13:58
  • I thought your `border-bottom` suggestion was inspired. Unfortunately (I just tried it) it won't work because the `12px` border displays beneath the right hand scroll bar. – Rounin Apr 15 '20 at 14:04
  • 1
    Well then you still have the pseudo element. It's a hack, of course, but not a particularly nasty one. Just a minor workaround, in my view. – Michael Benjamin Apr 15 '20 at 15:19

1 Answers1

1

One approach to solving this issue is to use an ::after pseudo-element, like this:

.panel::after {
  content: '';
  display: block;
  width: 100vw;
  height: 12px;
  background-color: transparent;
}

This would re-create the 12px bottom margin which isn't otherwise displaying.

This is a little hack-y, since the only reason to include the ::after pseudo-element is as a "helper" - it's pretty much a spacer GIF. (But still much less obtrusive than a wrapper <div>.)

Working Example of interface with ::after pseudo-element:

.interface {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  padding: 60px 0;
  font-family: sans-serif;
  color: rgb(255, 255, 255);
  background-color: rgb(159, 0, 0);
  opacity: 1;
}

.header,
.footer {
  position: fixed;
  left: 0;
  z-index: 12;
  width: 100%;
  height: 60px;
  line-height: 60px;
  text-align: center;
  background-color: rgb(159, 0, 0);
  box-shadow: 0 0 6px rgba(15, 0, 0, 0.4);
}

.header {
  top: 0;
}

.heading {
  margin: 0;
  padding: 0;
}

.footer {
  bottom: 0;
}

.credit {
  margin: 0;
  padding: 0;
}

.intro {
  height: 60px;
  margin: 0;
  padding: 0;
  line-height: 60px;
  font-size: 20px;
  text-transform: uppercase;
  text-align: center;
  background-color: rgba(127, 0, 0, 0.4);
  box-shadow: 0 0 6px rgba(15, 0, 0, 0.4);
}

.panel {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  height: calc(100vh - 180px);
  padding-top: 12px;
  overflow-y: scroll;
  box-sizing: border-box;
  transform: translateY(0);
}

.item {
  flex: 0 1 30vw;
  height: 160px;
  margin: 12px;
  line-height: 160px;
  text-align: center;
  text-shadow: 1px 1px 1px rgba(31, 0, 0, 0.4);
  background-color: rgba(47, 0, 0, 0.4);
  border: 1px solid rgb(95, 0, 0);
}

.panel::after {
  content: '';
  display: block;
  width: 100vw;
  height: 12px;
  background-color: transparent;
}


@media only screen and (max-width: 906px) {

  .item {
    flex: 0 1 44vw;
  }
}


@media only screen and (max-width: 590px) {

  .item {
    flex: 0 1 96vw;
  }
}
<aside class="interface">

<header class="header">
<h2 class="heading">Title</h2>
</header>

<p class="intro">Text-based introduction here.</p>

<div class="panel">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
</div>

<footer class="footer">
<p class="credit">Credit</p>
</footer>

</aside>

N.B. Open the Code Snippet above to Full page.

Rounin
  • 27,134
  • 9
  • 83
  • 108