5
votes

CSS Grid n'enveloppera pas les enfants lors de la définition de la ligne de grille

CODEPEN

J'expérimente avec Grid CSS et j'essaie d'arriver à cette mise en page qui est actuellement mise en œuvre à l'échelle

Mise en page attendue entrez la description de l'image ici

Problème: Sur le bureau, l'en-tête de l'élément doit avoir une largeur de 8 colonnes et si je n'ajoute pas de lignes de grille à element-header et element que

1
remplira le prochain element-header . Maintenant, si j'ajoute des lignes de grille , mon élément ne sera plus enveloppé.

Disposition actuelle (problème) entrez la description de l'image ici entrez la description de l'image ici

Question Comment puis-je corriger ma grille pour qu'elle corresponde à la capture d'écran "mise en page attendue" ci-dessus? c'est-à-dire que .element s'encapsulera et commencera sur la deuxième ligne de la grille

Code:

HTML: em >

.section {
  width: 100%;
  display: block;
  background: red;
  box-sizing: border-box;
  padding: 40px 24px;

  @media screen and (min-width: 600px) and (max-width: 1139px) {
    background: orange;
    padding: 56px 48px;
  }

  @media screen and (min-width: 1140px) {
    padding: 64px 48px;
    background: green;
  }
}

.container {
  margin: 0 auto;
  background: rgba(244,244,244, .25);
  max-width: 599px;

  @media screen and (min-width: 600px) and (max-width: 1139px) {
    max-width: 1039px;
    background: rgba(244,244,244, .25);
  }

  @media screen and (min-width: 1140px) {
    max-width: 1032px;
    background: rgba(244,244,244, .25);
  }
}

.samba-grid {
  display: grid;
  background: inherit;
  width: 100%;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 'auto auto';
  grid-gap: 24px;

  @media screen and (min-width: 600px) and (max-width: 1139px) {
    grid-template-columns: repeat(6, 1fr);
    grid-gap: 48px;
  }

  @media screen and (min-width: 1140px) {
    grid-template-columns: repeat(12, 1fr);
    grid-gap: 48px;
  }
}

h1 {
  font-size: 52px;
}
.element-header {
  grid-row: 1;
  grid-column: span 8; // SET THIS TO "span 12" TO SEE EXPECTED BEHAVIOR
}

.element {
  display: grid; // important to do this.
  background: rgba(0,0,0,.3);
  grid-column: span 3;
  grid-row: 2; // REMOVE THIS TO SEE EXPECTED BEHAVIOR

  @media screen and (min-width: 600px) and (max-width: 1139px) {
    grid-column: span 3;
  }

  @media screen and (min-width: 1140px) {
    grid-column: span 4;
  }
}

CSS:

<section class="section">
  <div class="container">
    <div class="samba-grid">
      <div class="element-header"><h1>I am a lot of header text that only goes 8 columsn wide</h1></div>
      <div class="element">1</div>
      <div class="element">2</div>
      <div class="element">3</div>
      <div class="element">4</div>     
    </div>
  </div>
</section>


4 commentaires

Pouvez-vous ajouter les images à l'origine du problème dans l'exemple CodePen?


@AndyHoffman terminé @!


J'ai ajouté span 12 où vous avez donné des instructions et commenté grid-row: 2 , mais je ne peux pas reproduire le problème que vous décrivez. Les images s'enroulent vers le bas mais pas vers le haut à côté de l'en-tête. Pouvez-vous charger votre stylo et fournir un lien vers la fourche avec le problème exact?


Ouais désolé c'est un problème difficile à décrire. Ignorez ces commentaires. Voici ce que je veux: je veux que les images: commencent sur la deuxième ligne et se terminent et je veux également garder l'en-tête à span 8


4 Réponses :


1
votes

Retirez l'en-tête du conteneur de la grille. Faites-en un élément autonome au niveau du bloc.

En dessous, placez le conteneur de grille avec uniquement les images.


4 commentaires

Compte tenu de votre solution, je force essentiellement des lignes basées sur DOM au lieu du CSS? Je fais confiance à votre jugement basé sur vos 154k points, donc, j'utilise / comprends sûrement Grid CSS de manière incorrecte, hein? Avez-vous autre chose à ajouter pourquoi je ne devrais / ne peux pas utiliser grid-row?


J'apprécie votre confiance en moi, mais je vais devoir y revenir plus tard, car je ne peux pas tester grand-chose à partir d'un appareil mobile.


Revenez bientôt s'il vous plaît!


D'autres grands experts de la grille / flex ici aussi. J'espère qu'ils pourront vous aider maintenant.



1
votes

Vous pouvez faire en sorte que le texte prenne toute la ligne, puis à l'intérieur vous diminuez sa largeur pour qu'il ne prenne que la largeur nécessaire. Comme ça vous bloquerez la 1ère ligne et aucun élément ne pourra y aller.

Voici un exemple simplifié:

<div class="samba-grid">
  <div class="element-header">
    <h1>I am a lot of header text that only goes 8 columsn wide</h1>
  </div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
