停止在移动设备上滚动过去最后一个 Div

Posted

技术标签:

【中文标题】停止在移动设备上滚动过去最后一个 Div【英文标题】:Stop Scrolling Past last Div on mobile device 【发布时间】:2021-04-15 10:05:49 【问题描述】:

只是提醒您,我创建网站的经验很少,所以我的代码非常混乱(大量代码来自尝试,我不会删除)。

我的网站在桌面上工作,但当我尝试在我的 Ipad 上滚动时,我跳过了页面。

我希望它在到达最后一个 Div 的末尾时停止滚动。

这里是截图:http://chrisandlisa.com/Images/errorScreenShot.jpeg

我的网站:http://chrisandlisa.com

我的 CSS 文件开始变大,但代码如下:

@charset "utf-8";
/* CSS Document */

@font-face 
    font-family: 'alice_in_wonderlandregular';
    src: url('font/alice_in_wonderland_3-webfont.woff2') format('woff2'),
         url('font/alice_in_wonderland_3-webfont.woff') format('woff');
    font-weight: normal;
    font-style: normal;



* 
        margin: 0;
        padding: 0;
        border: 0;
        outline: 0;
        vertical-align: baseline;
        background: transparent;
    

body, html 


header 
    overflow: hidden;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;



.object-fit_contain  
    object-fit: contain;
    object-position: center top;




  /* Parallax base styles
  --------------------------------------------- */

  .parallax 
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
    -webkit-perspective: 1px;
    perspective: 1px;
  

  .parallax__layer 
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
  

  .parallax__layer--base 
    -webkit-transform: translateZ(0);
    transform: translateZ(0);
  

  .parallax__layer--back 
    -webkit-transform: translateZ(-1px) scale(2);
    transform: translateZ(-1px) scale(2);
  


  /* demo styles
  --------------------------------------------- */

  body 
    font-family: 'alice_in_wonderlandregular', Arial, sans-serif;
    font-weight:normal;
    font-style:normal;
    text-align: left;  
    font-size: 100%;
  

  .parallax 
    font-size: 200%;
  

   /* add some padding to force scrollbars */
  .parallax__layer 
    padding-top: 0;
    padding-right: 0;
    padding-left: 0;
    margin: 0;
    padding-bottom: 0;
  
  
.bg1 
    background: url("Images/backgroundcopy.jpg");
    -webkit-background-size: contain;
    -moz-background-size: contain;
    -o-background-size: contain;
    background-size: contain;
    background-repeat: repeat-y;

#parallax1 
    display: block;
    margin-left: auto;
    margin-right: auto;
    transition: opacity 0.1s;
    


#parallax2 

.front
    opacity: 1;

.middle
    opacity: 0;

.bottomPadding
    

.banner1 
    float: none;
    width: 869px;
    display: block;
    margin: 0 auto 0 auto;
    padding-top: 10px;

.content1 
    float: none;
    width: 300px;
    display: block;
    margin: 0 auto 0 auto;
    padding-top: 10px;


.y-mandatory 
    -webkit-overflow-scrolling: touch; 
    scroll-behavior: smooth;
    overflow-scrolling: touch;
    scroll-snap-type: y mandatory;


.y-proximity 
    -webkit-overflow-scrolling: touch; 
    scroll-behavior: smooth;
    overflow-scrolling: touch;
    scroll-snap-type: y proximity;


.y-scroll-snap-start
        scroll-snap-align: start;
        scroll-snap-stop: normal;

.no-support 
  text-align: center;


@supports(scroll-snap-type: y mandatory) 
  .no-support 
    display: none;
  



img[class]  
  width: 100%;


a

  text-decoration: none;
  color: #FFFFFF;
  
  transition: color 0.3s ease;


a:hover

  color: #D9B374;


#menuToggle

  display: block;
  position: absolute;
  top: 50px;
  right: 50px;
  
  z-index: 1;
  
  -webkit-user-select: none;
  user-select: none;


#menuToggle input

  display: block;
  width: 40px;
  height: 32px;
  position: absolute;
  top: -7px;
  left: -5px;
  cursor: pointer;
  
  opacity: 0; /* hide this */
  z-index: 2; /* and place it over the hamburger */
  
  -webkit-touch-callout: none;


/*
 * Just a quick hamburger
 */
#menuToggle span

  display: block;
  width: 33px;
  height: 4px;
  margin-bottom: 5px;
  position: relative;
  
  background: #000000;
  border-radius: 3px;
  
  z-index: 1;
  
  transform-origin: 4px 0px;
  
  transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
              background 0.5s cubic-bezier(0.77,0.2,0.05,1.0),
              opacity 0.55s ease;


