停止在移动设备上滚动过去最后一个 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> <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.clientHeight
和window.innerHeight
在您更改移动 iOS 设备的方向后在初始加载后返回不一致的值。所以这也会破坏内容。唯一一致的是screen.height
和screen.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的主要内容,如果未能解决你的问题,请参考以下文章
JQuery 移动 IOS 设备如何在 web 上删除默认滚动
当用户在移动设备上长按时如何在 div 或输入字段中选择完整的文本