.samba-grid {
  display: grid;
  background: inherit;
  width: 100%;
  grid-template-columns: repeat(12, 1fr);
  grid-gap: 24px;
  border:1px solid;
}

.element-header {
  grid-row: 1;
  grid-column: span 8;
  background:red;
  order:-2;
}

.samba-grid:before {
 content:"";
 order:-1;
 grid-column: span 4;
 background:blue;
 height:2px;
}

.samba-grid > span {
  height:50px;
  grid-column: span 2;
  background:green;
}

Pour le rendre plus dynamique et facile à manipuler, vous pouvez considérer les variables CSS:

<div class="samba-grid">
  <div class="element-header">
    <h1>I am a lot of header text that only goes 8 columsn wide</h1>
  </div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
:root {
  --grid:12;
  --gap:24px;
}

.samba-grid {
  display: grid;
  background: inherit;
  width: 100%;
  grid-template-columns: repeat(var(--grid), 1fr);
  grid-gap: var(--gap);
  border:1px solid;
}

.element-header {
  grid-row: 1;
  grid-column: 1/-1;
  --grid-column:8; /*simply adjust this value to control the column*/
}
.element-header > h1 {
  width:calc(var(--grid-column)*(100% - (var(--grid) - 1)*var(--gap))/var(--grid) + calc(var(--grid-column) - 1)*var(--gap));
  background:red;
  margin:0;
}
.samba-grid > span {
  height:50px;
  grid-column: span 2;
  background:green;
}

Une autre idée est de considérer un élément caché qui occupera l'espace restant de la première ligne:

<div class="samba-grid">
  <div class="element-header">
    <h1>I am a lot of header text that only goes 8 columsn wide</h1>
  </div>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
.samba-grid {
  display: grid;
  background: inherit;
  width: 100%;
  grid-template-columns: repeat(12, 1fr);
  grid-gap: 24px;
  border:1px solid;
}

.element-header {
  grid-row: 1;
  grid-column: 1/-1;
}
.element-header > h1 {
  /*we take 8 colmuns (without gaps) + 7 gaps*/
  width:calc(8*(100% - 11*24px)/12 + 7*24px);
  background:red;
  margin:0;
}
.samba-grid > span {
  height:50px;
  grid-column: span 2;
  background:green;
}

En remarque, définir grid-row: 2 ne signifie pas commencer à partir de la deuxième ligne mais cela signifie être à l'intérieur de la deuxième ligne qui crée le problème.


14 commentaires

Ok donc à un niveau élevé, votre solution est, 1 - faire un wrapper 2 - utiliser calc pour calculer la "sous-grille"


@MatthewHarwood oui en gros, comme ça vous bloquerez la première ligne de votre élément et à l'intérieur vous diminuerez la hauteur comme vous le souhaitez. une autre idée est d'utiliser un élément caché, je vais éditer pour l'ajouter


Étant donné cette disposition, dois-je toujours utiliser la ligne de grille? J'ai l'impression que cela entraînera la même erreur. Le bloc caché devient un peu encombrant également car sur tablette et mobile, l'en-tête est à fond perdu.


@MatthewHarwood, vous n'avez plus besoin de ligne de grille dans ce cas, et l'élément caché ne sera pas un problème mais vous devez le changer comme vous le faites avec l'en-tête sur un petit éboulis, c'est comme si vous traitez avec un élément supplémentaire (je édité pour inclure ceci)


Ahh la commande et: après c'est super malin aussi! J'adore ces réponses jusqu'à présent, mais je ne comprends toujours pas pourquoi la logique de la ligne de grille rompt la disposition prévue. J'ai l'impression que la ligne de grille est la plus logique, mais il semble que cela ne fonctionnera toujours pas


@MatthewHarwood le problème n'est pas avec la ligne de grille elle-même, mais le fait que vous ayez encore de l'espace sur la droite qui peut contenir un élément .. grid-row peut empêcher cela mais cela changera également le comportement de la grille, créant un problème. Dans votre cas, vous les forcez à être sur la deuxième rangée (tous)


@MatthewHarwood grid-row ne fait pas ce que vous attendez (commencez à partir de la deuxième ligne) mais cela les place dans la deuxième ligne


Ok Cela a du sens, mais pourquoi est-ce que lorsque vous spécifiez une ligne sans grille, elle s'enroule naturellement? Est-ce que ça fait une nouvelle rangée? Est-il possible de définir le "début" d'une ligne de grille mais de faire en sorte que l'extrémité de ligne de grille hérite du comportement par défaut "auto wrap"?


