1

I was trying to get a div to fill the height of the remaining screen space and found the excellent answer here: Make a div fill the height of the remaining screen space (the chosen answer).

My problem with https://stackoverflow.com/users/1490904/pebbl's is that the flex container for the content as he presents it is height:100% and is a direct child of html and body elements with height:100%. In my app there are a bunch of intervening elements between the body and my flex container, and if I want my flex container to fill all available vertical space, each of these elements also has to have height:100%.

It works great if I just have a css rule like

 * {
     height: 100%;
   }

but that's crazy, right? I don't know if it's a problem to set every element in my DOM to 100%, but I'd rather not if I don't need to.

I tried (thinking this would select every element between body and my flex-box):

body * .flex-box {
  height: 100%;
}

with no luck.

My html (after being processed by react) looks sort of like:

<html>
  <body>
    <div>
      <div class="another-div">
        <div class="another-div navbar-and-whatnot">
          <div class="yet-another-bunch-of-divs">
            <div class="flex-box">
              <div class="flex-remaining-height">
                <svg class="this-should-be-big" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

And the relevant part of my scss file (including the non-working attempt to set height along the path) is:

html, body {
  height: 100%;
}
body * .flex-box { // this part doesn't work. the rest comes from https://stackoverflow.com/a/24979148/1368860
  height: 100%;
}
.flex-box {
  display: flex;
  flex-flow: column;
  height: 100%;
  //.flex-row { border: 1px dotted grey; }
  .flex-content-height {
    flex: 0 1 auto;
    /* The above is shorthand for:
    flex-grow: 0,
    flex-shrink: 1,
    flex-basis: auto
    */
  }
  .flex-remaining-height {
    flex: 1 1 auto;
  }
  .flex-fixed-height-40 {
    flex: 0 1 40px;
  }
}

I guess for now I can figure out every element in the path between body and my flex-box and set heights for them, but that's pretty fragile. I'll be needing to fix it constantly.

BTW, I'm using react-bootstrap, so if there's a simpler solution that way, I'll take it.

And, for further context, the reason I want to do this is that I'm using a library that creates an SVG element as big as its surrounding div and I want the SVG to be as big as possible (and fit on the screen).

P.P.S. I've also got jquery loaded. I guess that would be the easiest fix. Still, it would be nice to have a css solution.

Community
  • 1
  • 1
Sigfried
  • 2,943
  • 3
  • 31
  • 43

2 Answers2

2

There is no way in CSS to select a "path" of this kind. Selecting everything with * is dangerous and not good on performance, either. I would suggest that you instead define the path yourself. The easiest way might be to define a single class, say .full-height and just give this class to all the elements in the path. This way you only have to add the class to any new elements you add to this path, and the CSS can remain unchanged.

.full-height {
  height: 100%
}
skreborn
  • 2,133
  • 2
  • 16
  • 27
  • "Selecting everything with * is dangerous and not good on performance, either." But that's not what he's doing, so it's fine. – BoltClock Feb 21 '17 at 12:53
  • @BoltClock it is mentioned as an extreme possibility in the original question. I merely meant to emphasize that this *is* indeed a very bad idea. – skreborn Feb 21 '17 at 12:55
  • Ah, I missed that. – BoltClock Feb 21 '17 at 12:56
  • Great idea. Thanks! – Sigfried Feb 21 '17 at 13:17
  • Actually, I think this doesn't quite work -- my whole premise is wrong. Things with `full-height` class are turning out the same height as the body, even if they're in divs with stuff above and below them. – Sigfried Feb 21 '17 at 13:34
2

I'm afraid you're out of luck there. It is not possible to write a single complex selector matching all ancestors of a given element.

The selector body * .flex-box matches .flex-box that contains at least one ancestor appearing between it and body. Such a selector implies that body > .flex-box will not match. It does not match anything else other than .flex-box (unless that .flex-box itself contains another .flex-box, in which case both will match, ad nauseum).

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356