移动端交互式卡片导航Bug求助(HTML/CSS/JavaScript)
问题修复:移动端卡片导航正向滚动显示不全
问题原因
正向导航时,卡片从smallCard(100px宽)切换为bigCard(330px宽),容器布局会发生变化。原代码使用相对累加滚动的方式,加上CSS过渡导致的布局延迟,计算出的滚动位置不准确,导致目标卡片无法完全显示。反向导航时卡片是从宽变窄,布局变化对滚动计算的影响较小,所以表现正常。
修复步骤
1. 修正滚动计算逻辑
替换原switchCard函数中的滚动代码,改为直接基于目标卡片的父容器cardContainer计算绝对滚动位置,避免相对累加的误差:
// 替换原滚动代码 requestAnimationFrame(() => { const targetContainer = targetCard.closest('.cardContainer'); const containerScrollLeft = targetContainer.offsetLeft - container.offsetLeft; container.scrollTo({ left: containerScrollLeft, behavior: 'smooth' }); });
2. 优化移动端容器样式(可选)
确保移动端container的内边距和cardContainer的外边距不会干扰滚动对齐:
@media (max-width: 900px) { .container { padding: 0; /* 移除左右padding,避免滚动偏移 */ } .cardContainer { scroll-snap-align: center; /* 改为居中对齐,显示更完整 */ margin: 0 10px; /* 统一左右margin */ } }
完整修复后的代码
JavaScript
document.addEventListener('DOMContentLoaded', () => { const container = document.querySelector('.container'); function switchCard(targetCard) { let currentCard = document.querySelector('.bigCard'); if (currentCard) { currentCard.classList.remove('bigCard'); currentCard.classList.add('smallCard'); let currentButton = currentCard.querySelector('.button'); if (currentButton) { currentButton.classList.add('hidden'); } let currentSecondText = currentCard.querySelector('.secondHeadText'); if (currentSecondText) { currentSecondText.classList.add('hidden'); } let currentPrevButton = currentCard.querySelector('.button.prev'); if (currentPrevButton) { currentPrevButton.classList.add('hidden'); } } targetCard.classList.remove('smallCard'); targetCard.classList.add('bigCard'); let targetButton = targetCard.querySelector('.button'); if (targetButton) { targetButton.classList.remove('hidden'); } let targetSecondText = targetCard.querySelector('.secondHeadText'); if (targetSecondText) { targetSecondText.classList.remove('hidden'); } let targetPrevButton = targetCard.querySelector('.button.prev'); if (targetPrevButton) { targetPrevButton.classList.remove('hidden'); } // 修复后的滚动逻辑 requestAnimationFrame(() => { const targetContainer = targetCard.closest('.cardContainer'); const containerScrollLeft = targetContainer.offsetLeft - container.offsetLeft; container.scrollTo({ left: containerScrollLeft, behavior: 'smooth' }); }); } document.querySelectorAll('.smallCard, .bigCard').forEach(card => { card.addEventListener('click', function(event) { if (event.target.classList.contains('button')) return; switchCard(this); }); }); document.querySelectorAll('.button').forEach(button => { button.addEventListener('click', function(event) { event.preventDefault(); let targetCardSelector = this.getAttribute('data-target'); let targetPrevCardSelector = this.getAttribute('data-target-prev'); let targetCard = document.querySelector(targetCardSelector); let targetPrevCard = document.querySelector(targetPrevCardSelector); if (this.classList.contains('prev')) { if (targetPrevCard) { switchCard(targetPrevCard); } } else { if (targetCard) { switchCard(targetCard); } } }); }); });
CSS
@media (max-width: 900px) { .container { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; width: 100vw; padding: 0; } .cardContainer { scroll-snap-align: center; flex: none; margin: 0 10px; } } .container::-webkit-scrollbar { display: none; } .container { -ms-overflow-style: none; display: flex; flex-wrap: nowrap; overflow-x: auto; } .cardContainer { margin-left: 10px; margin-right: 10px; position: relative; flex: 0 0 auto; } a.button { background: lightgrey; padding: 15px; color: black; font-size: 20px; border-radius: 50%; display: inline-block; text-align: center; width: 45px; height: 45px; line-height: 15px; position: absolute; bottom: 20px; right: 20px; } a.button.prevRight { bottom: 20px !important; right: 20px !important; } a.button.prev { right: 80px; } .button.hidden { display: none; } .smallCard, .bigCard { border-radius: 10px; background-color: black; position: relative; display: flex; flex-direction: column; padding: 10px; overflow: hidden; transition: all 0.5s ease; } .smallCard { height: 330px; width: 100px; } .smallCard:hover{ cursor: pointer; } .smallCard h1 { padding-top: 15px; font-weight: 200; font-size: 25px; color: white; text-align: center; margin: 0; width: 100%; } .smallCard p { color: white; font-size: 18px; transform: rotate(90deg); white-space: nowrap; line-height: 140px; } .smallCard .secondHeadText { display: none; } .bigCard { height: 330px; width: 330px; } .bigCard p.headText { margin-top: 10px; font-size: 20px; } .bigCard p.secondHeadText { margin-top: 30px; } .bigCard h1 { padding-top: 30px; font-weight: 400; font-size: 40px; color: white; text-align: left; padding-left: 20px; margin: 0; } .bigCard p { color: white; font-size: 15px; text-align: left; padding-left: 20px; margin: 0; } .bigCard:hover{ cursor: pointer; }
HTML
<section class="container"> <div class="cardContainer"> <div class="bigCard" id="card1"> <h1>01.</h1> <p class="headText">Kies het Type Dienst</p> <p class="secondHeadText">Hier moet een informatie tekst komen die verdere informatie geeft over deze specifieke stap. (van max 4 regels). <a class="button" href="#" data-target="#card2">></a> </div> </div> <div class="cardContainer"> <div class="smallCard" id="card2"> <h1>02.</h1> <p class="headText">Vul Gebouwgegevens in</p> <p class="secondHeadText">Hier moet een informatie tekst komen die verdere informatie geeft over deze specifieke stap. (van max 4 regels). <a class="button hidden" href="#" data-target="#card3">></a> <a class="button prev hidden" href="#" data-target-prev="#card1"><<</a> </div> </div> <div class="cardContainer"> <div class="smallCard" id="card3"> <h1>03.</h1> <p class="headText">Voer contactgegevens in</p> <p class="secondHeadText">Hier moet een informatie tekst komen die verdere informatie geeft over deze specifieke stap. (van max 4 regels). <a class="button hidden" href="#" data-target="#card4">></a> <a class="button prev hidden" href="#" data-target-prev="#card2"><<</a> </div> </div> <div class="cardContainer"> <div class="smallCard" id="card4"> <h1>04.</h1> <p class="headText">Verzend de aanvraag</p> <p class="secondHeadText">Hier moet een informatie tekst komen die verdere informatie geeft over deze specifieke stap. (van max 4 regels). <a class="button hidden" href="#" data-target="#card5">></a> <a class="button prev hidden" href="#" data-target-prev="#card3"><<</a> </div> </div> <div class="cardContainer"> <div class="smallCard" id="card5"> <h1>05.</h1> <p class="headText">Offerte terug binnen 24u</p> <p class="secondHeadText">Hier moet een informatie tekst komen die verdere informatie geeft over deze specifieke stap. (van max 4 regels). <a class="button prev prevRight hidden" href="#" data-target-prev="#card4"><<</a> </div> </div> </section>
内容的提问来源于stack exchange,提问作者Aaron de Klerk
相关产品推荐
相关产品推荐

