Discussion icon indicating copy to clipboard operation
Discussion copied to clipboard

Get height of element AFTER the page is done loading

Open IntellectProductions opened this issue 10 years ago • 14 comments

So this is my current dilemna:

http://jsfiddle.net/59yp3r4h/

If you look at the Fiddle, the height gets cut off (line 81 in the javascript). If you hit run, it gets it fine. I have to do a setTimeout with a 10 milisecond timeframe to get the height of the element. This looks terrible.. I thought the attached method and ready method waited until $el was available.. It's getting the wrong height because it's not loading fast enough or something.

What's a workaround for this BESIDES the setTimeout? The element is available at that time, but the height isn't available yet. It SAYS 129 pixels when I do a console.log(this.$el), but whenever I do this.$el.clientHeight, it says 76. Even though it says 129 when I look through that first console log. This makes no sense..

I'm having this issue in multiple places that I need to get the dimensions. Vue works great functionality wise, but this issue is starting to drag my work down at my workplace and personal projects. I feel like I shouldn't be using Vue because of this. I have to mess with the dimensions a LOT for my components.

Thanks for any help.

IntellectProductions avatar Sep 13 '15 20:09 IntellectProductions

Figured it out. I ended up creating a mixin that issued window.onload() and called the callback function that was passed into it! So I would create a method in my methods section inside my component where everything that needed to be fired on window load would be in that method. Then on the attached() method, I just called this.onPageLoad( this.callBackFunction ). Only thing that I could see as a workaround for now.

IntellectProductions avatar Sep 13 '15 21:09 IntellectProductions

EDIT: use the solution below.

// In your component or mixin:
created () { // would work in 'ready', 'attached', etc.
  window.addEventListener('load', () => {
    // https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
    console.log(this.$el.clientHeight)
  })
}

elcontraption avatar Jul 25 '16 16:07 elcontraption

ready() {

  this.$nextTick(() => {

    console.log(this.$el.clientHeight);

  });

}

pbelyaev avatar Aug 26 '16 16:08 pbelyaev

In Vue2.0 the above code by @pbelyaev isn't working anymore.

Anymore ideas besides listening to window onload ?

pxwee5 avatar Aug 30 '17 22:08 pxwee5

In Vue 2.x, ready was replaced by mounted.

mounted () {
  this.$nextTick(() => {
    console.log(this.$el.clientHeight)
  })
}

elcontraption avatar Aug 30 '17 23:08 elcontraption

@elcontraption Yes I am aware of that. Sorry should have made it clear in the beginning.

But it still didn't work. I tested on mounted() and updated() (I think updated() gets fired one time after the component is mounted) method, and both returned the wrong clientHeight.

pxwee5 avatar Aug 30 '17 23:08 pxwee5

@pxwee5 try a reduced test case? https://codepen.io/elcontraption/pen/eEbvRp/.

elcontraption avatar Aug 30 '17 23:08 elcontraption

@elcontraption That's weird.

Let me check the code, maybe it's to do with the images not loaded yet during mount.

pxwee5 avatar Aug 31 '17 00:08 pxwee5

@pxwee5

If you use style-loader(That use with blob:http to load css, it seems asynchronous ) instead of vue-style-loader(use

In the dev mode, because we not use extract-text-webpack-plugin, the style is add when the component init, so the style of the component is not ready in the mounted hook...

It is not a problem in the 'production' with extract-text-webpack-plugin, so we can just do something to fix this in dev mode:

Vue.mixin({
  methods: {
    $ready(fn) {
      if (process.env.NODE_ENV === 'production') {
        return this.$nextTick(fn);
      }

      setTimeout(() => {
        this.$nextTick(fn);
      });
    }
  }
});

and use in the mounted hook:

mounted() {
    this.$ready(() => {
      // here the style is ready
   })
}

ccqgithub avatar Oct 26 '17 07:10 ccqgithub

@ccqgithub -- thank you. i was struggling even with $nextTick to find the offsetWidth of a flexbox element upon being mounted. this mixin helped.

jonalexander avatar Nov 21 '17 21:11 jonalexander

@ccqgithub's solution worked for me, too... but I had to configure setTimeout to wait a second (second parameter).

Vue.mixin({
  methods: {
    $ready(fn) {
      if (process.env.NODE_ENV === 'production') {
        return this.$nextTick(fn)
      }

      setTimeout(() => {
        this.$nextTick(fn)
      }, 1000)
    },
  },
})

aminimalanimal avatar Dec 19 '17 22:12 aminimalanimal

I also run into this problem, any updates?

ywmail avatar Feb 24 '18 03:02 ywmail

I am also facing this problem when using $nextTick inside a mixin. My intention was to wait for all child components to be ready in order to bind some elements using an third party library.

When I used this approach directly on a component, I have not found any errors. But it never worked once extracted into a mixin.

phcoliveira avatar Mar 20 '18 14:03 phcoliveira

I had a similiar problem (however, mine was IE specific and clientWidth, but still on the mounted() lifecycle call). So, for some reason, it helped referencing it twice. Since my initial value was 0 I could do something like this: var width = this.$el.clientWidth || this.$el.clientWidth;

I ran across this when I tried to debug it and the bug would disappear if I logged the clientWidth via console.log before I used it.

Maybe this helps someone! Sorry if it doesn't!

awaigand avatar Apr 24 '18 13:04 awaigand