Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I hide flex items when it overflows the flex parent?

Tags:

html

css

flexbox

Supposing that I have a flexbox container where the content may overflow the parent container. What I would like is that if any item gets larger than the container by any amount that it be hidden. If I set overflow: hidden it will only hide the overflowed portion of that item, not the entire item.

Consider the following:

<nav id="top-nav">
    <div id="main-nav-container">
        <div class="menu">
            <ul>
                <li><a href="/">Item 1</a></li>
                <li><a href="/">Item 2</a></li>
                <li><a href="/">Item 3</a></li>
                <li><a href="/">Item 4</a></li>
            </ul>
        </div>
        <div class="menu">
            <ul>
                <li><a href="/">Other 1</a></li>
                <li><a href="/">Other 2</a></li>
            </ul>
        </div>
    </div>
</nav>

CSS:

#top-nav, #top-nav div.menu ul li {
  background-color: #444;
}

#main-nav-container {
  margin: 0 auto;
  max-width: 1200px;
  padding: 0 40px;
  display: -webkit-inline-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-box-pack: justify;
  -moz-justify-content: -moz-space-between;
  -ms-justify-content: -ms-space-between;
  justify-content: space-between;
}

#top-nav div.menu {
  -webkit-flex: 1;
  display: -webkit-inline-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

#top-nav div.menu:last-child {
  display: -webkit-inline-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  -webkit-justify-content: flex-end;
  -webkit-flex-direction: row;
  flex-direction: row;
  justify-content: flex-end;
}

#top-nav div.menu,
#top-nav div.menu ul {
  text-align: left;
  alignment-baseline: baseline;
  margin: 0;
  padding: 0;
}
#top-nav div.menu ul {
  list-style: none;
}
#top-nav div.menu > ul {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
  white-space: nowrap;
}
#top-nav div.menu li {
  -webkit-flex-shrink: 0;
  -moz-flex-shrink: 0;
  -ms-flex-shrink: 0;
  flex-shrink: 0;
  margin: 0
  position: relative;
  font-size: 1.1em;
  cursor: pointer;
}
#top-nav div.menu ul li a {
  color: #E6E6E6;
  text-decoration: none;
  display: block;
  padding: 7px;
}

If the window shrinks I want "Item 4" to hide as soon as it starts to become overlapped by "Other 1".

Once I achieve this I'd also need a selector that can target those that are hidden.

jsfiddle setup here

like image 746
Brett Ryan Avatar asked Jun 19 '14 05:06

Brett Ryan


People also ask

How do you wrap the Flex content?

As you only want the text itself to wrap you need to use flex-wrap: nowrap; to keep . right on the same line. The text will automatically wrap when there is not enough space.

Why is flexbox overflowing?

The initial value of the flex-wrap property is nowrap . This means that if you have a set of flex items that are too wide for their container, they will overflow it.


2 Answers

A workaround for your problem would be to add following CSS code:

#top-nav div.menu > ul {
  flex-wrap: wrap;
  height: 34px;
  overflow: hidden;
}

If you want to know which elements got hidden, you should solve your problem using Javascript/jQuery, because you cannot know that using CSS.

like image 76
Barun Avatar answered Oct 13 '22 14:10

Barun


I made a multipart codepen demonstrating the above answers ( e.g. using overflow hidden and height) but also how you would expand / collapse overflowed items

Example 1: https://codepen.io/Kagerjay/pen/rraKLB ( Real simple example using the aanswers others have mentioned)

Example 2: https://codepen.io/Kagerjay/pen/LBErJL (Single event handler show more / showless on overflowed items)

Example 3: https://codepen.io/Kagerjay/pen/MBYBoJ (Multi event handler on many show more/ show less on overflowed items)

I have attached example 3 below as well, I use Jade/Pug so its kind of verbose example below

// Overflow boolean checker
function isOverflown(element){
  return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

// Jquery Toggle Text Plugin
$.fn.toggleText = function(t1, t2){
  if (this.text() == t1) this.text(t2);
  else                   this.text(t1);
  return this;
};

// Toggle Overflow
function toggleOverflow(e){
  e.target.parentElement.classList.toggle("grid-parent--showall");
  $(e.target).toggleText("Show More", "Show LESS");
}

// Where stuff happens
var parents = document.querySelectorAll(".grid-parent");

parents.forEach(parent => {
  if(isOverflown(parent)){
    parent.lastElementChild.classList.add("btn-show");
    parent.lastElementChild.addEventListener('click', toggleOverflow);
  }
})
body {
  background-color: #EEF0ED;
  margin-bottom: 300px;
}

.grid-parent {
  margin: 20px;
  width: 250px;
  background-color: lightgrey;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  max-height: 100px;
  position: relative;
}
.grid-parent--showall {
  max-height: none;
}

.grid-item {
  background-color: blue;
  width: 50px;
  height: 50px;
  box-sizing: border-box;
  border: 1px solid red;
}
.grid-item:nth-of-type(even) {
  background-color: lightblue;
}

.btn-expand {
  display: none;
  z-index: 3;
  position: absolute;
  right: 0px;
  bottom: 0px;
  padding: 3px;
  background-color: red;
  color: white;
}

.btn-show {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
  <p>Any grid-parent over 10 child items has a "SHOW MORE" button to expand</p>
  <p>Click "SHOW MORE" to see the results</p>
</section>
<radio></radio>
<div class="wrapper">
  <h3>5 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>8 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>10 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>13 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>16 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>19 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
</div>
like image 5
Vincent Tang Avatar answered Oct 13 '22 14:10

Vincent Tang