web-dev-qa-db-fra.com

Une disposition de grille avec des carrés réactifs

Je souhaite créer une disposition de grille avec des carrés réactifs.

Je pense que je devrais être capable de le faire avec la disposition de la grille CSS, mais j'ai du mal à définir la hauteur de chaque carré pour qu'elle soit égale à la largeur.

Vous avez également du mal à définir une gouttière entre chaque carré.

Serais-je mieux d'utiliser Flexbox?

Actuellement, mon code HTML ressemble à ceci, mais sera dynamique, de sorte que davantage de carrés peuvent être ajoutés. Et bien sûr, il doit être réactif et utilisera idéalement une requête multimédia pour la réduire à une colonne.

<div class="square-container">

  <div class="square">
    <div class="content">
    </div>
  </div>

  <div class="square">
    <div class="content spread">
    </div>
  </div>

  <div class="square">
    <div class="content column">
    </div>
  </div>

</div>

En utilisant la grille CSS, c'est pour autant que je suis arrivé

.square-container{
    display: grid;
    grid-template-columns: 30% 30% 30%;
    .square {

    }
}

J'ai pu aller un peu plus loin avec flexbox et j'ai pu utiliser l'espace entre les deux pour aligner les carrés avec une jolie gouttière, mais je luttais toujours pour obtenir la hauteur correspondant à la largeur de chaque carré.

Je n'ai pas pu trouver d'exemples de ce qui se faisait avec flexbox ou grid mais tous les exemples seraient également appréciés.

Merci

20
Stretch0

Le padding-bottom l'astuce est la plus utilisée pour y parvenir.

Vous pouvez le combiner avec les deux Flexbox et CSS Grid, et comme l'utilisation du pourcentage pour la marge/le remplissage donne un résultat incohérent pour les éléments flex/grid, on peut ajouter un wrapper supplémentaire, ou comme ici, en utilisant un pseudo, donc l'élément avec pourcentage n'est pas l'élément flex/grille.


Edit: Remarque, il y a une mise à jour apportée aux spécifications. , qui devrait maintenant donner un résultat cohérent lorsqu'elle est utilisée sur flex/grid articles. Sachez cependant que le problème se produit toujours sur les anciennes versions.


Remarque, si vous ajoutez du contenu à l'élément content, il doit être en position absolue pour conserver le rapport hauteur/largeur du carré.

Démo Fiddle - Flexbox

.square-container {
  display: flex;
  flex-wrap: wrap;
}

.square {
  position: relative;
  flex-basis: calc(33.333% - 10px);
  margin: 5px;
  border: 1px solid;
  box-sizing: border-box;
}

.square::before {
  content: '';
  display: block;
  padding-top: 100%;
}

.square .content {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  width: 100%;
}
<div class="square-container">

  <div class="square">
    <div class="content">
    </div>
  </div>

  <div class="square">
    <div class="content spread">
    </div>
  </div>

  <div class="square">
    <div class="content column">
    </div>
  </div>

  <div class="square">
    <div class="content spread">
    </div>
  </div>

  <div class="square">
    <div class="content column">
    </div>
  </div>

</div>

Version de la grille CSS

.square-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
  grid-gap: 10px;
}

.square {
  position: relative;
  border: 1px solid;
  box-sizing: border-box;
}

.square::before {
  content: '';
  display: block;
  padding-top: 100%;
}

.square .content {
  position: absolute;
  top: 0; left: 0;
  height: 100%;
  width: 100%;
}
<div class="square-container">

  <div class="square">
    <div class="content">
    </div>
  </div>

  <div class="square">
    <div class="content spread">
    </div>
  </div>

  <div class="square">
    <div class="content column">
    </div>
  </div>

  <div class="square">
    <div class="content spread">
    </div>
  </div>

  <div class="square">
    <div class="content column">
    </div>
  </div>

</div>
18
LGSon

Essayez d'utiliser unités de pourcentage de la fenêtre d'affichage.

jsFiddle

.square-container {
  display: grid;
  grid-template-columns: repeat(3, 30vw);
  grid-template-rows: 30vw;
  grid-gap: 2.5vw;
  padding: 2.5vw;
  background-color: gray;
}

.square {
  background-color: lightgreen;
}

body {
  margin: 0; /* remove default margins */
}
<div class="square-container">
  <div class="square">
    <div class="content"></div>
  </div>
  <div class="square">
    <div class="content spread"></div>
  </div>
  <div class="square">
    <div class="content column"></div>
  </div>
</div>

De la spécification:

5.1.2. Longueurs en pourcentage de la fenêtre: vw, vh, vmin, vmax unités

Les longueurs en pourcentage de la fenêtre sont relatives à la taille du bloc contenant initial. Lorsque la hauteur ou la largeur du bloc contenant initial est modifiée, elles sont mises à l'échelle en conséquence.

  • vw unit - Égal à 1% de la largeur du bloc contenant initial.
  • vh unit - Égal à 1% de la hauteur du bloc contenant initial.
  • Unité vmin - Égal au plus petit de vw ou vh.
  • Unité vmax - Égal au plus grand de vw ou vh.
9
Michael_B

Vous pouvez utiliser le fait que - padding est calculé en fonction de la largeur et défini padding-top: 100% directement au square éléments de la grille (les éléments de la grille seraient désormais carrés).


Mise à jour 2019

Notez que pour éléments flexibles ainsi que éléments de grille plus tôt, cela ne fonctionnait pas - voir le message lié dans les commentaires à cette réponse:

Maintenant qu'il existe un consensus entre les navigateurs (versions plus récentes) pour avoir le même comportement pour padding pour éléments flexibles et éléments de grille, vous peut utiliser cette solution.

Voir la démo ci-dessous:

.square-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(30%, 1fr));
  grid-gap: 10px;
}

.square {
  background: cadetblue;
  padding-top: 100%; /* padding trick directly on the grid item */
  box-sizing: border-box;
  position: relative;
}

.square .content { /* absolutely positioned */
  position: absolute;
  top: 0;
  right:0;
  left: 0;
  bottom: 0;
}
<div class="square-container">
  <div class="square">
    <div class="content"> some content here</div>
  </div>
  <div class="square">
    <div class="content"> some content here</div>
  </div>
  <div class="square">
    <div class="content"> some content here</div>
  </div>
  <div class="square">
    <div class="content"> some content here</div>
  </div>
  <div class="square">
    <div class="content column">some content here and there is a lot of text here</div>
  </div>
  <div class="square">
    <div class="content spread">text</div>
  </div>
  <div class="square">
    <div class="content column">some text here</div>
  </div>
</div>
2
kukkuz