How can I completely hide elements that overflow their container vertically?
Asked Answered
C

3

29

I have a fixed width and height container that consists of arbitrary height elements that need to be stacked vertically. How can I hide any elements that do not fit? overflow: hidden could still show the part of an element that doesn’t overflow.

.container {
  border: 1px solid #eee;
  height: 200px;
  overflow: hidden;
}

.box {
  background-color: #ccc;
  line-height: 54px;
  margin: 20px;
  text-align: center;
  width: 60px;
}

.incorrect {
  background-color: #fa9;
}
<div class="container">
  <div class="box">show</div>
  <div class="box">show</div>
  <div class="box incorrect">hide</div>
</div>
Changeover answered 21/4, 2017 at 16:12 Comment(1)
Meta discussion on this questionDobla
C
40

Assuming that your child elements have the same width as the container, this can be achieved by leveraging the containing box created from the flex property.

The trick is to use flex-flow: column wrap; in conjunction with overflow: hidden; on the container. The former dictates that the content is stacked vertically and that anything that does not fit should be wrapped into a second column, outside of the content box of the container. The latter dictates that this second column (and any subsequent columns) should be hidden.

.container {
  width: 300px;
  height: 200px;
  display: flex;
  flex-flow: column wrap;
  overflow: hidden;
}

.box {
  width: 300px;
  height: 75px;
}

.box:nth-child(1) {
  background: red;
}
.box:nth-child(2) {
  background: green;
}
.box:nth-child(3) {
  background: blue;
}
<div class='container'>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
Changeover answered 21/4, 2017 at 16:12 Comment(2)
Mind that it will also hide other stuff, in my case a filter: drop-shadow which overflowsNotorious
Also, if any focusable content inside it, you can tab to it and put it in view.Notorious
T
5

An easy way of doing this would be to use CSS columns instead of flex.

Just use a column-width equal to the width of the container. Apply break-inside: avoid on child divs. And there you go.

It resolves all of the asks:

[..]have a fixed width and height container that consists of arbitrary height elements that need to be stacked vertically. How can I hide any elements that do not fit?

You can notice that the red div (the last one) is hidden completely.

Example Snippet:

* { box-sizing: border-box; margin: 0; padding: 0; }
.container {
  border: 1px solid #999;
  height: 200px; width: 300px; 
  overflow: hidden;
  column-width: 300px; 
}
.box {
  padding: 8px; text-align: center; color: #fff;
  width: 250px; height: 80px;
  break-inside: avoid
}
.box:nth-child(1) { background: #3b3; }
.box:nth-child(2) { background: #33b; width: 200px; height: 75px; }
.box:nth-child(3) { background: #b33; }
<div class="container">
  <div class="box">show</div>
  <div class="box">show</div>
  <div class="box">hide</div>
</div>

Note: As of now, Firefox is still a problem area with CSS columns. The break-inside, although documented on MDN, is buggy in Firefox. The bug is still open: https://bugzilla.mozilla.org/show_bug.cgi?id=549114.

Transmontane answered 24/4, 2017 at 6:56 Comment(0)
H
3

The OP`s answer is beautiful, but the first item will still be clipped, instead of hidden, if it does not fit.

If you want the first item to become hidden as well, you can use a spacer with the relevant dimension set to zero.

Here's the idea, applied to a row, just for some variation:

(note the .container can be resized for some live action)

.container {
  /* functional */
  height: 1em;
  display: flex;
  flex-flow: row wrap;
  overflow: hidden;
  /* cosmetic & convenience */
  background-color: plum;
  width: 10em;
  resize: horizontal;
}

.container div {
  /* functional */
  height: 100%;
}

.container div:first-child {
  /* functional */
  width: 0;
}
<div class='container'>
  <div>
    <!-- zero-width spacer -->
  </div>
  <div>first</div>
  <div>second</div>
  <div>third</div>
</div>
Heritage answered 21/12, 2023 at 17:20 Comment(1)
Super! Yesterday I was looking for a css way of doing this, but found a lot of ppl saying its not possible with CSS and that I needed to use JS, and here you are with an elegant solution. Thank youMcmann

© 2022 - 2024 — McMap. All rights reserved.