#menuToggle span:first-child

  transform-origin: 0% 0%;


#menuToggle span:nth-last-child(2)

  transform-origin: 0% 100%;


/* 
 * Transform all the slices of hamburger
 * into a crossmark.
 */
#menuToggle input:checked ~ span

  opacity: 1;
  transform: rotate(45deg) translate(-2px, -1px);
  background: #FFFFFF;


/*
 * But let's hide the middle one.
 */
#menuToggle input:checked ~ span:nth-last-child(3)

  opacity: 0;
  transform: rotate(0deg) scale(0.2, 0.2);


/*
 * Ohyeah and the last one should go the other direction
 */
#menuToggle input:checked ~ span:nth-last-child(2)

  opacity: 1;
  transform: rotate(-45deg) translate(0, -1px);


/*
 * Make this absolute positioned
 * at the top left of the screen
 */
#menu

  position: absolute;
  width: 300px;
  margin: -100px 0 0 0;
  padding: 50px;
  padding-top: 125px;
  right: -100px;
  
  background: #20191A;
  list-style-type: none;
  -webkit-font-smoothing: antialiased;
  /* to stop flickering of text in safari */
  
  transform-origin: 0% 0%;
  transform: translate(100%, 0);
  
  transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);


#menu li

  padding: 10px 0;
  font-size: 30px;


/*
 * And let's fade it in from the left
 */
#menuToggle input:checked ~ ul

  transform: none;
  opacity: 1;


#googleIframe 
    display: block;
    margin-left: auto;
    margin-right: auto;
    width: 300px;
    height: 200px;


@media screen and (max-width: 843px) 
    #menu 
        transform: none;
        opacity: 0;

        transition: opacity 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
    
    
    .banner1 
        float: left;
        width: 100%;
        display: block;
        margin: 0 30px 20px 0;
        padding-top: 45px;
        padding-bottom: 600px;
  
        &:nth-child(2n) 
            clear: left;
        
  
        &:nth-child(2n+1)
            margin-right: 0;
        
        
        
    
    
    .content1 
        float: none;
        width: 60%;
        display: block;
        margin: 0 auto 0 auto;
        padding-top: 45px;
  
        &:nth-child(2n) 
            clear: left;
        
  
        &:nth-child(2n+1)
            margin-right: 0;
        
    
    
    h1
        font-size: .8em;
    

    h2
        font-size: .5em;
    
    #googleIframe 
        display: block;
        margin-left: auto;
        margin-right: auto;
        width: 280px;
        height: 200px;
    


@media screen and (orientation: landscape) and (min-height: 1024px) and (min-width: 866px)
    .banner1 
        float: none;
        width: 869px;
        display: block;
        margin: 0 auto 0 auto;
        padding-top: 10px;
    
    .content1 
        float: none;
        width: 600px;
        display: block;
        margin: 0 auto 0 auto;
        padding-top: 10px;
    
    
    h1
        font-size: 1.2em;
    

    h2
        font-size: 1em;
    
    
    #googleIframe 
        display: block;
        margin-left: auto;
        margin-right: auto;
        width: 600px;
        height: 400px;
    


@media screen and (orientation: landscape) and (max-height: 1023px) and (min-width: 866px)
    .banner1 
        float: none;
        width: 550px;
        display: block;
        margin: 0 auto 0 auto;
        padding-top: 10px;
    
    .content1 
        float: none;
        width: 250px;
        height: auto;
        display: block;
        margin: 0 auto 0 auto;
        padding-top: 10px;
    
    
    h1
        font-size: 2em;
    

    h2
        font-size: 3em;
    
    
    #googleIframe 
        display: block;
        margin-left: auto;
        margin-right: auto;
        width: 250px;
        height: 200px;
    


h1, h2 
    font-family: 'alice_in_wonderlandregular', Arial, sans-serif;
    font-weight:normal;
    font-style:normal;
    text-align: center;

h1
    font-size: 1em;


h2
    font-size: .8em;


