I'm having a conflict issue with Bootstrap 5 (any version) in my Vue 2.7 app when I try to scroll to an element using JS to add duration and easing to the scrolling. It happens either using the vue-scrollto directive by button click or by a custom method in a mixin (I will post the code below).
The scroll starts slowly for the duration that I set (ex. 1000) and after the duration time, it scrolls smoothly to the element without any easing. I found out that if I comment the Bootstrap CSS in my main.js file "//import 'bootstrap/dist/css/bootstrap.css'" the scroll acts normally.
At first I thought it was related to Bootstrap JS, but by trying to isolate the problem, the conflict happens only with Bootstrap's CSS. Neither disabling BootstrapVue, Bootstrap JS or my custom CSS have any effect on this conflict. And calling Boostrap by CDN also have the same issue.
edit1: At the moment I'm using Bootstrap 5.3. With Bootstrap 4.6.2, the problem does not happen, but when I upgraded to v5 I haven't had this conflict at first.
edit2: I've just tested with Firefox 114.0.1 (most recent version) and it does not have any conflict. It happens in Chrome and Edge 114*.
When using vue-scrollto, the code is like this:
<button type="button" class="btn btn-secondary" v-scroll-to="'#scroll-test'">v-scroll-to</button>
or
<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>
my main.js file starts like this:
let Bootstrap = require('bootstrap')
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css' // if I comment this, the conflict goes away
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,
})
and this is a custom mixin that I use to start the scroll by calling this.scrollToElement(element,duration); in some method:
export default {
methods: {
scrollToElement(element, duration) {
let start = null;
const target = element && element? element.getBoundingClientRect().top : 0;
//const firstPos = window.pageYOffset || document.documentElement.scrollTop; // pageYOffset deprecated
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(); } //get id of animation
let elapsed = timestamp - start;
console.log('elapsed', elapsed);
let progress = elapsed / duration; // default animation duration 600ms
//ease in function from https://github.com/component/ease/blob/master/index.js
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);
// if target is 0 (back to top), the position is: current pos + (current pos * percentage of duration)
// if target > 0 (not back to top), the positon is current pos + (target pos * percentage of duration)
pos = (target === 0)? (firstPos - (firstPos * easeInPercentage)) : (firstPos + (target * easeInPercentage));
window.scrollTo(0, pos);
//console.log('scrollTo target:', target);
//console.log(pos, target, firstPos, progress);
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);
},
},
}
Any ideas on how to solve this?