You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端交互式卡片导航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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 20:34:53