Empêcher le contenu de développer les éléments de la grille

153

TL; DR: Y a - t-il quelque chose comme table-layout: fixedpour les grilles CSS?


J'ai essayé de créer un calendrier à vue annuelle avec une grande grille 4x3 pour les mois et des grilles 7x6 imbriquées pour les jours.

Le calendrier doit remplir la page, de sorte que le conteneur de la grille d'année a une largeur et une hauteur de 100% chacun.

.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);
}

Voici un exemple de travail: https://codepen.io/loilo/full/ryXLpO/

Pour simplifier, chaque mois dans cet enclos a 31 jours et commence un lundi.

J'ai également choisi une taille de police ridiculement petite pour illustrer le problème:

Les éléments de la grille (= cellules de jour) sont assez condensés car il y en a plusieurs centaines sur la page. Et dès que les étiquettes de numéro de jour deviennent trop grandes (n'hésitez pas à jouer avec la taille de la police dans le stylo en utilisant les boutons en haut à gauche), la grille augmentera simplement en taille et dépassera la taille du corps de la page.

Existe-t-il un moyen d'empêcher ce comportement?

J'ai initialement déclaré que ma grille d'année était à 100% en largeur et en hauteur, c'est donc probablement le point de départ, mais je n'ai pas trouvé de propriétés CSS liées à la grille qui auraient répondu à ce besoin.

Avertissement: je suis conscient qu'il existe des moyens assez simples de styliser ce calendrier sans utiliser CSS Grid Layout. Cependant, cette question concerne plus les connaissances générales sur le sujet que la résolution de l'exemple concret.

Loilo
la source
Que voulez-vous qu'il se passe à la place? La police de chaque cellule peut être de n'importe quelle taille et ne provoque jamais l'augmentation de la taille de la cellule de la grille?
Michael Coker
1
Exactement. Fondamentalement, un moyen plus pratique de ce qui se passerait si je définissais les tailles des éléments de la grille en fonction de valeurs de pourcentage au lieu de fractions.
Loilo
Je recherche essentiellement une version en grille de mise en page de table: corrigé (voir: codepen.io/loilo/pen/dvxpvq?editors=1100 )
Loilo
7
C'est le plus gros problème de toute la spécification CSS Grid. Ils doivent être un cadre où les zones de grille ne peuvent pas échapper aux dimensions de l'un de leurs conteneurs de grille parent! En l'état, c'est un cauchemar pour les structures de grille profondément imbriquées.
Lonnie Best

Réponses:

263

Par défaut, un élément de la grille ne peut pas être plus petit que la taille de son contenu.

Les éléments de la grille ont une taille initiale de min-width: autoet min-height: auto.

Vous pouvez modifier ce comportement en définissant les éléments de la grille à min-width: 0, min-height: 0ou overflowavec toute autre valeur que visible.

De la spécification:

6.6. Taille minimale automatique des éléments de la grille

Pour fournir une taille minimale par défaut plus raisonnable pour les éléments de la grille, cette spécification définit que la autovaleur de min-width/ min-heightapplique également une taille minimale automatique dans l'axe spécifié aux éléments de la grille dont overflowest visible. (L'effet est analogue à la taille minimale automatique imposée aux éléments flexibles.)

Voici une explication plus détaillée couvrant les éléments flexibles, mais elle s'applique également aux éléments de la grille:

Cet article couvre également les problèmes potentiels avec les conteneurs imbriqués et les différences de rendu connues entre les principaux navigateurs .


Pour corriger votre mise en page, apportez ces ajustements à votre code:

.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 */
}

codepen révisé


1fr contre minmax(0, 1fr)

La solution ci-dessus fonctionne au niveau de l'élément de la grille. Pour une solution au niveau du conteneur, consultez cet article:

