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

Edge与Chrome浏览器中图片轮播平滑滚动失效问题求助

问题解决:Chrome/Edge中scroll-snap拖拽轮播失效的修复

问题根源

你的轮播在Firefox正常但Chrome/Edge失效,核心是webkit内核的兼容性差异:

  • scroll()方法在webkit中行为与Firefox不一致,原生滚动逻辑干扰自定义拖拽
  • 未阻止鼠标事件默认行为,浏览器原生滚动/选择与自定义拖拽冲突
  • transform: translateX(50%)会打乱webkit的scroll-snap计算逻辑
  • 恢复scroll-snap样式的时机未适配webkit的渲染机制

修复步骤

1. 替换scroll方法为直接修改scrollLeft

将拖拽时的container.scroll((currentscroll - moved), 0)改为container.scrollLeft = currentscroll - moved,规避webkit内核的方法行为差异。

2. 阻止鼠标事件默认行为

在down和move函数中添加e.preventDefault(),阻止浏览器原生滚动、文本选择等行为,避免干扰自定义拖拽逻辑。

3. 移除transform,改用padding实现居中

将.carousel-item的transform: translateX(50%)替换为父容器的padding-left: 50%和padding-right: 50%,同时调整最后一个item的margin,确保scroll-snap在webkit中正常计算。

4. 优化样式恢复时机

在up函数中使用requestAnimationFrame延迟恢复scroll-snap样式,确保webkit内核正确应用样式,避免滚动跳变。

修改后的完整代码

JavaScript

// ----------------------- //
// ------ FONCTIONS ------ //
// ----------------------- //

// DISABLE SELECTION FOR ELEMENTS
function clicAndDrag() {
    const childs = Array.from(document.querySelector('.carousel').children)
    childs.forEach(undrag)
    function undrag(e) {
        e.setAttribute("draggable", "false")
        e.style.cssText="-moz-user-select: none; -webkit-user-select: none; -ms-user-select:none; user-select:none;-o-user-select:none;" 
        e.unselectable="on"
        e.style.onselectstart = "return false;"
        e.style.onmousedown = "return false;"
        const subchilds = Array.from(e.children)
        subchilds.forEach(undrag)
    }

    // GRABBING EFFECT
    const container = document.querySelector('.carousel')
    let mousedown = false;
    document.body.addEventListener('mousedown', () => {mousedown = true});
    document.body.addEventListener('mouseup', () => {mousedown = false});
    let firstpos;
    let currentscroll;
    // Remove smooth scrolling and scrol-snap for free scrolling and get the scroll/cursor positions
    container.addEventListener('mousedown', down)
    function down(e) {
        e.preventDefault(); // 阻止默认行为
        currentscroll = container.scrollLeft
        firstpos = e.clientX
        container.style.cssText="scroll-behavior: initial; scroll-snap-type: none;"
        childs.forEach(e => {
            e.style.cssText="scroll-snap-align: none;"
        })
    }
    container.addEventListener('mousemove', move)
    function move(e) {      //  Grab Effect
        if (mousedown === true) {
            e.preventDefault(); // 阻止默认行为
            const moved = e.clientX - firstpos
            container.scrollLeft = currentscroll - moved // 改用scrollLeft直接赋值
        }
    }
    // Add smooth scrolling with scroll-snap on releasing mouse
    container.addEventListener('mouseup', up)
    function up() {
        // 延迟恢复样式,适配webkit渲染
        requestAnimationFrame(() => {
            container.style.cssText="scroll-snap-type: x mandatory; scroll-behavior: smooth;"
            childs.forEach(e => {
                e.style.cssText="scroll-snap-align: center;"
            })
        })
    }
}

// ----------------------- //
// ------ LANCEMENT ------ //
// ----------------------- //

// Gestion du javascript si activé
document.addEventListener("DOMContentLoaded", function() {
    
    var htmlClass = document.getElementsByTagName('html')[0];
    htmlClass.classList.replace("no-js", "has-js");
})

// Lancement des fonctions lorsque la page est chargée
window.addEventListener('load', function () { 
    clicAndDrag();
});

CSS

/* -------------------------------- */
/* ------------ GLOBAL ------------ */
/* -------------------------------- */

* {
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body, html {
    margin: 0;
    padding: 0;
    height: 100%;
    width: 100%;
}

#global {
    display: flex;
    flex-direction: column;
}

/* -------------------------------- */
/* ------ NAVIGATION EN HAUT ------ */
/* -------------------------------- */

nav {
    display: flex;
    justify-content: space-between;;
    width: 100%;
    height: 60px;
    padding: 10px 40px;
    font-family: 'Karla', sans-serif;
    font-weight: 400;
    color: #111;
}

