lexible Overflow

Flex display mode allows us to create a lot of interesting interactions. In this article I’ll show how to use it to implement a responsive block which could substitute one content with another, all based on which one would fit inside the container.

Gif animation showing this article’s effect in action

A lot of people love responsive sites, and we used to make them with the help of Media Queries. Today, in the era of components, we can’t rely just on the width of our viewport anymore. Our components need to be independent and work in any conditions.

One of the solutions everyone is waiting for is Container Queries (formerly known as Element Queries). But their future is not certain, and while there are polyfills that allow us to use some of their possible features, the need to polyfill everything can be daunting.

But should we rely on JS or look at our news feeds in anticipation of Container Queries all the time? What if CSS is already powerful enough to solve some of the potential Container Queries use cases right now? What if CSS could even solve some of the responsive cases that even Container Queries probably couldn’t solveGo to a sidenote?

Today I’ll present you with one of those cases.

ong Line of Text Becomes Shorter

Whenever we have a very long string that won’t fit our available space, the most obvious solution is text-overflow: ellipsis. But very often we don’t want to just truncate our long text strings: we could want to substitute it with some other text instead, remove some parts, or replace it with just an icon. That’s what you could see happening in the gif at the start of this article, and here is a much simpler live example (try to resize the wrapper or toggle the toggler to see how it would behave):

Some long text that could become shorter.

The code beyond this example is just some HTML & CSS which usesGo to a sidenote flexbox, and is made to be accessible to screen-readers which would read only the longest part, ignoring the shorter one. Ah, and also whenever you see the shorter line, the longer part would be also accessible as an HTML title.

he Implementation

I’ll go straight to the code and would explain some parts of it later. Here is the CSS I’ve written for the above example:

.overflower {
  display: inline-block;
  overflow: hidden;

  box-sizing: border-box;
  max-width: 100%;
  height: 1.5em;
  line-height: 1.5em;

  white-space: nowrap;
  text-overflow: ellipsis;
}

.overflower-long {
  display: inline;
}

.overflower-short {
  display: none;
}

@supports (flex-wrap: wrap) {
  .overflower {
    display: inline-flex;
    flex-wrap: wrap;
  }

  .overflower-short {
    display: block;
    overflow: hidden;

    flex-grow: 1;
    width: 0;

    text-overflow: ellipsis;
  }

  .overflower-long {
    flex-basis: 100%;
  }
}

Here is how the markup looks for it:

<span class="overflower">
  <span
    class="overflower-short"
    aria-hidden="true"
    title="Some long text that could become shorter"
  >
    Short text here is.
  </span>
  <span class="overflower-long">
    Some long text that could become shorter.
  </span>
</span>

The best part here is that you can nest this construction, thus gaining more than two possible length variations:

Very long text that would become shorter if you'd resize it.

And two more examples: header and a menu, as the more common use cases for something like this:

Really Long Header Becomes so Much Shorter.

lex

So, how and why does this work? Let’s look at CSS:

  1. The first thing you can notice is that most of the styles are beyondGo to a sidenote the @supports: that is because everything works only when we can have flex-wrap, so we would need to have some fallback in case there won’t be any (UC Browser for Android, hello).

  2. The next thing is that we need to make the height of our block fixed (and equal to line-heightGo to a sidenote for simplicity), so we could trim everything that would be wrapped later (rather a common trick I’d say).

  3. Now, the most interesting part: we need to make the shorter part to disappear when there is enough space for our long part, but then to appear when there won’t be. We do this by making the short part to take all the remaining space of the flex flow and then making the long part to take all 100%.

    When there is enough space for the long part it would always take this space. But when its parent would become shorter than the contents of the long part, the magic part would happen: it would jump to the new line as there was another item before it, and that shorter item, that had basically 0 width before, would grow to take all the suddenly vacant space.

Side note: We miss IE11 here, and maybe with some hacks, we could make it work as well, but I don’t think it would worth the effort. You can try though if you want. Jump to this sidenote’s context.

Side note: That would be an ideal case for the lh unit, can we have it already, please? Jump to this sidenote’s context.

In the end, the CSS for this effect is rather short. We just utilize multiple aspects of flexbox together: wrapping, growing and shrinking.

ccessibility

While there are some minor caveats that are hard to overcome (when the shorter variant is shown, you could select & copy it alongside the longer variantGo to a sidenote), most of the a11y stuff is fixable in HTML:

lay With Flex, CSS & Everything

This was just one of the possible effects you can achieve using powerful modern CSS. And as flexbox is already really wide supported, and fallbacks for it are easy, nothing should stop you from using it. I’ll continue my experiments with flexbox, and later with grids, so stay tuned for more responsive, queryless solutions from me. Ah, and there is also some space for good old floats, they’re still cool and can sometimes achieve stuff that is really hard to do otherwise.

Things were interesting in CSS, they are now, and they’ll always be.


Let me know what you think about this article on Mastodon!