Michael Benjamin
la source
3
Sensationnel. C'est fascinant et intéressant à la fois, et je ne l'aurais certainement pas trouvé en essayant simplement. Avez-vous juste jeté un coup d'œil à travers les spécifications pour cette information? Parce qu'après ne pas savoir quoi chercher sur Google, c'est ce que j'ai essayé avant, mais j'ai fini par lire la mauvaise section (après avoir conclu la mauvaise cause du problème).
Loilo
1
J'avais déjà rencontré ce problème avec des éléments flexibles . Étant donné qu'il existe de nombreuses similitudes entre les éléments flex et grid, j'ai pensé que le comportement pourrait être le même et je me suis concentré sur cette section de la spécification.
Michael Benjamin
1
Il fixe la hauteur, mais il continue de croître dans le sens horizontal, min-width: 0;n'aide pas. Est-ce que je manque quelque chose?
utilisateur
2
Pour les grilles imbriquées, nous devons l'appliquer à tous les niveaux. Mais je suis vraiment venu ici pour voter et merci ..
Knack
2
@PragyAgarwal .. stackoverflow.com/users/3597276/michael-b?tab=answers :-)
Michael Benjamin
57

La réponse précédente est assez bonne, mais je voulais aussi mentionner qu'il est un équivalent de mise en page fixe pour les réseaux, vous avez juste besoin d'écrire au minmax(0, 1fr)lieu de 1frvotre taille de piste.

FremyCompany
la source
6
Je recommande cette approche par rapport à la réponse précédente acceptée.
Thierry Prost
Bien que cela fonctionne, je n'y comprends pas un peu ... Pouvez-vous expliquer pourquoi cela fonctionne? Que fait minmax (0, 1fr)? Cela ne devrait-il pas toujours être égal à 0? Je suis confus :(
BAERUS
2
minmax(0, 1fr)fonctionne parce que 1frc'est vraiment un raccourci pour minmax(auto,1fr), qui n'est pas la valeur correcte pour la question d'origine.
Mikko Rantalainen
Pour plus de détails, voir github.com/w3c/csswg-drafts/issues/1777
Mikko Rantalainen
1

Les réponses existantes résolvent la plupart des cas. Cependant, je suis tombé sur un cas où j'avais besoin du contenu de la cellule de la grille overflow: visible. Je l'ai résolu en positionnant absolument dans un emballage (pas idéal, mais le meilleur que je connaisse), comme ceci:


.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
la source
0

une chose plus facile à faire consiste à définir la largeur maximale de l'élément de la grille comme ceci:

//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
la source
Je suis un peu confus pour être honnête. Votre code ne ressemble pas du tout à la question d'origine, et appliquer max-width: 100% aux éléments de la grille (au lieu de min-width: 0 de la solution acceptée) ne résoudra pas le problème ...
Loilo
max-width l'empêchera de se réajuster par rapport à sa largeur enfant
Pedro JR
J'ai essayé de reproduire votre code, et cela fonctionne réellement, mais cela ne semble pas être à cause de la largeur max: 100% mais à cause de la grille-colonne: span 4; sans définir de colonne de départ. Définissez une colonne de départ (par exemple en utilisant grid-column: 1 / span 4;) et cela cassera à nouveau la disposition. (Ce comportement est un peu étrange, mais je suis sûr qu'il y a un coin quelque part dans la spécification où cela est défini.)
Loilo
d'accord, ça sonne bien. mais vous n'envisagez pas encore de vote pour moi
Pedro JR
Pour être franchement honnête: 1. Ce problème est résolu depuis plus de trois ans. 2. votre réponse n'est pas correctement testée (votre CSS contient plusieurs fautes de frappe qui doivent être corrigées avant même que le navigateur ne reconnaisse votre grille). Et 3. votre réponse ne correspondait pas réellement à l'exemple de ma question (sinon vous auriez réalisé que votre solution ne fonctionnait pas avec elle). - Alors non, je suis désolé, mais je n'envisage pas de voter pour.
Loilo