Steven Lu
Steven Lu

Reputation: 43427

Hide parent if all children are hidden

I have a list with groups in it, and use CSSOM to dynamically filter the contents using a text field. This is a way to implement a "search" using only CSS.

Unfortunately when the filter filters everything out, the group containers still remain visible. I'd need to also set display: none onto them using CSS somehow, otherwise I need to add a bunch of JS to control them.

Is this remotely possible? I know this is a bit of a long shot, but is there a selector that can select elements whose children (fitting some selector) all must have a style selected on them?

Is it even possible if I greatly relax the constraints, where this might be a selector that selects elements whose children (fitting some selector) all must have a particular class?

Upvotes: 8

Views: 7905

Answers (2)

rugk
rugk

Reputation: 5513

Actually, this is nowadays possible in CSS only with the :has selector, given it works as a parent selector. Also it is generally a good idea to use a class for hiding elements, which I have demonstrated below.

.container {
  background-color: red;
  padding: 2px;
}

@supports(selector(:has(div))) {
  .container {
    display: none
  }

  /* "unhides" all elements that contain at least one visible child element directly below */
  .container:has(> :not(.invisible)) {
    display: block;
  }
}

.invisible {
  /* display: none !important; */
  background-color: yellow; /* for easier debugging instead */
}
<!-- This will be visible -->
<div class="container">
  <h4>Should be visible:</h4>
  <div class="invisible">Invisible 1</div>
  <div class="invisible">Invisible 2</div>
  <div class="invisible">...</div>
</div>

<!-- This will be hidden -->
<div class="container">
  <div class="invisible">Invisible 1</div>
  <div class="invisible">Invisible 2</div>
  <div class="invisible">...</div>
</div>

<div class="container">
  Inline text is getting ignored
  <div class="invisible">Invisible 1</div>
  <div class="invisible">Invisible 2</div>
  <div class="invisible">...</div>
</div>

Mind the browser-support for :has, so I've wrapped it in a @supports clause.

Upvotes: 2

Vadim Ovchinnikov
Vadim Ovchinnikov

Reputation: 14012

No, it's impossible only via CSS:

  1. There is no parent selector.
  2. There is no visibility selector, except something like :not([style*="display:none"]):not([style*="display: none"]) if you hide elements only using inline CSS.
  3. There is no CSS way to know if all children satisfy some condition.

This can be solved only using pure JS loops and conditions or via jQuery selectors like .parent:not(:has(:visible)).

Upvotes: 8

Related Questions