这是我的html:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Chris and Lisa's Wedding</title>
        <link href="ChrisAndLisaWedding.css" rel="stylesheet" type="text/css" media="screen">
    </head>
    
    <header id="header">
        <nav role="navigation">
                  <div id="menuToggle">
                    <!--
                    A fake / hidden checkbox is used as click reciever,
                    so you can use the :checked selector on it.
                    -->
                    <input type="checkbox" />
    
                    <!--
                    Some spans to act as a hamburger.
    
                    They are acting like a real hamburger,
                    not that McDonalds stuff.
                    -->
                      <span></span>
                      <span></span>
                      <span></span>
                    <!--
                    Too bad the menu has to be inside of the button
                    but hey, it's pure CSS magic.
                    -->
                    <ul id="menu">
                        <a href="#parallax1"><li>Home</li></a>   
                        <a href="#"><li>About</li></a>
                        <a href="#"><li>Info</li></a>
                        <a href="#"><li>Contact</li></a>
                    </ul>
                  </div>
                </nav>  
    </header>
    
    <body>      
        <div class="parallax">
          <div class="parallax__layer parallax__layer--back bg1 object-fit_contain" id="parallax2">
                
            </div>
            <div class="parallax__layer parallax__layer--base" id="parallax1">
              
                <!--
                Content goes here
                -->
                
              <div class="banner1 y-scroll-snap-start front">
                    <img class="object-fit_contain" src="Images/top-page.png" />
                </div>
                
                <div class="content1 y-scroll-snap-start middle">
                    
                    <h1>Wedding Location<br><br></h1>
                    
                    
                    <img class="object-fit_contain" src="Images/Scovill-Pavilionweb.jpg" />
                    
                  <h2> &nbsp;<br>
                      SCOVILL ZOO GAZEBO<br>
                      71 S. COUNTRY CLUB RD.<br>
                      DECATUR, IL 62521<br>
                      2:30pm<br>
  <br>
                      Standing room only </h2>
                  <iframe id="googleIframe" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3064.1540705731177!2d-88.91550038409686!3d39.825963199278696!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x8874af9ec8b29ee1%3A0xd07a3a5a6ba86588!2s71%20S%20Country%20Club%20Rd%2C%20Decatur%2C%20IL%2062521!5e0!3m2!1sen!2sus!4v1618455859789!5m2!1sen!2sus" style="border:0;" allowfullscreen="true" loading="lazy"></iframe>
                </div>
            </div>
        </div>
    </body>
    <script type="text/javascript">
        
        var offsetHeightParallax = document.getElementById('parallax1').scrollHeight;
        
        document.getElementById("parallax2").style.height = offsetHeightParallax+"px";
        
        //document.querySelector(".bottomPadding").style.paddingBottom = (offsetHeightParallax/4) + "px";
        
        function sizeChanged()
            var offsetHeightParallax = document.getElementById('parallax1').scrollHeight;
            document.getElementById("parallax2").style.height = offsetHeightParallax+"px";
            //document.querySelector(".bottomPadding").style.paddingBottom = (offsetHeightParallax/4) + "px";
            console.log("Height of page: "+offsetHeightParallax+"px");
        
        
        function orientationChanged()
            var offsetHeightParallax = document.getElementById('parallax1').scrollHeight;
            document.getElementById("parallax2").style.height = offsetHeightParallax+"px";
            //document.querySelector(".bottomPadding").style.paddingBottom = (offsetHeightParallax/4) + "px";
        
        
        window.addEventListener('resize', sizeChanged);
        window.addEventListener('orientationchange', orientationChanged);
        
        console.log("Height of page: "+offsetHeightParallax+"px");
        
        
        (function () 
        $('menu').css('display', 'block');
        // or $('#id_of_your_sidebar').show();
        );
        
        const checkpoint = 700;

        document.querySelector('.parallax').addEventListener('scroll', changeOpacity);
        
        function changeOpacity()
            
            const currentScroll = document.querySelector('.parallax').scrollTop;
            
            if (currentScroll <= checkpoint) 
                opacity = 1 - currentScroll / checkpoint;
                opacity2 = currentScroll / checkpoint;
             
            else 
                opacity = 0;
                opacity2 = 1;
            
            
            document.querySelector(".front").style.opacity = opacity;
            document.querySelector(".middle").style.opacity = opacity2;
            
        
        
    </script>
</html>

感谢我能得到的任何帮助。

谢谢

【问题讨论】:

【参考方案1】:

我认为您的问题是,在 ipad 的不同屏幕尺寸上,您会看到背景图片无法覆盖的区域。

如果您将 .bg1 的 CSS 代码从 background-size: contain; 更改为 background-size: cover;,它可能会修复页面底部的空白。

【讨论】:

