“This is the first day of my participation in the First Challenge 2022. For details: First Challenge 2022”
Mobile terminal to prevent popover lower page sliding method
During H5 development, popovers are required in many scenarios
When a popover occurs, it is expected that the page below the popover cannot be slid in most scenarios
You certainly don’t expect popovers to slide
Recently the liver page encountered this problem again
Here are some of the most common approaches, along with some boundary cases and coping strategies
overflow:hidden
The most popular way is to set overflow: Hidden for elements
Setting the body prevents the page from sliding
document.body.style.overflow = 'hidden'
document.body.style.overflow = 'visible'
Copy the code
This works in most cases
But on some machines, this doesn’t work:
Popup window mask
There is also a case where some elements of the page have local sliding
<body style="overflow:hidden;">
<div style="overflow:scroll; height:100%;">
<! -- more element -->
</div>
</body>
Copy the code
The current situation sets overflow:hidden for the body to still have no effect
Add the following mask to the popover, and under normal circumstances, the lower element will not receive the TouchMove event
<body style="overflow:hidden;">
<div style="overflow:scroll; height:100%;">
<! -- more element -->
</div>
<! -- dialog -->
<div class="dialog">
<! - mask - >
<div class="mask" style="position:fixed; inset:0;"></div>
<div class="content"></div>
</div>
</body>
Copy the code
Where the inset property is short for left,top,right,bottom
On some models, however, the underlying element still receives the TouchMove event and slides accordingly
So you need to sacrifice the following method
prevent touchmove
Prevents the default behavior of the touchswipe event TouchMove
const touchHandle = function(e) {
e.preventDefault()
}
// Popover events
{
onShow(){
document.body.addEventListener('touchmove', preventDefault, {
passive: false}); },onHide(){
document.body.removeEventListener('touchmove', preventDefault); }}Copy the code
Prevents the default behavior of the sliding event of the target element directly when the popover opens
This method is most efficient if the popover content is not slidable
If there is something to slide in the popover, and the sliding content is complicated
Then fine force control via TouchMove can be troublesome when preventing sliding events
position:fixed
There is also a common position:fixed
The target element is fixed when the popover opens and restored when it closes
Because positioning changes the position of the element on the page, you need to record the position of the element before fixing it
Unfixed scrolls the element back to its original position
// Popover events
{
onShow(){
document.body.style.top = `The ${document.body.getClientRects()[0].top
}px`;
document.body.style.position = 'fixed';
document.body.style.left = '0';
document.body.style.right = '0';
},
onHide(){
document.body.style.position = 'visible';
window.scrollTo(
0.Math.abs(+document.body.style.top.replace('px'.' '))); }}Copy the code
Use class instead of style
This also happens to be found in the iOS low-end machine will be the above way after trying
There is still a problem, the phenomenon is as follows (TODO: complementary graph)
Lower pages will no longer slide, but masks and pop-ups as a whole can still be pulled down
A popover is a drop-down list popover whose position needs to be dynamically calculated, as shown in the following structure
<body style="overflow:hidden;">
<! -- dialog -->
<div class="dialog" style="top:88px;">
<! - mask - >
<div class="mask" style="position:fixed; inset:0;"></div>
<! - content - >
<div class="content"></div>
</div>
</body>
Copy the code
The result is that the style and class Settings are displayed in the same way on this model
But the actual interactions are inconsistent
The fixed HTML structure looks like this, inserting a style tag in the element, using the class selector and! Important overrides the distance style
<body style="overflow:hidden;">
<! -- dialog -->
<div class="dialog" style="top:88px;">
<! - mask - >
<div class="mask" style="position:fixed; inset:0;"></div>
<! - content - >
<div class="content"></div>
<style>
.dialog{
top:88px ! important;
}
</style>
</div>
</body>
Copy the code
The following code
{
onShow(){
setTimeout(() = > {
const dialogEl = document.querySelector<HTMLElement>('.dialog')
if(! dialogEl) {return
}
const style = document.createElement('style')
style.textContent = `
.dialog{
top:${dialogEl.style.top}! important; } `
dialogEl.append(style)
}, 200)}}Copy the code
It’s a very confusing operation, but it solves the problem
summary
For the abnormal scene that the lower page of the popup window on the mobile terminal can be slid
This article introduces four common solutions and a “puzzle operation.”
The demo presentation
-
The demo address
-
PC code scanning experience
-
Demo source code address