Rolf B: 1fr Höhenangaben in einem Grid

Hallo,

ich habe ein Seitenlayout, das ich gar nicht für so kompliziert halte. Der Body soll 100vh hoch sein, hat einen head mit Auto-Höhe, und dann zwei Streifen, die gleich hoch sein sollen. Streifen 1 besteht aus nav und main, Streifen 2 ist ein footer (das ist ein Debug-Layout, der Footer enthält Log-Infos, darum soll er höher sein).

body {
  margin: 0;
  height: 100vh;
  display: grid;
  grid-template: "head head" auto
                 "nav main" 1fr
                 "foot foot" 1fr
                 / 10em 1fr;
}

Zum Zweck der Diskussion kann der body des HTML minimal sein.

<body>
<header><h1>Header</h1></header>
<nav>NAV</nav>
<main>
  <header><h2>Header 2</h2></header>
  <ul>
  <li>Item</li>...20 stück...<li>Item</li>
  </ul>
</main>
<footer>Fooo</footer>
</body>

Innerhalb von main möchte ich, dass h2 ständig sichtbar ist und die Liste scrollt. Vermutlich könnte ich das mit Subgrid lösen, oder einem komplexeren Body-Grid. Ich wollte das Layout des main-Bereichs aber austauschbar und separat halten und habe darum ein eigenes Grid daraus gemacht.

main {
  grid-area: main;
  display: grid;
  grid-template-rows: auto 1fr;
}
main ul {
  overflow-y: scroll;
}

Aber: Das funktioniert nicht. Der Browser (Chrome und Firefox) vergrößert statt dessen den 1. Streifen, so dass alle li sichtbar werden. Wenn die 100vh des body nicht ausreichen, macht er ihn auch höher (und erzeugt den Scrollbar, den ich nicht will)

Ich habe dazu neulich selbst was geschrieben, finde es aber nicht wieder - Problem müsste sein - wenn ich mich recht erinnere - dass die Höhe eines inneren Elements bei relativen Höhenangaben in äußeren Containern nicht eingegrenzt wird. Dazu braucht es absolute Angaben.

Wenn ich die 1fr Angaben im Body-Grid durch calc(50vh - 1.5em) ersetze und den Header auf 3em festsetze, dann bekommt die Liste ihren Scrollbar. Aber diese Starrheit will ich nicht.

Was ich herausgefunden habe: Gebe ich dem main-Element ein overflow-y: hidden, DANN werden die 1fr Angaben des body-Grid auf einmal beachtet und die Liste im main bekommt einen Scrollbar.

-> https://jsfiddle.net/Rolf_b/v38w6mLn/

Liegt das daran, dass overflow:hidden einen block formatting context erzeugt? Geht das irgendwie besser? Ich habe es mit dem contain-Attribut versucht. Die Werte layout, paint oder content sollen ja auch einen BFC erzeugen - aber nein. Das löst es nicht. Aber: contain:size; - das löst es auch.

Bevor ich das blog- oder wikifiziere: Doktere ich hier an Symptomen herum und mache was anderes grundsätzlich falsch? Oder ist das, was ich da getan habe, so im Sinne des CSS Erfinders?

Update: Da hab ich wohl vor einem Jahr schon mal gebastelt - und die Antwort auf den Titel jenes Threads lautet offensichtlich: "Nein, Rolf!". Aber overflow:hidden auf dem img scheint auch mein damaliges Problem zu lösen. Dann klappt es sogar ohne ein Hilfs-Div. contain:size dagegen hilft nicht.

Rolf

--
sumpsi - posui - obstruxi
  1. Hallo Rolf,

      grid-template: "head head" auto
                     "nav main" 1fr
                     "foot foot" 1fr
                     / 10em 1fr;
    

    Dies war der Anlass meiner Bastelei, es passiert aber auch bei einem footer mit fester Höhe. Wenn main seinerseits ein Grid wird, braucht es contain:size oder overflow:hidden, damit seine Höhe limitiert werden kann.

    Rolf

    --
    sumpsi - posui - obstruxi
  2. Tach!

    Aber: Das funktioniert nicht. Der Browser (Chrome und Firefox) vergrößert statt dessen den 1. Streifen, so dass alle li sichtbar werden. Wenn die 100vh des body nicht ausreichen, macht er ihn auch höher (und erzeugt den Scrollbar, den ich nicht will)

    Die Einheit fr verteilt nur den "remaining" Platz. Bei mehreren Elementen mit jeweils 1fr bekommen alle Elemente erstmal den Platz, den sie brauchen. Der Rest, wenn noch welcher übrig ist, wird dann aufgeteilt. Zum Beispiel bei drei Elementen ist das eine größer als ein Drittel, dann bekommen die anderen beiden den eventuell verbleibenden Rest, so dass sie gleich groß werden.

    Für eine generell gleiche Verteilung des Platzes muss man den Elementen im Grid das overflow auf hidden oder auto setzen, zumindest demjenigen, das zu groß werden kann.

    dedlfix.

    1. Hallo dedlfix,

      ja, das ist eben die Verständnisschwierigkeit. Wenn ich ein row-template für Grid auf auto 1fr 1fr setze, erwarte ich doch eigentlich, dass ich damit "von außen nach innen" den Platz definiere. Erste Zeile auto, und Zeile 2+3 sollen sich den remaining space im Verhältnis 1:1 teilen. Wenn ich wollte, dass eine Zeile "mindestens" 1fr bekommt, eventuell mehr und EVENTUELL sogar das ganze Grid seine Höhenbegrenzung auf 100% sprengt (zumindest bei overflow:auto im main), dann würde ich doch kein height oder max-height auf den Body legen und ein anderes Row-Template verwenden.

      Aber DANN guckt sich der Brauser das Innenleben der Zeilen an und stellt fest, dass eine mehr Platz braucht, und verteilt neu. Es ist nun mal so, und man muss es hinnehmen, aber logisch finde ich es nicht.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Tach!

        Aber DANN guckt sich der Brauser das Innenleben der Zeilen an und stellt fest, dass eine mehr Platz braucht, und verteilt neu. Es ist nun mal so, und man muss es hinnehmen, aber logisch finde ich es nicht.

        Ja, das ist etwas ärgerlich, weil man das weder so erwartet (vielleicht auch, weil man das von .NETs XAML nicht so kennt), noch ist das Verhalten von fr so deutlich in den Tutorials beschrieben. Und es fällt oftmals nicht gleich auf, weil man mit wenig Testdaten zunächst nicht merkt, dass die Container sich ausdehnen.

        dedlfix.

        1. Hallo dedlfix,

          XAML? W[TP]F?

          Ich bin bei WinForms stehen geblieben 😂

          Rolf

          --
          sumpsi - posui - obstruxi