nav a {
    text-decoration: none;
    color: #111;
}

.logo {
    display: flex;
    align-items: center;
}

.logo a {
    text-transform: uppercase;
    font-size: 1.3125em; /* Equivalent a 21px standard*/
    letter-spacing: 0.2em;
}

.menu {
    display: flex;
    list-style: none;
    align-items: center;
    justify-content: center;
    font-size: 0.75em; /* Equivalent a 12px standard*/
    margin: 0;
    padding: 0;
}

.is-active {
    text-decoration: underline !important;
}

.menu li {
    padding-right: 30px;
}

.menu li:last-child {
    padding-right: 0;
}

.social {
    display: block;
}

.serie {
    font-weight: 700;
}

/* -------------------------------- */
/* ----------- CAROUSEL ----------- */
/* -------------------------------- */

.carousel {
    display: flex;
    height: calc(100svh - 80px);
    width: 100%;
    overflow-x: scroll;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    padding-left: 50%; /* 替换transform实现居中 */
    padding-right: 50%;
}

/* Masquage de la scrollbar si javascript activé */
.has-js .carousel {
    -ms-overflow-style: none;  /* IE and Edge */
    scrollbar-width: none;  /* Firefox */
}

/* Idem mais pour navigateurs webkit */
.has-js .carousel::-webkit-scrollbar {
    display: none;
}

.carousel-item {
    display: flex;
    height: calc(100% - 40px);
    flex-direction: column;
    flex: 0 0 auto;
    margin-right: 30px; /* Espacement entre chaque image */
    scroll-snap-align: center;
    /* 移除transform: translateX(50%) */
}

.carousel-item img {
    height: 100%; /* Redimensionnement par rapport à la hauteur du carrousel */
    max-height: 1400px;
    width: auto; /* Pour conserver les proportions de l'image */
}

.carousel-item:last-child {
    margin-right: 0; /* 调整最后一个item的margin */
}

.caption {
    display: block;
    font-family: 'Karla', sans-serif;
    font-weight: 400;
    color: #111;
    font-size: 0.75em; /* Equivalent a 12px standard*/
    padding: 4px 0 0 0;
}

footer {
    display: flex;
    height: 20px;
    align-items: center;
    justify-content: right;
    font-family: 'Karla', sans-serif;
    font-weight: 400;
    text-transform: uppercase;
    color: #aaaaaa;
    font-size: 10px;
    margin-right: 10px;
}

HTML

<!DOCTYPE html>
<html lang="fr" class="no-js">
<head>
    <title>Alan Renault - Photographie</title>

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/all.css">

    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap" rel="stylesheet">   
</head>
<body>
    <div id="global">

        <!-- NAVIGATION EN HAUT DE LA PAGE -->
        <nav>
            <!-- Logo -->
            <div class="logo">
                <a href="#">Alan Renault</a>
            </div>

            <!-- Navigation -->
            <ul class="menu">
                <li><span class="serie">Séries :</span></li>
                <li><a class="is-active" href="index.html">2023</a></li>
                <li><a href="2022.html">2022</a></li>
                <li><a href="about.html">&Agrave; propos</a></li>
                <li><a href="contact.html">Contact</a></li>
                <a class="social" href="https://www.instagram.com/alanrenault/" target="_blank"><i class="fa-brands fa-instagram"></i></a>
            </ul>
        </nav>

        <!-- CARROUSEL DE PHOTOS -->
        <div class="carousel" id="myCarousel">
            <div class="carousel-item"><img src="https://alanrenault.com/gallery/photographies/ALR_7064.jpg" alt="Image 1"><span class="caption">Légende</span></div>
            <div class="carousel-item"><img src="https://alanrenault.com/gallery/photographies/ALR_7048.jpg" alt="Image 2"><span class="caption">Légende</span></div>
            <div class="carousel-item"><img src="https://alanrenault.com/gallery/photographies/ALR_7977.jpg" alt="Image 3"><span class="caption">Légende</span></div>
            <div class="carousel-item"><img src="https://alanrenault.com/gallery/photographies/ALR_7940.jpg" alt="Image 3"><span class="caption">Légende</span></div>
            <div class="carousel-item"><img src="https://alanrenault.com/gallery/photographies/ALR_6932.jpg" alt="Image 3"><span class="caption">Légende</span></div>
        </div>

        <footer>
            Copyright &copy; 2023 - Alan Renault
        </footer>

    </div>

    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
    <script src="js/script.js"></script>
</body>
</html>

内容的提问来源于stack exchange,提问作者Alan Renault

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:07:04