Tippyjs: sticky: true repaints frequently

Created on 19 Jul 2019  路  13Comments  路  Source: atomiks/tippyjs

Bug description

setting sticky: true and trigger: click on an element, it seems to repaint the document rather frequently, so much so that the dom can't be edited from dev console.

(This is happening in chrome, but might be happening in other browsers too.)

Reproduction

  1. visit https://test-tippy-obddnsfyyn.now.sh/

  2. click the button

  3. inspect the tippy element

  4. notice that various dom elements in the dev console are flickering and un-editable:

ScreenRecording2019-07-18at7

馃悰 bug

All 13 comments

That's its purpose and perf limitation, because updates need to occur on every animation frame in case the element moves for any reason and Popper needs to immediately catch up, so there's "wasted" updates when the element doesn't move. I don't think it's possible to know exactly how and when the element changes its position on the document, so use this particular prop with caution

With 3-4 sticky tooltips open CPU is too high ... I've managed to fix this problem by calling
instance.popperInstance.update() when i needed to update tooltip position, it was a little tricky with the tooltip that was inside another tooltip ... that needs to have a lot of events attached to work without sticky: true... or i can just destroy() it when parent tooltip get's updated... still looking for a good solution to that problem.

updates need to occur on every animation frame in case the element moves for any
reason and Popper needs to immediately catch up

It makes sense that we need to poll every animation frame to detect element movement, but I'm wondering if there's a way we can only read the element state, rather than actually writing anything to the dom. If nothing changes (which would be true for most of the frames we're checking) it might help significantly.

Mm yeah I guess, but what about transform: scale() transitions of the reference element, or layout changes: https://codepen.io/atomiks/pen/WVQpde

sticky updating each animation frame fixes those cleanly without needing to check anything.

sticky updating each animation frame fixes those cleanly without needing to check anything.

I get that the static update each frame is very clean. I think the issue though is that updating essentially does 2 things under the hood each frame:

  • re-draws the element
  • triggers a layout re-flow

For most of those frames, nothing will have changed. I'm wondering if we could useElement.getBoundingClientRect() each frame to detect if the element has changed. That would still trigger layout re-flow, but at least we're not thrashing the dom with unnecessary re-draws.

https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

@mreinstein that seems like a good idea, I'll look into it

can we backport this bugfix to v4?

@mreinstein I'll try and do a release for this (and all the other fixes made) today 馃檪

There are a few techniques that can be applied to decrease the CSS size for v4 like I did for v5, so I'm going to try and do that before releasing to hopefully offset some of the size increases that were made

I'll try and do a release for this (and all the other fixes made) today

No rush from my perspective, I'm not able to use the npm distribution of this package anyway because I need to run the build process with my own namespacing so everything gets prefixed.

my build process:

git clone [email protected]:atomiks/tippyjs.git
cd tippyjs
# get the latest v4 code commit
git checkout bc64e239e7635ca3ca6fe42286da344befb89c05
npm install
NAMESPACE=acmeinc npm run build
cp umd/index.all.min.js ~/Sites/acmeinc/scripts/lib/tippy/index.all.min.js

Ahh right yeah I forgot about that. Well, you can use it right now then 馃槤

yep! That said almost everyone else is probably using the default tippy.js npm package and would probably like the improvements you've made in a new release.

that said, if you want to backport the theme customization to v4, that would be pretty amazing. That would reduce the size of the css that gets bundled and eliminate a manual step in the tippy.js customization process:

NAMESPACE=acmeinc THEME=light-border npm run build
Was this page helpful?
0 / 5 - 0 ratings