Hi, thanks for your great slider!
I've a quite big problem with Swiper on mobile browsers: I've built a website with nested swipers, slides have 100% width and height and as requirement parent slides should move vertically (as it does with eg. parentSwiper.swiper({direction:'vertical',effect:'slide'})), some slides contain long texts that need a scrollbar when screens become smaller: using overflow-y: auto works great on desktops but on mobiles/touch devices text scrolling doesn't work (a vertical swipe triggers a slide movements while the text remains unscrollable, it should scroll text and then start moving the slider when reaching text 'borders').
Is there a way to have Swiper integrated scrollbar working for slide content? the demos show it working only for swiper-container as an aternative to pagination, it would be very useful for responsive websites/apps to have it working for slide content.
(with another project that used Swiper 2.x I got a semi-working solution for vertical swiper with vertical scrollbar for slides contents by tweaking swiper code, but it was buggy because it needs to rely on timers and double clicks/touches to allow both native overflow scrolling for contents and slides scrolling)
In theory it is possible, you have to listen touch events on "overflow-y" container and check its scroll position, and if it is not on edge position (beginning or end) then you should do e.stopPropagation to prevent parent vertical Swiper from using this events
Hi Vladimir,
thank you for quick reply! The main issue when using CSS overflow seems in edge cases evaluation:
.swiper-slide {
overflow: auto;
}
var checkScroll = function(evt){
var $slide = $(this),
scrollTop = $slide.scrollTop();
if (scrollTop > 0 && (scrollTop + $slide.height()) < $slide[0].scrollHeight) {
evt.stopPropagation();
}
};
$('.swiper-slide').on('touchmove', checkScroll);
At the beginning the "overflow-y" container has always scrollTop = 0, so evt.stopPropagation() is never triggered and the content remains unscrollable, if instead the check is >= then is slide movement that is blocked (the same for bottom edge).
I would store and evaluate an oldScrollTop value to check when scrolling "reached" the edges and in those cases avoid to trigger a stopPropagation, but I still need to figure out the correct way to do it.
still buggy in edge cases:
var oldScrollTop = 0;
var checkScroll = function(evt){
var $slide = $(this),
slideHeight = $slide.height(),
slideScrollHeight = $slide[0].scrollHeight;
if (slideHeight !== slideScrollHeight) {
// slide has content overflow
var scrollTop = $slide.scrollTop();
if (scrollTop > 0 && (scrollTop + slideHeight) < slideScrollHeight // scrolling the content
|| ((scrollTop == 0 && oldScrollTop == 0) // moving from top edge
|| ((scrollTop + slideHeight) == slideScrollHeight && (oldScrollTop + slideHeight) == slideScrollHeight))) { // moving from bottom edge
evt.stopPropagation();
}
oldScrollTop = scrollTop;
}
};
$('.swiper-slide').on('touchmove', checkScroll);
UPDATE:
I tried another way, dealing only with touch movements:
(can't use swiper callbacks because evt.stopPropagation() has no effect into swiper onTouchMove callback)
var ts = undefined,
dir = undefined;
var onTouchStart = function (evt){
ts = evt.originalEvent.touches[0].clientY;
};
var onTouchMove = function (evt){
var te = evt.originalEvent.changedTouches[0].clientY;
if(ts > te){
dir = 'slidedown';
}
else if(ts < te){
dir = 'slideup';
}
// check scroll
var $slide = $(this),
slideHeight = $slide.height(),
slideScrollHeight = $slide[0].scrollHeight;
if (slideHeight !== slideScrollHeight) {
// slide has content overflow
var scrollTop = $slide.scrollTop();
if (scrollTop > 0 && (scrollTop + slideHeight) < slideScrollHeight // scrolling the content
|| (scrollTop == 0 && dir == 'slidedown') // moving from top edge
|| ((scrollTop + slideHeight) == slideScrollHeight && dir == 'slideup')) { // moving from bottom edge
evt.stopPropagation();
}
}
};
$('.swiper-container').on('touchstart', onTouchStart);
$('.swiper-slide').on('touchmove', onTouchMove);
Need to test it on physical devices and with many slides and nested swipers, it works quite well in a basic usage case.
There is still a minor bug, when swiping without releasing finger and passing from content overflow scrolling to slide moving (edge case) the movement of the slides 'jump' to a middle position, probably because with evt.stopPropagation() called in the first part of the finger swipe, swiper starts reading coordinates with the wrong offset.
I'm wondering if this is the best way to achieve vertical content scroll on vertical swiper with a lot of slides and nested swiper instances (I mean attaching all those event handlers on each slide). Anyway thank you again Vladimir for your previous suggestion! :)
I will check it more deeper on a days to look for a better workaround
Can you give me examples of the basic HTML and sliders' setup for your case?
Ok, here is a pretty nice working solution. Works well on iOS https://jsfiddle.net/8fgphstx/1/
Here is the JS:
var swiper = new Swiper('.swiper-container', {
direction: 'vertical',
});
var startScroll, touchStart, touchCurrent;
swiper.slides.on('touchstart', function (e) {
startScroll = this.scrollTop;
touchStart = e.targetTouches[0].pageY;
}, true);
swiper.slides.on('touchmove', function (e) {
touchCurrent = e.targetTouches[0].pageY;
var touchesDiff = touchCurrent - touchStart;
var slide = this;
var onlyScrolling =
( slide.scrollHeight > slide.offsetHeight ) && //allow only when slide is scrollable
(
( touchesDiff < 0 && startScroll === 0 ) || //start from top edge to scroll bottom
( touchesDiff > 0 && startScroll === ( slide.scrollHeight - slide.offsetHeight ) ) || //start from bottom edge to scroll top
( startScroll > 0 && startScroll < ( slide.scrollHeight - slide.offsetHeight ) ) //start from the middle
);
if (onlyScrolling) {
e.stopPropagation();
}
}, true);
I think we can close it as there is no further discussion
how to deal this problem with v3.4.1
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
Ok, here is a pretty nice working solution. Works well on iOS https://jsfiddle.net/8fgphstx/1/
Here is the JS: