khush
khush

Reputation: 2801

Hide child elements which are cropped due to overflow hidden property

Although there are many similar question posted around this topic, there are no apt answers present.

Here, overflow hidden property is applied to parent div. I want to show only those child elements which are visible 100% in this container. As shown in picture, I want to hide 3rd item which is cropped.

enter image description here

.wrapper {
    border: 1px solid black;
    display: block;
    overflow-x: hidden;
    white-space: nowrap;
    width: 200px;

}

  .item {
    border: 1px solid red;
    box-sizing: border-box;
    display: inline-block;
    *display:inline; /* for IE7*/
    *zoom:1;/* for IE7*/
    width: 40%;
}

#i1{ height: 32px; }
#i2{ height: 64px; }
#i3{ height: 48px; }
<div class="wrapper">
    <div id="i1" class="item">
      item 1
    </div>
    <div id="i2" class="item">
      item 2
    </div>
    <div id="i3" class="item">
      item 3
    </div>
   

</div>

Upvotes: 0

Views: 111

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

If you're okay with statically setting the height of the wrapper to the height of the highest item (but keep reading if not), you can make the items wrap by removing the white-space: nowrap and adding overflow-y: hidden; (along with height):

.wrapper {
    border: 1px solid black;
    display: block;
    overflow-x: hidden;
    overflow-y: hidden; /* <=== */
    height: 64px;       /* <=== */
    width: 200px;
}

Live Example:

.wrapper {
    border: 1px solid black;
    display: block;
    overflow-x: hidden;
    overflow-y: hidden; /* <=== */
    height: 64px;       /* <=== */
    width: 200px;
}

.item {
    border: 1px solid red;
    box-sizing: border-box;
    display: inline-block;
    *display:inline; /* for IE7*/
    *zoom:1;/* for IE7*/
    width: 40%;
}

.hidden {
    display: none;
}

#i1{ height: 32px; }
#i2{ height: 64px; }
#i3{ height: 48px; }
<div class="wrapper">
    <div id="i1" class="item">
      item 1
    </div>
    <div id="i2" class="item">
      item 2
    </div>
    <div id="i3" class="item">
      item 3
    </div>
</div>

That works because the child elements are inline-block, and when the last child wraps, it's hidden because the parent isn't tall enough to show it.


Assuming you don't want to do that, I can't think of a way other than JavaScript:

const wrapper = document.querySelector(".wrapper");
const wrapperBox = wrapper.getBoundingClientRect();
for (const child of wrapper.children) {
    const childBox = child.getBoundingClientRect();
    child.classList.toggle("hidden", overflows(wrapperBox, childBox));
}

function overflows(parentBox, childBox) {
    return childBox.right > wrapperBox.right ||
        childBox.bottom > wrapperBox.bottom ||
        childBox.left < wrapperBox.left ||
        childBox.top < wrapperBox.top;
}

That would need to be re-run whenever the layout changed, unlike the CSS example where the browser would effectively do that for you.

Live Example:

const wrapper = document.querySelector(".wrapper");
const wrapperBox = wrapper.getBoundingClientRect();
for (const child of wrapper.children) {
    const childBox = child.getBoundingClientRect();
    child.classList.toggle("hidden", overflows(wrapperBox, childBox));
}

function overflows(parentBox, childBox) {
    return childBox.right > wrapperBox.right ||
        childBox.bottom > wrapperBox.bottom ||
        childBox.left < wrapperBox.left ||
        childBox.top < wrapperBox.top;
}
.wrapper {
    border: 1px solid black;
    display: block;
    overflow-x: hidden;
    white-space: nowrap;
    width: 200px;

}

.item {
    border: 1px solid red;
    box-sizing: border-box;
    display: inline-block;
    *display:inline; /* for IE7*/
    *zoom:1;/* for IE7*/
    width: 40%;
}

.hidden {
    display: none;
}

#i1{ height: 32px; }
#i2{ height: 64px; }
#i3{ height: 48px; }
<div class="wrapper">
    <div id="i1" class="item">
      item 1
    </div>
    <div id="i2" class="item">
      item 2
    </div>
    <div id="i3" class="item">
      item 3
    </div>
   

</div>

Upvotes: 1

Related Questions