Overlay Divs on Scroll

Overlay divs on scroll

Here is a proof of concept that, whilst works, does need to be tested across browsers (however I'm confident that it will work everywhere) and slightly refined.

The idea is to use JavaScript to monitor the window's scroll position and fix the appropriate content panel accordingly, giving the illusion that the new content is overlapping it when scrolling in to view.

http://jsfiddle.net/amustill/wQQEM/

Overlay 2 DIVs where one is Static and the other is Scrollable

You can achieve that with these steps:

  1. Set the position of the container (i.e. homepage) to relative.
  2. Set the position of the hero to fixed, so it doesn't scroll with the container.
  3. Set the position of the frames to absolute with z-index higher than the hero so it can overlay it.

You can see the example below. I set the container background color so we can see it and set its height to 1000px so we can test it scrolling, so those settings are for demo purpose only.

To center your hero and frames, you need these steps:

  1. Set the left and right margins to auto.
  2. Set a fixed width. This is required for the auto margins to work.
  3. Set the left and right to zero. This is required for fixed and absolute layouts to be centered.

.homepage {    background-color: #0ff;    height: 1000px;    position: relative;}
.hero-image { position: fixed; width: 150px; margin: 0 auto; left: 0; right: 0;}
.homeScreen1 { position: absolute; width: 160px; margin: 0 auto; top: 200px; left: 0; right: 0; z-index: 1;}
<div class="homepage">    <div class="hero-image">        <img src="http://placehold.it/150x150">    </div>    <div class="homeScreen1">        <img src="http://placehold.it/160x160">    </div> </div>

CSS overlay with scrolling content

You can avoid adding a container to your Bottom element by moving its height to an ::after pseudo-element:

.bottom {
overflow-y: scroll;
height: calc(100% - 80px);
}

.bottom::after {
content: '';
display: block;
height: 10000px;
}

Updated Fiddle

Prevent body scrolling but allow overlay scrolling

Theory

Looking at current implementation of the pinterest site (it might change in the future), when you open the overlay, a noscroll class is applied to the body element (setting overflow: hidden) making the body no longer scrollable.

The overlay created on-the-fly or already injected in the page and made visible via display: blockit makes no difference – has position : fixed and overflow-y: scroll, with top, left, right and bottom properties set to 0: this style makes the overlay fill the whole viewport (but now we are in 2022, so you may use inset: 0 instead).

The div inside the overlay is in position: static so the vertical scrollbar is related to that element. This is resulting in a scrollable but fixed overlay.

When you close the overlay, you have to hide it (using display: none) and you could even remove the node via javascript (or just the content inside, it's up to you but also depends on the nature of the content).

The final step is to also remove the noscroll class applied to the body (so the overflow property gets back to the value it had previously)


Code

Codepen Example

(it works by changing the aria-hidden attribute of the overlay in order to show and hide it and to increase its accessibility).

Markup

(open button)

<button type="button" class="open-overlay">OPEN LAYER</button>

(overlay and close button)

<section class="overlay" aria-hidden="true" tabindex="-1">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>

CSS

.noscroll { 
overflow: hidden;
}

.overlay {
position: fixed;
overflow-y: scroll;
inset: 0; }

[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }

Javascript (vanilla-JS)

var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]'),
openingBtt;

[].forEach.call(overlayBtts, function(btt) {

btt.addEventListener('click', function() {

/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';

/* storing a reference to the opening button */
if (overlayOpen) {
openingBtt = this;
}

/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);

/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;

/* forcing focus for Assistive technologies but note:
- if your modal has just a phrase and a button move the
focus on the button
- if your modal has a long text inside (e.g. a privacy
policy) move the focus on the first heading inside
the modal
- otherwise just focus the modal.

When you close the overlay restore the focus on the
button that opened the modal.
*/
if (overlayOpen) {
overlay.focus();
}
else {
openingBtt.focus();
openingBtt = null;
}

}, false);

});

/* detect Escape key when the overlay is open */
document.body.addEventListener('keyup', (ev) => {
if (ev.key === "Escape" && overlay.getAttribute('aria-hidden') === 'false') {
overlay.setAttribute('aria-hidden', 'true');
body.classList.toggle('noscroll', false);
openingBtt.focus();
openingBtt = null;
}
})

Finally, here's another example in which the overlay opens with a fade-in effect by a CSS transition applied to the opacity property. Also a padding-right is applied to avoid a reflow on the underlying text when the scrollbar disappears.

Codepen Example (fade)

CSS

.noscroll { overflow: hidden; }

@media (min-device-width: 1025px) {
/* not strictly necessary, just an experiment for
this specific example and couldn't be necessary
at all on some browser */
.noscroll {
padding-right: 15px;
}
}

.overlay {
position: fixed;
overflow-y: scroll;
inset: 0;
}

[aria-hidden="true"] {
transition: opacity 1s, z-index 0s 1s;
width: 100vw;
z-index: -1;
opacity: 0;
}

[aria-hidden="false"] {
transition: opacity 1s;
width: 100%;
z-index: 1;
opacity: 1;
}

How to get overlay to cover the entire page even when scrolling

just move: background: #dff9fb; from .popup to .overlay

* {padding: 0; margin: 0; box-sizing: border-box; }
body { padding: 152px 32px; position: relative; }
.overlay-text { height: 100%; min-height: 100%;}
.overlay { z-index: 10; position: fixed; top: 0; left: 0; bottom: 0; right: 0; width: 100%; height: 100vh; visibility: hidden; opacity: 0; overflow-y: scroll; background: #dff9fb;}
.overlay:target { visibility: visible; opacity: 1;}
iframe { margin: 0 auto; display: block;}
.popup { height: 100%; position: relative; padding-top: 24px;}
.close { position: absolute; top: 12px; right: 16px;}
<ul>
<li>
<a href=#popup1> <img class="new-tracks__image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1774776/new.jpg"></a>
<div id="popup1" class="overlay"> <div class="popup">
<h2>Jerry Craft - <em>"New Kid"</em></h2>
<iframe src="https://open.spotify.com/embed/album/2yFC1YqdyPHnpCGJubdGaK" width="300" height="80" frameborder="0" allowtransparency="true" allow="encrypted-media"></iframe>
<div class="overlay-text"> <p>The three Greystone kids always raced each other home when they got off the school bus, and Finn always won.</p>
<p>It wasn’t because he was the fastest.</p>
<p>Even he knew that his older brother and sister, Chess and Emma, let him win so he could make a grand entrance.</p>
<p>Today he burst into the house calling out, “Mom! We’re home! It’s time to come and adore us!”</p>
<p>“Adore” had been on his second-grade spelling list two weeks ago, and it had been a great discovery for him. So that was what it was called, the way he had felt his entire life.</p>
<p>Emma, who was in fourth grade, dropped her backpack on the rug beside him and kicked off her red sneakers. They flipped up and landed on top of the backpack—someday, Finn vowed, he would get Emma to teach him that trick.</p>
<p>“Twenty-three,” Emma said. There was no telling what she might have been counting. Finn hoped it was a prediction of how many chocolate chips would be in every cookie Mom was probably baking for them right now, for their after-school snack.</p>
<p>Finn sniffed. The house did not smell like cookies.</p>
<p>Oh well. Mom worked from home, designing websites, and sometimes she lost track of time. If today was more of a Goldfish-crackers-and-apple-slices kind of day, that was okay with Finn. He liked those, too.</p>
<p>“Mom!” he called again. “Your afternoon-break entertainment has arrived!”</p>
<p>“She’s in the kitchen,” Chess said, hanging his own backpack on the hook where it belonged. “Can’t you hear?”</p>
<p>“That would mean Finn had to listen for once, instead of talking,” Emma said, rubbing Finn’s head fondly and making his messy brown hair even messier. Finn knew she didn’t mean it as an insult. He was pretty sure Emma liked talking as much as he did.</p>
<a class="close" href="#">×</a> </div> </div> </li>
</ul>

Pure CSS overlay scrolling

position:sticky can approximate this:

.headervideo {
background: url(https://picsum.photos/id/1064/800/800) center/cover;
height: 100vh;
position: relative;
z-index: 2;
}

.nextsection {
background: url(https://picsum.photos/id/107/800/800) center/cover;
height: 100vh;
margin-top: -100vh;
position: sticky;
top: 0;
}

.container {
height:200vh;
}

body {
margin: 0;
}
<div class="container">
<div class="headervideo"></div>

<div class="nextsection"></div>
</div>

<div style="height:150vh"> more content later </div>


Related Topics



Leave a reply



Submit