Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Gabotronix's avatar

Javascript: offsetTop always returns 0

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>
0 likes
1 reply

Please or to participate in this conversation.