It's best to use getBoundingClientRect() for that nowadays.
Source: https://plainjs.com/javascript/styles/get-the-position-of-an-element-relative-to-the-document-24/
Let me know if that works better for you!
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
Hi everybody, I'm trying to make an element fixed when the user scrolls past it, but I have an issue. For some reason my element (in my case it's a navbar) always returns 0 despite being at like 300px height more or less.
This is my mounted method where I do the calculation, as you see I'm console loging stickyTop, always 0.
I tried with offsetTop and getBoundingClientRect().top and both return 0 always.
mounted() {
console.log(this.$options.name+' component successfully mounted');
let self = this;
let sticky = document.getElementById("sticky");
//sticky.style.border = '10px solid red';
//let stickyTop = sticky.getBoundingClientRect().top;
let stickyTop = sticky.offsetTop;
console.log(stickyTop);
let scrolled = false;
let $window = window;
window.addEventListener('scroll', function(e) {
scrolled = true;
});
let timeout = setInterval(function() {
/* If the page was scrolled, handle the scroll */
if (scrolled) {
scrolled = false;
if (window.pageYOffset > stickyTop) {
self.isScrolled = true;
}
else {
self.isScrolled = false;
}
}
}, 2000);
},
My full component just in case:
<nav id="sticky" class="LAYOUTnav1_maincontainer" :class="{ 'fixed_class' : isScrolled }" @mouseleave="activeNav = null">
<div class="LAYOUTnav1_links_container">
<a class="LAYOUTnav1_link_container hover_slide_center" v-for="(link, index) in visibleLinks" :key="index" @mouseover="selectNav(link, $event);" @click="selectNav(link, $event);" :href="link.url" :class="{ active_nav : meta.activeNav == link.name}">
<span class="LAYOUTnav1_link_text">{{ link.name }}</span>
</a>
<button class="LAYOUTnav1_cart_button" type="button" @click="TOGGLE_CART_TAB()" v-bg-color="'rgb(10,10,10)'">
<i class="LAYOUTnav1_cart_button_icon fas fa-shopping-cart"></i>
<span class="LAYOUTnav1_cart_button_text" v-if="cartItems.length != 0">{{ cartItems.length }}</span>
<span class="LAYOUTnav1_cart_button_text" v-if="cartItems.length == 0">¡El carrito esta vacio!</span>
</button>
</div>
<div class="LAYOUTnav1_responsive_container">
<a class="LAYOUTnav1_responsive_title" href="/">{{ globals.generals.appName }}</a>
<button class="LAYOUTnav1_responsive_button" @click.self="selectNav({ name: 'responsive', sublinks: []}, $event)">
<i class="LAYOUTnav1_responsive_button_icon fas fa-bars" v-show="!showResponsiveNav"></i>
<i class="LAYOUTnav1_responsive_button_icon fas fa-times" v-show="showResponsiveNav"></i>
</button>
</div>
<div class="LAYOUTnav1_dropdowns_container" v-show="activeNav == 'responsive'">
<a class="LAYOUTnav1_dropdown_container" v-for="link in visibleLinks" :key="link.name" @mouseover="selectNav(link, $event);" @click="selectNav(link, $event);" :href="link.url" :class="{ active_nav : meta.activeNav == link.name}">
<span class="LAYOUTnav1_dropdown_text">{{ link.name }}</span>
</a>
</div>
</nav>
</template>
<!--SCRIPTS-->
<script>
import $ from 'jquery';
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';
export default {
name: 'LAYOUTnav6',
computed: {
...mapState('Cart', ['cartItems']),
withLinks: function(){
return this.globals.navLinks.filter(link => link.sublinks.length > 0 && link.subLinks);
},
visibleLinks: function(){
return this.globals.navLinks.filter(link => link.isVisible && !link.hasSublinks || link.isVisible && link.hasSublinks && link.sublinks.length > 0);
}
},
data: function () {
return {
activeNav: null,
showResponsiveNav: false,
isScrolled: false,
}
},
props: {
globals: {required:true},
meta: {required:true}
},
mounted() {
console.log(this.$options.name+' component successfully mounted');
let self = this;
let sticky = document.getElementById("sticky");
//sticky.style.border = '10px solid red';
//let stickyTop = sticky.getBoundingClientRect().top;
let stickyTop = sticky.offsetTop;
console.log(stickyTop);
let scrolled = false;
let $window = window;
window.addEventListener('scroll', function(e) {
scrolled = true;
});
let timeout = setInterval(function() {
/* If the page was scrolled, handle the scroll */
if (scrolled) {
scrolled = false;
if (window.pageYOffset > stickyTop) {
self.isScrolled = true;
}
else {
self.isScrolled = false;
}
}
}, 2000);
},
methods: {
...mapMutations('Cart', ['TOGGLE_CART_TAB']),
selectNav: function(link, event){
if(link.sublinks.length > 0){
//event.preventDefault();
this.activeNav = link.name;
}
else{
this.activeNav = link.name;
this.showResponsiveNav = !this.showResponsiveNav
}
},
}
};
</script>
Please or to participate in this conversation.