Zapobiegaj rozszerzaniu elementów siatki przez zawartość

153

TL; DR: Czy jest coś podobnego table-layout: fixeddo siatek CSS?


Próbowałem utworzyć kalendarz z widokiem na rok z dużą siatką 4x3 dla miesięcy i tam zagnieżdżonymi siatkami 7x6 dla dni.

Kalendarz powinien wypełniać stronę, tak aby kontener siatki lat miał szerokość i wysokość 100% każdy.

.year-grid {
  width: 100%;
  height: 100%;

  display: grid;
  grid-template: repeat(3, 1fr) / repeat(4, 1fr);
}

.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
}

Oto działający przykład: https://codepen.io/loilo/full/ryXLpO/

Dla uproszczenia każdy miesiąc w tym zagrodzie ma 31 dni i zaczyna się w poniedziałek.

Wybrałem też śmiesznie mały rozmiar czcionki, aby zademonstrować problem:

Elementy siatki (= komórki dnia) są dość skondensowane, ponieważ na stronie jest ich kilkaset. A gdy tylko etykiety z numerami dni staną się zbyt duże (możesz swobodnie bawić się rozmiarem czcionki w piórze za pomocą przycisków w lewym górnym rogu), siatka po prostu powiększy się i przekroczy rozmiar strony.

Czy istnieje sposób, aby temu zapobiec?

Początkowo zadeklarowałem, że moja siatka roczna ma 100% szerokości i wysokości, więc prawdopodobnie od tego należy zacząć, ale nie mogłem znaleźć żadnych właściwości CSS związanych z siatką, które pasowałyby do tej potrzeby.

Zastrzeżenie: zdaję sobie sprawę, że istnieją dość łatwe sposoby na stylizowanie tego kalendarza bez użycia układu siatki CSS. Jednak to pytanie dotyczy bardziej ogólnej wiedzy na ten temat niż rozwiązania konkretnego przykładu.

Loilo
źródło
Co chcesz zamiast tego? Czcionka w każdej komórce może mieć dowolny rozmiar i nigdy nie powoduje zwiększenia rozmiaru komórki siatki?
Michael Coker
1
Dokładnie. Zasadniczo wygodniejszy sposób, co by się stało, gdybym ustawił rozmiary elementów siatki według wartości procentowych zamiast ułamków.
Loilo,
Zasadniczo szukam wersji układu tabeli z układem siatki: naprawiono (patrz: codepen.io/loilo/pen/dvxpvq?editors=1100 )
Loilo
7
To największy ból w całej specyfikacji CSS Grid. Muszą to być ustawienia, w których obszary siatki nie mogą uciec od wymiarów żadnego z ich kontenerów nadrzędnych! W rzeczywistości jest to koszmar dla głęboko zagnieżdżonych struktur siatkowych.
Lonnie Best

Odpowiedzi:

263

Domyślnie element siatki nie może być mniejszy niż rozmiar jego zawartości.

Elementy siatki mają początkowy rozmiar min-width: autoi min-height: auto.

Można to zmienić poprzez ustawienie pozycji do siatki min-width: 0, min-height: 0lub overflowz jakiegokolwiek innego niż wartości visible.

Ze specyfikacji:

6.6. Automatyczny minimalny rozmiar elementów siatki

Aby zapewnić bardziej rozsądny domyślny rozmiar minimalny dla elementów siatki, niniejsza specyfikacja definiuje, że autowartość min-width/ min-heightrównież stosuje automatyczny rozmiar minimalny w określonej osi do elementów siatki, których overflowjest visible. (Efekt jest analogiczny do automatycznego rozmiaru minimalnego nałożonego na elementy elastyczne).

Oto bardziej szczegółowe wyjaśnienie dotyczące elementów elastycznych, ale dotyczy to również elementów siatki:

Ten post obejmuje również potencjalne problemy z zagnieżdżonymi kontenerami i znane różnice w renderowaniu między głównymi przeglądarkami .


Aby naprawić układ, wprowadź następujące zmiany w kodzie:

.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;
  min-height: 0;  /* NEW */
  min-width: 0;   /* NEW; needed for Firefox */
}

.day-item {
  padding: 10px;
  background: #DFE7E7;
  overflow: hidden;  /* NEW */
  min-width: 0;      /* NEW; needed for Firefox */
}

poprawiony codepen


1fr vs minmax(0, 1fr)

Powyższe rozwiązanie działa na poziomie elementu siatki. Rozwiązanie na poziomie kontenera można znaleźć w tym poście:

Michael Benjamin
źródło
3
Łał. To jednocześnie fascynujące i interesujące, a na pewno nie wymyśliłbym tego po prostu próbując. Czy właśnie rzuciłeś okiem na specyfikację, aby uzyskać te informacje? Ponieważ nie wiedziałem, po co szukać w Google, próbowałem tego wcześniej, ale skończyło się na tym, że przeczytałem niewłaściwą sekcję (po stwierdzeniu złej przyczyny problemu).
Loilo,
1
Miałem wcześniej ten problem z elementami elastycznymi . Ponieważ istnieje wiele podobieństw między elementami flex i grid, doszedłem do wniosku, że zachowanie może być takie samo i skupione na tej sekcji specyfikacji.
Michael Benjamin,
1
Ustala wysokość, ale nadal rośnie w kierunku poziomym, min-width: 0;nie pomaga. Czy coś mi brakuje?
użytkownik
2
W przypadku siatek zagnieżdżonych musimy zastosować to na wszystkich poziomach. Ale naprawdę przyszedłem tutaj, aby zagłosować i podziękować ...
Knack
2
@PragyAgarwal .. stackoverflow.com/users/3597276/michael-b?tab=answers :-)
Michael Benjamin
57

Poprzednia odpowiedź jest dobra, ładna, ale chciałem też wspomnieć, że nie jest stałą równoważny układ do sieci, wystarczy napisać minmax(0, 1fr)zamiast 1frjako wielkości toru.

FremyCompany
źródło
6
Polecam takie podejście w stosunku do poprzedniej, zaakceptowanej odpowiedzi.
Thierry Prost,
Chociaż to działa, trochę z tego nie rozumiem ... Czy mógłbyś wyjaśnić, dlaczego to działa? Co robi minmax (0, 1fr)? Czy nie powinno to zawsze wynosić 0? Jestem zdezorientowany :(
BAERUS
2
minmax(0, 1fr)działa, ponieważ 1frtak naprawdę jest skrótem dla minmax(auto,1fr), co nie jest poprawną wartością dla pierwotnego pytania.
Mikko Rantalainen
Więcej informacji można znaleźć na stronie github.com/w3c/csswg-drafts/issues/1777
Mikko Rantalainen,
1

Istniejące odpowiedzi rozwiązują większość przypadków. Jednak natknąłem się na przypadek, w którym potrzebowałem zawartości komórki siatki overflow: visible. Rozwiązałem to, umieszczając absolutnie w opakowaniu (nie idealne, ale najlepsze, jakie znam), na przykład:


.month-grid {
  display: grid;
  grid-template: repeat(6, 1fr) / repeat(7, 1fr);
  background: #fff;
  grid-gap: 2px;  
}

.day-item-wrapper {
  position: relative;
}

.day-item {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 10px;

  background: rgba(0,0,0,0.1);
}

https://codepen.io/bjnsn/pen/vYYVPZv

bjnsn
źródło
0

łatwiejszą rzeczą będzie ustawienie maksymalnej szerokości elementu siatki w następujący sposób:

//for the container
.gridContainer{
    display: grid;
    grids-templates-column: repeat (12, 1fr);
 }

 //for the grid item
 .gridItem{
       max-width: 100%;
       grid-column: span 4  //4 can be any number from1-12 as we specified in the grid template
  }
Pedro JR
źródło
Jestem trochę zdezorientowany, jeśli mam być szczery. Twój kod w ogóle nie przypomina oryginalnego pytania, a zastosowanie max-width: 100% do elementów siatki (zamiast min-width: 0 z przyjętego rozwiązania) nie rozwiąże problemu ...
Loilo
max-width zapobiegnie ponownej regulacji w stosunku do szerokości dziecka
Pedro JR
Próbowałem odtworzyć twój kod i faktycznie działa, ale wydaje się, że nie jest tak z powodu max-width: 100%, ale z powodu grid-column: span 4; bez definiowania kolumny początkowej. Zdefiniuj kolumnę początkową (np. Używając grid-column: 1 / span 4;) i ponownie zepsuje to układ. (To zachowanie jest trochę dziwne, ale jestem pewien, że gdzieś w specyfikacji jest róg, w którym jest to zdefiniowane.)
Loilo
w porządku, brzmi dobrze. ale nie myślisz jeszcze o głosowaniu za mnie
Pedro JR
Szczerze mówiąc: 1. To jest problem rozwiązany od ponad trzech lat. 2. Twoja odpowiedź nie została poprawnie przetestowana (CSS zawiera wiele literówek, które należy poprawić, zanim przeglądarka w ogóle rozpozna twoją siatkę). 3. Twoja odpowiedź nie odpowiadała w rzeczywistości przykładowi z mojego pytania (w przeciwnym razie zorientowałbyś się, że Twoje rozwiązanie nie działa). - Więc nie, przepraszam, ale nie rozważam poparcia.
Loilo