Here’s Atif Afzal on using a <div>
that is permanently on the page where tooltips are added/removed and how they perform vastly better than plopping those same tooltips right into the <body>
. It’s not really discussed, but the reason you put them that high-up in the DOM is so you can absolutely position them exactly where you need to on the page without having to deal with hidden overflow or relative parents and the like.
To my amazement, just having a separate container without even adding the [CSS]
contain
property fixed the performance. The main problem now, was to explain it. First I thought this might be some internal browser heuristic optimizing theRecalculate Style
, but there is no black magic and I discovered the reason.
The trick is to avoid forced recalculations of style:
[…] The tooltip container is not visible in the page, so modifying it doesn’t invalidate the complete page render tree. If the tooltip container would have been visible in the page, then the complete render tree would be invalidated but in this case only an independent subtree was invalidated.
Recalculating Style
for a small subtree of 3 doesn’t take a lot of time and hence is faster.
Looks like popper.js was used here, so you have to be smart about it. We use toast messages on CodePen, and it’s the only third-party component we use at the moment: react-hot-toast. I checked it, and not only do we tuck the messages in a <div>
of our own, but the library itself does that, so I think we’re in the clear.
I usually do append my tooltips to the body, so this is truly helpful to know. Thanks for the insightful article. Atif’s was great as well.
Concerning Hot Toast, what has been your reasoning thus far on keeping that 3rd-party as opposed to developing custom, promise-based tooltips as you need them in-house?
We might replace them at some point, it’s just faster to use third-party stuff and in this case it checked all the boxes of what we needed.