DEV Community

Massimo Artizzu
Massimo Artizzu

Posted on

CSS Tip: hide content in short containers

The problem

I was recently asked: "Show the percentage on the progress bar, but only if it's at least 30 pixels tall." In other words, I was tasked to hide some content if the the container wasn't tall enough.

Now, the first thing that I thought was: "Shoot, it would be the perfect task for element queries..." But we're not going to get those anytime soon.

Alternatively, I could use a library like this one or good ol' eq.js, but I wondered if that could be achieved with just CSS.

I found out it could be done.

The solution

I don't want to bore you, so here you go:

Why it works

This is basically the same principle of breaking lines of text: the container isn't wide enough, so the rest of the text goes on a new line.

Text in a container that gets wrapped when the container isn't wide enough

But if we limit the height of the paragraph to just the first line (with something like height: 1lh - what's lh?) and hide the overflown content, we can hide the content if the container isn't wide enough:

Limiting the height of the container effectively hides the rest of the text from view

Flexing the layout

But we're not dealing with just text. Fortunately, we can use the same logic in a flex container:

<div>
  <span>Lorem</span>
  <span>ipsum</span>
</div>
Enter fullscreen mode Exit fullscreen mode
div {
  display: flex;
  flex-wrap: wrap;
}
Enter fullscreen mode Exit fullscreen mode

So, if the second <span> can't fit the first line, it's placed in the row below.

Shift the axis

We've talked about width so far, but the initial problem had a height costraint. That's where flex-direction: column comes into play: this way, if the second <span> can't fit the first column, it's moved on the right.

In the end, the second <span> contains the content we want to hide. We don't care about the first one, so it could also be empty. Even better, we can avoid using a <span> altogether and use a pseudo-element instead:

div {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}
div::before {
  content: '';
  width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Note that we need that first, empty content, or else the content we want to hide would just sit on the top. And we also need to declare width: 100% because without any size on the cross axis it'd like the element isn't even there.

Wrapping up

What happens when the height isn't enough, then? Our content is pushed outside of our container, as it's clear in this screenshot (I painted the pseudo-element yellow to highlight its role - but normally its height is zero):

The content we want to hide is pushed on the right of the constrained container

Now all we have to do is to declare overflow: hidden and we're golden.

Hidden ≠ not rendered

My final warning is that you should be aware that hidden content isn't the same as not rendered or inert. Which means that it's not the same as display: none or <template> elements. In a nutshell, images and other media still get downloaded.

Conclusions

My good friend Giacomo Zinetti has pushed this kind of tricks to another level to mimic media and element queries. For example:

The previous warning still applies, but it's impressive how we can go far without using expensive queries.

Have a nice CSS, folks! 👋

Top comments (0)