Reputation: 1017
Consider this flexbox container with a few items. A few random ones tagged with .hide-on-overflow
<div id="container">
<div class="item">Item 1 </div>
<div class="item hide-on-overflow">Item 2 </div>
<div class="item hide-on-overflow">Item 3 </div>
<div class="item ">Item 4 </div>
<div class="item hide-on-overflow">Item 5 </div>
</div>
CSS to set this up as a flexbox row
#container {
display: flex;
}
.item {
flex-shrink: 0;
}
.hide-on-overflow { }
Now I would like the items tagged with .hide-on-overflow
to disappear when #container
begins to overflow. The question is not how to hide them (I would use display: none;
), but how to detect the container overflowing. This is intended as a flexible solution instead of using a media query on the entire window width (thus estimating when the container would overflow)
Upvotes: 1
Views: 381
Reputation: 2058
I do not think this can be done with CSS. But I would do it in JavaScript using the Intersection Observer API. Note that this an example of just one way to do this, there are possibly much better ways.
const container = document.querySelector("#container")
// elements to hide when overflowing
const elements = document.querySelectorAll(".hide-on-overflow")
// lastItem with which we detect if we are overflowing
const lastItem = container.lastElementChild
const observer = new IntersectionObserver(callback, {
root: null, // intersect with viewport
rootMargin: '0px', // no margin when computing intersections
threshold: 1.0, // execute callback when every pixel is visible/hidden
})
observer.observe(lastItem)
let breakpoint = 0 // breakpoint where we started to overflow
// Intersection Observer callback, which is called when no pixels of lastItem
// are visible anymore.
function callback(entries, observer) {
for (const entry of entries) {
if (!entry.isIntersecting) {
// Save current viewport width when we hide the elements.
breakpoint = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
for (const element of elements) {
element.style.display = "none"
}
}
}
}
window.onresize = function() {
// If we resize before the breakpoint is set, do nothing.
if (breakpoint === 0) {
return
}
// Viewport width
vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
if (vw > breakpoint) {
for (const element of elements) {
element.style.display = ""
}
}
}
Below is a simple summary of what this does. To best understand it, make sure to know the basics of Intersection Observer and read the code.
Using Intersection Observer we observe whether lastItem
(last item in #container
) is visible depending on the viewport. If it is not, it means we are overflowing. When this happens, we save the viewport width and hide the hide-on-overflow
elements.
Then using a resize
event listener, we display the hide-on-overflow
elements when the current viewport width is larger than the viewport width of when we started overflowing.
We cannot use Intersection Observer for both ways as the lastItem
is no longer visible when we hide it and the callback
is not called back anymore. That is why we use the breakpoint
variable and the resize
event listener.
Viewport width is retrieved like it is described in javascript - How to get browser viewport dimensions?.
Upvotes: 1