Teoria
Observando a implementação atual do site do pinterest (isso pode mudar no futuro), quando você abre a sobreposição, uma noscroll
classe é aplicada ao body
elemento e overflow: hidden
é definida, portanto, body
não é mais rolável.
A sobreposição (criado on-the-fly ou já dentro da página e tornada visível através display: block
, não faz diferença) tem position : fixed
e overflow-y: scroll
, com top
, left
, right
e bottom
propriedades definido para0
: esse estilo faz a sobreposição de preencher toda a janela.
A parte div
interna da sobreposição é apenas position: static
a barra de rolagem vertical que você vê relacionada a esse elemento. Como resultado, o conteúdo é rolável, mas a sobreposição permanece fixa.
Quando você fecha o zoom, oculta a sobreposição (via display: none
) e também pode removê-la completamente via javascript (ou apenas o conteúdo interno, cabe a você como injetá-la).
Como etapa final, você também deve remover a noscroll
classe para body
(para que a propriedade overflow retorne ao seu valor inicial)
Código
Exemplo de Codepen
(funciona alterando o aria-hidden
atributo da sobreposição para mostrá-lo e ocultá-lo e aumentar sua acessibilidade).
Marcação
(botão aberto)
<button type="button" class="open-overlay">OPEN LAYER</button>
(botão de sobreposição e fechamento)
<section class="overlay" aria-hidden="true">
<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;
top: 0; right: 0; bottom: 0; left: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
Javascript (baunilha-JS)
var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]');
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* 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;
}, false);
});
Finalmente, aqui está outro exemplo no qual a sobreposição é aberta com um efeito de desvanecimento por um CSS transition
aplicado à opacity
propriedade. Também padding-right
é aplicado um para evitar um refluxo no texto subjacente quando a barra de rolagem desaparecer.
Exemplo de Codepen (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;
top: 0; left: 0; right: 0; bottom: 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;
}