@MatthewHarwood cela s'appelle la grille implicite , si rien n'est spécifié, l'algorithme de grille placera l'élément en utilisant une certaine logique. mais si vous spécifiez des éléments tels que grid-row, cela devient une grille explicite et le navigateur doit suivre les instructions. Nous pouvons contrôler le wrap mais ne savons pas si nous pouvons contrôler le quand il devrait envelopper (essaiera d'y penser)


merci beaucoup pour cette goutte de connaissances. Je vais laisser ce fil ouvert pour quelques réponses supplémentaires. Mais j'ai appris plus dans ce fil que la lecture de tous les articles au cours des derniers mois. De plus, je sais que c'est un peu exagéré, mais j'aimerais beaucoup une méthode de définition explicite de la grille implicite;) ouais?


@MatthewHarwood J'ai fait une autre modification pour inclure la variable CSS pour le premier exemple


Marquer ceci comme correct, mais ce serait formidable si vous avez d'autres idées intéressantes sur la façon de réinitialiser la grille implicite


@MatthewHarwood Oui, je garde cela à l'esprit;) reviendrai Si je trouve une solution cool ... En fait, toutes les idées sont en quelque sorte des hacks


Si tu as une minute, j'ai un autre coup dur pour toi. stackoverflow.com/questions/55175808/… Apprendre CSS Grid est tellement plus difficile que les flottants et Flex



1
votes

Je demande à .element-header de toujours couvrir le nombre maximum de colonnes disponibles. Pour le h1 , j'ai ajouté une règle dans la requête @media plus grande qui la maintient à l'échelle correctement (8 colonnes sur 12). De plus, j'ai commenté .grid-row: 2 .

<section class="section">
  <div class="container">
    <div class="samba-grid">
      <div class="element-header"><h1>I am a lot of header text that only goes 8 columns wide</h1></div>
      <div class="element"><img src="https://placebear.com/160/90" alt=""></div>
      <div class="element"><img src="https://placebear.com/160/90" alt=""></div>
      <div class="element"><img src="https://placebear.com/160/90" alt=""></div>
      <div class="element"><img src="https://placebear.com/160/90" alt=""></div>     
    </div>
  </div>
</section>

Démo (en utilisant le CSS compilé) strong >

.section {
  width: 100%;
  display: block;
  background: red;
  box-sizing: border-box;
  padding: 40px 24px;
}
@media screen and (min-width: 600px) and (max-width: 1139px) {
  .section {
    background: orange;
    padding: 56px 48px;
  }
}
@media screen and (min-width: 1140px) {
  .section {
    padding: 64px 48px;
    background: green;
  }
}

.container {
  margin: 0 auto;
  background: rgba(244, 244, 244, 0.25);
  max-width: 599px;
}
@media screen and (min-width: 600px) and (max-width: 1139px) {
  .container {
    max-width: 1039px;
    background: rgba(244, 244, 244, 0.25);
  }
}
@media screen and (min-width: 1140px) {
  .container {
    max-width: 1032px;
    background: rgba(244, 244, 244, 0.25);
  }
}

.samba-grid {
  display: grid;
  background: inherit;
  width: 100%;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 'auto auto';
  grid-gap: 24px;
}
@media screen and (min-width: 600px) and (max-width: 1139px) {
  .samba-grid {
    grid-template-columns: repeat(6, 1fr);
    grid-gap: 48px;
  }
}
@media screen and (min-width: 1140px) {
  .samba-grid {
    grid-template-columns: repeat(12, 1fr);
    grid-gap: 48px;
  }
}

h1 {
  font-size: 52px;
}
@media screen and (min-width: 1140px) {
  h1 {
    width: calc(80% / 120 * 100);
  }
}

.element-header {
  grid-row: 1;
  grid-column-start: 1;
  grid-column-end: -1;
}

.element {
  display: grid;
  background: rgba(0, 0, 0, 0.3);
  grid-column: span 3;
}
@media screen and (min-width: 600px) and (max-width: 1139px) {
  .element {
    grid-column: span 3;
  }
}
@media screen and (min-width: 1140px) {
  .element {
    grid-column: span 4;
  }
}

.element img {
  width: 100%;
}
.element-header {
  grid-column-start: 1;
  grid-column-end: -1;
}

h1 {
  …  
  @media screen and (min-width: 1140px) {
    width: calc(80% / 120 * 100); /* 8 of 12 columns */
 }

Démo CodePen


3 commentaires

C'est un truc cool! mais je veux que l'en-tête d'élément aille à la 8ème colonne et que les éléments commencent sur la deuxième ligne et s'enroulent! J'adore l'attention que suscite cette question. J'apprends tellement!


Hé Andy, je vais probablement faire ça pour l'intérim. Cependant, consultez notre conversation temani et moi-même. La dernière ligne de grille explicite avec un comportement de grille implicite, serait cool hein? Des idées.


@MatthewHarwood Ah, ce serait très utile. CSS manque encore beaucoup de fonctionnalités. Nous n'avons même pas encore de moyen d'obtenir l'élément précédent.



0
votes

J'ajouterais un élément vide juste pour remplir l'espace pour la résolution supérieure.

Le HTML

.filler {
  display: none;

  @media screen and (min-width: 1140px) {
    grid-column: 9 / span 4;
    display: initial;
  }
}

Le CSS

<div class="element-header"><h1>I am a lot of header text that only goes 8 columsn wide</h1></div>
<div class='filler'></div>
<div class="element"><img src="https://placebear.com/160/90" alt=""></div>


1 commentaires

Désolé, je n'ai pas vu ça