I have told a few people about solving container query issues with IntersectionObserver. I am currently working on a longer post that I have tentatively titled "The myth of container queries" but enough people have asked about this one that I'll provide the code (above) and detail how and why it works.


First the usecase, when a box gets small enough that text overflows the container we need to know this an ellipse the text. Doing this measuring on the client end is terrible for performance. In most scenarios, the front end developer doesn't own the content so they can't make a sweeping judgement so they begin doing measurements on any possible box that can need truncation in the given layout via DOM APIs such as offsetWidth or getBoundingClientRects. The downside of this approach, is that in many circustamces it requires the web engine to do layout to answer your question, and if the content is too long this results in the author changing the layout to ellipse the content, which in turn causes the engine to run through the pipeline again. So those layout calls to determine if you should ellipse or not are technically wasted work for the engine while it is achieveing the net end result.

Solving it with IntersectionObserver

As such, what I've done in the above code is setup an IntersectionObserver wrapper and then made the IO root fill that area (this allows you to do padding and other design focused changes). Then I used the root property to focus on that area rather than the default of the viewport. Then I added the observer to the 1px tall .io-clash element.

Then harnessing the power of block layout, if the content is long enough that it pushes the content out of view then we get the default layout which is to ellipse the content since the div is not intersecting with the root. Then if we change the width, height or content within the container and the div is visible within the viewport you'll notice the ellipses are removed due to the removal of the class done within the callback of IntersectionObserver.

Keep it simple

You'll note that the wrapper isn't anything special and the ellipsing of text still works. This is why I like this approach is because at its core it is using block layout. So you can make the root be withing grid or flex items and it will still work. Don't believe me here is one a flex and I've moved the ellipses to the paragraph so it doesn't stay fixed to the bottom of the flex:


We still have the issues that the ellipses are outside of the flow, so from time-to-time they'll partly cut off a glyph. If you want however, you can go a step further in your callback and clean up the text via JS like you would have before. This will incur some of the perf penalty stated above but you'll only run it on the ones that actually need the truncation. I think this approach is a decent MVP for most sites and most users will be fine with the result.

Take Aways

IntersectionObserver allows you to flip the container query model on its head. Rarely do you actually care about the width of the container, what you actually care about is the layout of its children as a result of that width (coorelation != causation). This pattern gives you the capability to respond to what you actually care about which is the content has overflowed, not that the width of the container is 200px. In other scenarios, such as needing to remove labels from icons can be achieved here as well because you'll know that they've wrapped for example and can respond by changing the class and remove the labels accordingly.

Feel free to fork the idea pens above and show how you can harness IntersectionObserver to solve your container query woes (and improve on the initial idea)! Then maybe I won't need to build so many for my post :)

Finally, if you build or work on any of the ellipsing libraries - maybe add in a feature detection that uses this approach.

Have fun and feel free to hit me up on twitter if you have any questions.

5,388 0 14