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

Vue 2.7中Bootstrap 5 CSS与JS滚动逻辑冲突问题求助

问题:Vue2.7 + Bootstrap5.3 滚动动画异常(Chrome/Edge 114)

问题现象

  • 在Vue2.7项目中引入Bootstrap5.3后,使用vue-scrollto指令或自定义scrollToElement方法实现带时长和缓动的元素滚动时,出现异常:滚动先按设置时长缓慢启动,之后无缓动直接跳至目标元素。
  • 注释掉main.js中的import 'bootstrap/dist/css/bootstrap.css'后,滚动恢复正常。

排查结果

  • 冲突仅来自Bootstrap CSS,禁用Bootstrap JS、BootstrapVue或自定义CSS均无改善,通过CDN引入Bootstrap也存在该问题。
  • 仅Bootstrap4.6.2版本无此问题;该异常仅出现在Chrome和Edge 114版本,Firefox 114.0.1无异常。

代码示例

vue-scrollto使用示例

<button type="button" class="btn btn-secondary" v-scroll-to="'#scroll-test'">v-scroll-to</button>

或

<button type="button" class="btn btn-secondary" v-scroll-to="{ el: '#scroll-test', duration: 1000, easing: 'ease-in-out', offset: 0 }">v-scroll-to 2</button>

main.js相关代码

let Bootstrap = require('bootstrap')
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'

import 'bootstrap/dist/css/bootstrap.css' // 注释此行后冲突消失
import 'bootstrap/dist/js/bootstrap.js'
import 'bootstrap-vue/dist/bootstrap-vue.css'

import '/public/media/css/layout.css';
import '/public/media/css/mobile.css';

import Vue from 'vue'
import VueMeta from 'vue-meta'
import App from './App.vue'
import router from './router'
import Vuex from 'vuex'
import store from './store'
import VueI18n from 'vue-i18n'

Vue.use(Bootstrap)
Vue.use(BootstrapVue)
Vue.use(IconsPlugin)

const VueScrollTo = require('vue-scrollto')
Vue.use(VueScrollTo, {
    duration: 1000,
    easing: 'ease-in-out',
    offset: -50,
})

自定义滚动mixin代码

export default {
  methods: {
    scrollToElement(element, duration) {
      let start = null;
      const target = element && element? element.getBoundingClientRect().top : 0;
      const firstPos = window.scrollY || document.documentElement.scrollTop;
      let pos = 0;

      (function() {
          
        var browser = ['ms', 'moz', 'webkit', 'o'];
        
        for(let x = 0, length = browser.length; x < length && !window.requestAnimationFrame; x++) {
          window.requestAnimationFrame = window[browser[x]+'RequestAnimationFrame'];
          window.cancelAnimationFrame = window[browser[x]+'CancelAnimationFrame'] 
          || window[browser[x]+'CancelRequestAnimationFrame'];
        }
          
      }());
      
      function showAnimation (timestamp) {

        if(!start) { start = timestamp || new Date().getTime(); }
        
        let elapsed = timestamp - start;
        let progress = elapsed / duration;
        
        const inOutQuad = function(n){
          n *= 2;
          if (n < 1) return 0.5 * n * n;
          return - 0.5 * (--n * (n - 2) - 1);
        };
        
        let easeInPercentage = +(inOutQuad(progress)).toFixed(2);

        pos = (target === 0)? (firstPos - (firstPos * easeInPercentage)) : (firstPos + (target * easeInPercentage));
        
        window.scrollTo(0, pos);
          
        if(target !== 0 && pos >= (firstPos + target) || target === 0 && pos <= 0) {
          cancelAnimationFrame(start);
          if(element) { 
            element.setAttribute("tabindex", -1);
            element.focus();
          }
          pos = 0;
        } else {
          window.requestAnimationFrame(showAnimation);
        }
          
      }
      window.requestAnimationFrame(showAnimation);
      
    },
  },
}

解决方案

方案1:覆盖Bootstrap的原生平滑滚动设置

Bootstrap5.3的CSS默认给html元素设置了scroll-behavior: smooth,这会导致Chrome/Edge 114中浏览器原生平滑滚动与自定义滚动动画冲突。在自定义CSS文件中添加以下代码覆盖该设置:

html, body {
  scroll-behavior: auto !important;
}

方案2:临时禁用原生平滑滚动(针对自定义滚动方法)

如果需要保留Bootstrap的其他样式且方案1无效,可以在自定义滚动方法中临时禁用原生平滑滚动,完成后恢复:
修改scrollToElement方法:

scrollToElement(element, duration) {
  // 临时禁用原生平滑滚动
  const originalHtmlScrollBehavior = document.documentElement.style.scrollBehavior;
  const originalBodyScrollBehavior = document.body.style.scrollBehavior;
  document.documentElement.style.scrollBehavior = 'auto';
  document.body.style.scrollBehavior = 'auto';

  let start = null;
  const target = element && element? element.getBoundingClientRect().top : 0;
  const firstPos = window.scrollY || document.documentElement.scrollTop;
  let pos = 0;

  // ... 原有的浏览器兼容代码 ...

  function showAnimation (timestamp) {
    // ... 原有的动画逻辑 ...
    
    if(target !== 0 && pos >= (firstPos + target) || target === 0 && pos <= 0) {
      cancelAnimationFrame(start);
      if(element) { 
        element.setAttribute("tabindex", -1);
        element.focus();
      }
      pos = 0;
      // 动画结束后恢复原生平滑滚动设置
      document.documentElement.style.scrollBehavior = originalHtmlScrollBehavior;
      document.body.style.scrollBehavior = originalBodyScrollBehavior;
    } else {
      window.requestAnimationFrame(showAnimation);
    }
  }
  window.requestAnimationFrame(showAnimation);
}

方案3:改用浏览器原生平滑滚动

如果可以接受原生平滑滚动的效果,直接移除vue-scrollto和自定义滚动mixin,使用锚点链接,并确保Bootstrap的scroll-behavior: smooth生效即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:27:12