背景尺寸:封面;具有相同的效果。此外,我创建了背景,以便在 y 轴上重复时看起来无缝。我认为这可能与视差效应有关。 我将问题缩小到它是视差效果和我用来尝试修复视差效果背景问题的 JavaScript 的组合。您会注意到在此示例中底部有空格:codepen.io/tribex/pen/mWNWdz 你能解决这个问题吗?如果是这样,您应该将其发布为其他人的答案。 还没有。我想我可能使用 JavaScript 有一个不太优雅的修复,但我想避免,因为它可能会在以后引起问题。我回家后会尝试我不太优雅的解决方案。 我编写了 JavaScript,但我在 Ipad 上看到的行为与我想象的不同。我认为它将页面视为有多个滚动条,而我看不到它,因为它位于移动设备上。所以我要给我的所有 涂上不同的颜色,这样我就可以缩小可能导致问题的范围。如果我弄清楚了,我会发布答案。 【参考方案2】:

我从来没有找到答案,为什么它会滚动到内容之外,因为它只发生在 ios 中。

我确实发现document.element.clientHeightwindow.innerHeight 在您更改移动 iOS 设备的方向后在初始加载后返回不一致的值。所以这也会破坏内容。唯一一致的是screen.heightscreen.width,它们为您提供了整个屏幕的大小,并且不会随着方向的变化而改变。您可以通过访问 iOS 设备上的任何“我的视口”网站来尝试此操作。

我写了几个可以解决的函数。我会警告你它们很草率,我仍然需要清理它们,但它们可以工作

首先我重做了sizeChanged() 函数:

//returns new height of page
        function sizeChanged()
            //if viewport size <= last <div> size
            if(window.innerHeight <= document.querySelector('#thankYouPage').scrollHeight)
                //Content Height
                var offsetHeightParallax = document.querySelector('#parallax1').scrollHeight;
            
            
            else           
                //if content >= viewport
                if(document.querySelector('#parallax1').scrollHeight >= window.innerHeight)
                    
                    //Height difference = viewport - last <div> size
                    var heightDiffContent = window.innerHeight - document.querySelector('#thankYouPage').scrollHeight;
                    
                    //Height = height difference + content
                    var offsetHeightParallax = heightDiffContent + document.querySelector('#parallax1').scrollHeight;
                
                //else height = viewport
                else
                    var offsetHeightParallax = window.innerHeight;
                
            
            
            //return new height of page
            return offsetHeightParallax;
        

我无耻地从另一个用于检测 iOS 设备的堆栈溢出帖子中窃取了这段代码

//##############################################
//Detect iOS returns true or false
//##############################################
function iOS() 
            return [
                'iPad Simulator',
                'iPhone Simulator',
                'iPod Simulator',
                'iPad',
                'iPhone',
                'iPod'
            ].includes(navigator.platform)
                // iPad on iOS 13 detection
                || (navigator.userAgent.includes("Mac") && "ontouchend" in document)
        

然后我写了一个函数用于事件监听器

function sizeChangedListener()
            
            //bug with IOS prevents getting correct viewport work around is refresh page
            if(iOS())
                window.location.reload(false);
            
            
            var endOfPage = sizeChanged();

            document.getElementById("parallax2").style.height = endOfPage+"px";
        
window.addEventListener('resize', sizeChangedListener);

最后一件事,我写了一个防止越过内容的函数。

function stopScrolling()
                    
            var currentScrollEnd = (document.querySelector('.parallax').scrollTop + window.innerHeight);        
            var endOfPage = sizeChanged();
            
            //if bottom of viewport reaches end of page don't let it scroll beyond the end
            if(currentScrollEnd >= endOfPage)
                //You need top of viewport in order to reset
                var currentViewportTopPos = endOfPage - window.innerHeight;
                //reset scroll position as to prevent scrolling past content
                document.querySelector('.parallax').scrollTo(0,currentViewportTopPos);
            
        
document.querySelector('.parallax').addEventListener('scroll', stopScrolling);

这是我对我的问题的不太优雅的解决方案,但它再次有效。

【讨论】:

以上是关于停止在移动设备上滚动过去最后一个 Div的主要内容,如果未能解决你的问题,请参考以下文章

滚动不适用于移动设备

基于 JavaScript 滚动的动画在移动设备上不稳定

JQuery 移动 IOS 设备如何在 web 上删除默认滚动

当用户在移动设备上长按时如何在 div 或输入字段中选择完整的文本

在多个设备上按需加载,例如移动设备和 ipad pro 和 ipad

css 将div中的所有表包装在一起以允许在移动设备上进行水平滚动 - CSS AND JS