Take a look at this codepen
There's red square in the corner.
If you click (using mouse or touchpad) this square and drag it down - in Safari on Mac .parent
element will scroll down.
Even though .parent has overflow-y: hidden;
No scrolling occurs in all other browsers.
How can I prevent this scrolling on safari?
As a rough solution, I can listen to the scroll and override the scrollTop if it's not zero, but perhaps there is a more elegant solution?
You can add an intermediary div. then, set width, height, overflow properties to it.
.parent {
width: 200px;
height: 200px;
border: 1px dashed black;
overflow-x: auto;
overflow-y: hidden;
}
/** intermediary div */
.parent > div {
width: 200%;
height: 100%;
overflow: hidden;
}
.child {
width: 100%; /** this should be 100% **/
height: 200%;
background: linear-gradient(to right bottom, red, tomato), linear-gradient(to bottom, white, black);
background-size: 50px 50px, 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
<div class="parent">
<div>
<div class="child"></div>
</div>
</div>
Or add pointer-events:none
to parent.
.parent {
/* This prevents dragging */
pointer-events: none;
width: 200px;
height: 200px;
border: 1px dashed black;
overflow-x: auto;
overflow-y: hidden;
}
.child {
width: 200%;
height: 200%;
background: linear-gradient(to right bottom, red, tomato), linear-gradient(to bottom, white, black);
background-size: 50px 50px, 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
<div class="parent">
<div class="child"></div>
</div>
Using css you can give pointer-events:none; to avoid any events occurring while clicking it.
This is definitely an interesting find! You'd think this would be impossible since you set overflow-y
to none
. Nonetheless you can prevent this behavior and disallow clicks inside the parent using this JavScript:
const parent = document.querySelector('.parent');
parent.addEventListener('mousedown', e => e.preventDefault());
By adding preventDefault()
to the event triggered on mousedown
, you prevent the browser from evaluating any further events related to that click, including dragging. Here it is in action:
const parent = document.querySelector('.parent');
parent.addEventListener('mousedown', e => e.preventDefault());
.parent {
width: 200px;
height: 200px;
border: 1px dashed black;
overflow-x: auto;
overflow-y: hidden;
}
.child {
width: 200%;
height: 200%;
background: linear-gradient(to right bottom, red, tomato), linear-gradient(to bottom, white, black);
background-size: 50px 50px, 100% 100%;
background-repeat: no-repeat;
background-position: center;
}
<div class="parent">
<div class="child"></div>
</div>