Is it possible to access the current scaling factor of the% -width element using Javascript without causing a rescheduling?

I am trying to fix some slow-running javascript in a sluggish user interface, and I narrowed down the main reason to calling jQuery .width() , used to view the actual pixel size of the width: 100% element in the responsive layout, in a process that should often occur in response to user actions.

I added measurements based on the time method, and they show that it accounts for about 33% of the delay time, which makes the difference between the UI feel sharp and the UI feel sluggish. By removing this line, the user interface feels fast - but, it puts things in the wrong place ...

It seems that .width() relatively slower in jQuery> 1.8 , mainly for two reasons:

  • It forces reflow when calculating the size of an element . From the article in When does DOM overflow occur? :

    [reflow happens when] you retrieve a dimension that needs to be calculated, for example, a reference to offsetWidth, clientHeight, or any computed CSS value (via getComputedStyle () in DOM-compatible browsers or currentStyle in IE)

    ... in fact, for browsers such as IE and Firefox that delay DOM changes until the last moment in order to avoid conflicting changes (for example, hide and show functions in the same call), people sometimes add unnecessary state getters to force reschedule .

  • It is also necessary to check the state of the border element. From my blog :

    jQuery 1.8 now needs to check the window size property when using .width () so that it can decide whether to subtract the width of the pad and the width. It can be expensive - 100 times more expensive in Chrome!

The purpose of my width() code call is to see if the responsive design has shrunk and how different it is. He should look at the widget's shell element, which has width: 100%; (but it may be in a column or another container, depending on which node / page it is on), and he needs to see what% of this maximum width of the wrapper is actually showing on.

Another code, based on a different coordinate system, gives me the location in pixels for the label, then I need to use the scaling factor (essentially = $wrapper.width() / maxWidth; ) to zoom out the location so that, for example, if the page is being viewed in a narrow window / device, and the shell is 50% of its maximum size, the top and left offsets of the labels are 50% of their default values.

Is there any way to access this data about how much the% -width element has been reduced without causing re-layout, but other things that make slow calls to .width() ?

Things I tried or ruled out:

  • .outerWidth() is just as slow as .width()
  • .get(0).clientWidth (pure Javascript / non- .get(0).clientWidth option) is also almost as slow as .width() (presumably therefore overflow, which is the culprit)
  • I noticed that in most browsers, if I perform any of them, followed by any of the above actions in another dimension (e.g. .get(0).clientWidth , and then .outerHeight() ) calls after the first very fast (~ 20 times faster), Presumably, since the correction has just been completed and the properties of the element were just available, they are somehow cached. But the effect is not performed for repeated function calls, only within one function call.
  • .css("width") is obviously not used because it will just give me 100% in all cases
  • I decided to get the width of the window, but things get complicated depending on the layout of the columns of the page on which this element is placed. For example, if my cover art is in a two-column layout and the window is slightly wider than the breakpoint that collapses the two columns, the window will be wider than the layout size of the wrapper element, but the wrapper element will not be 100% of its maximum width .

[ Update ] I thought I decided to deal with my need to solve the problem and put my labels without access to element scaling: since I already had the maxWidth variable in pixels and pixel offsets, I had enough data to calculate the percentage offset for my labels with leftOffset_px / maxWidth_px and topOffset_px / maxHeight_px , then + '%' and apply this as for each CSS label top and left offset. This is ridiculously faster - now less than 1 millisecond, so my timestamp function cannot measure it!

Unfortunately, I also have another function that checks that fixed-width labels do not overflow the sensitive container, and for this I need to consider either the current pixel width of the container or its scale factor.

+7
javascript jquery css reflow
source share
1 answer

I'm not sure how big the improvement will be, but you can try adding an absolutely positioned element containing children to the root of your widget, with the sole purpose of reading its width. I think that absolutely positioned elements only melt their children:

 .root { position: relative; } .ruler { position: absolute; width: 100%; } 

_

 <div class="root> ... <div class="ruler"></div> </div> 

-

 var updatedWidth = $('.ruler').width() 

(Although I agree with the comments you should try and resolve with CSS)

+1
source share

All Articles