Grille de carrés réactifs

170

Je me demande comment je procéderais pour créer une mise en page avec des carrés réactifs . Chaque carré aurait un contenu aligné verticalement et horizontalement . L'exemple spécifique est affiché ci-dessous ...

carrés réactifs avec contenu

garethdn
la source
Je déteste la façon dont les questions avec d'excellentes réponses sont simplement fermées au hasard par des personnes avec une vision vraiment pédante de ce à quoi devrait ressembler le stackoverflow. S'ils ont de bonnes réponses acceptées et votées ... pourquoi la fermer ??? Où est la confusion à avoir? Bien sûr, sur sa propre "grille de carrés réactifs", cela peut nécessiter un peu ou beaucoup d'explications, mais il s'agit d'une question vieille de 7 ans, 160+ avec une réponse de 400+. Je vote rouvrir.
leinaD_natipaC le

Réponses:

416

Vous pouvez créer une grille réactive de carrés avec un contenu centré verticalement et horizontalement uniquement avec CSS . Je vais vous expliquer comment dans un processus étape par étape, mais voici d'abord 2 démos de ce que vous pouvez réaliser:

Grille carrée 3x3 réactive Images carrées réactives dans une grille 3x3

Voyons maintenant comment créer ces carrés réactifs fantaisie!



1. Créer les carrés réactifs:

L'astuce pour garder les éléments carrés (ou tout autre rapport hauteur / largeur) est d'utiliser le pourcentage padding-bottom.
Note latérale: vous pouvez également utiliser un rembourrage supérieur ou une marge supérieure / inférieure mais l'arrière-plan de l'élément ne s'affichera pas.

Comme le remplissage supérieur est calculé en fonction de la largeur de l' élément parent ( voir MDN pour référence ), la hauteur de l'élément changera en fonction de sa largeur. Vous pouvez maintenant conserver ses proportions en fonction de sa largeur.
À ce stade, vous pouvez coder:

HTML :

 <div></div>

CSS

div {
    width: 30%;
    padding-bottom: 30%; /* = width for a square aspect ratio */
}

Voici un exemple de mise en page simple d' une grille de 3 * 3 carrés en utilisant le code ci-dessus.

Avec cette technique, vous pouvez faire n'importe quel autre rapport hauteur / largeur, voici un tableau donnant les valeurs de remplissage du bas en fonction du rapport hauteur / largeur et d'une largeur de 30%.

 Aspect ratio  |  padding-bottom  |  for 30% width
------------------------------------------------
    1:1        |  = width         |    30%
    1:2        |  width x 2       |    60%
    2:1        |  width x 0.5     |    15%
    4:3        |  width x 0.75    |    22.5%
    16:9       |  width x 0.5625  |    16.875%




2. Ajout de contenu à l'intérieur des carrés

Comme vous ne pouvez pas ajouter de contenu directement à l'intérieur des carrés (cela augmenterait leur hauteur et les carrés ne seraient plus des carrés), vous devez créer des éléments enfants (pour cet exemple, j'utilise des divs) à l'intérieur d'eux position: absolute;et y mettre le contenu. . Cela retirera le contenu du flux et conservera la taille du carré.

N'oubliez pas d'ajouter position:relative;les div parent afin que les enfants absolus soient positionnés / dimensionnés par rapport à leur parent.

Ajoutons du contenu à notre grille de carrés 3x3:

HTML :

<div class="square">
    <div class="content">
        .. CONTENT HERE ..
    </div>
</div>
... and so on 9 times for 9 squares ...

CSS :

.square {
    float:left;
    position: relative;
    width: 30%;
    padding-bottom: 30%; /* = width for a 1:1 aspect ratio */
    margin:1.66%;
    overflow:hidden;
}

.content {
    position:absolute;
    height:80%; /* = 100% - 2*10% padding */
    width:90%; /* = 100% - 2*5% padding */
    padding: 10% 5%;
}

RESULT <- avec un peu de mise en forme pour le rendre joli!



3. centrer le contenu

Horizontalement:

Ceci est assez facile, il vous suffit d'ajouter text-align:centerà .content.
RÉSULTAT

Alignement vertical

Cela devient sérieux! L'astuce est d'utiliser

display:table;
/* and */
display:table-cell;
vertical-align:middle;

mais nous ne pouvons pas utiliser display:table;on .squareou .contentdivs car il entre en conflit avec position:absolute;donc nous devons créer deux enfants à l'intérieur des .contentdivs. Notre code sera mis à jour comme suit:

HTML :

<div class="square">
    <div class="content">
        <div class="table">
            <div class="table-cell">
                ... CONTENT HERE ...
            </div>
        </div>
    </div>
</div>
... and so on 9 times for 9 squares ...

CSS:

.square {
    float:left;
    position: relative;
    width: 30%;
    padding-bottom : 30%; /* = width for a 1:1 aspect ratio */
    margin:1.66%;
    overflow:hidden;
}

.content {
    position:absolute;
    height:80%; /* = 100% - 2*10% padding */
    width:90%; /* = 100% - 2*5% padding */
    padding: 10% 5%;
}
.table{
    display:table;
    height:100%;
    width:100%;
}
.table-cell{
    display:table-cell;
    vertical-align:middle;
    height:100%;
    width:100%;
}




Nous avons maintenant terminé et nous pouvons jeter un œil au résultat ici:

RÉSULTAT EN PLEIN ÉCRAN EN DIRECT

violon modifiable ici


web-tiki
la source
2
@ d.raev oui. Les pourcentages de remplissage et de marge sont calculés en fonction de la largeur du parent. Vérifiez ici pour padding developer.mozilla.org/en-US/docs/Web/CSS/padding
web-tiki
4
C'est bien. Juste un * { box-sizing: border-box; }avertissement pour les autres: si vous utilisez, vous devrez ajuster la hauteur et la largeur dans le div .content à 100%. :)
Rob Flaherty
2
quel est le calcul derrière la valeur de la marge? et si je veux définir une grille 5x5?
kiwi1342
2
@ kiwi1342 la somme de toutes les marges + toute la largeur d'une ligne doit être égale à 100%. Donc, pour une grille 5x5, vous pouvez utiliser une largeur de 18% avec des marges de 1% de chaque côté des éléments.
web-tiki
1
Fantastique. Juste un avertissement: pour centrer horizontalement et verticalement, il suffit de faire du .content une flexbox avecjustify-content: center; align-items: center; flex-flow: column nowrap;
NonameSL
15

Vous pouvez utiliser des unités vw (largeur de vue), ce qui rendrait les carrés réactifs en fonction de la largeur de l'écran.

Une maquette rapide de ceci serait:

html,
body {
  margin: 0;
  padding: 0;
}
div {
  height: 25vw;
  width: 25vw;
  background: tomato;
  display: inline-block;
  text-align: center;
  line-height: 25vw;
  font-size: 20vw;
  margin-right: -4px;
  position: relative;
}
/*demo only*/

div:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: inherit;
  width: inherit;
  background: rgba(200, 200, 200, 0.6);
  transition: all 0.4s;
}
div:hover:before {
  background: rgba(200, 200, 200, 0);
}
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>

jbutler483
la source
4
Ne pas utiliser l' margin-left: -4px;utilisation margin-right:-4px. Ne jouez pas plutôt avec l'incohérence dans mincharspace mais définissez la taille de la police parent de wrapper sur 0 et que pour les éléments enfants réinitialisés à 1rem(relative-em)
Roko C.Buljan
9

La réponse acceptée est excellente, mais cela peut être fait avec flexbox.

Voici un système de grille écrit avec la syntaxe BEM qui permet d'afficher 1 à 10 colonnes par ligne.

Si la dernière ligne est incomplète (par exemple, vous choisissez d'afficher 5 cellules par ligne et il y a 7 éléments), les éléments de fin seront centrés horizontalement. Pour contrôler l'alignement horizontal des éléments de fin, modifiez simplement la justify-contentpropriété sous la .square-gridclasse.

.square-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.square-grid__cell {
  background-color: rgba(0, 0, 0, 0.03);
  box-shadow: 0 0 0 1px black;
  overflow: hidden;
  position: relative;
}

.square-grid__content {
  left: 0;
  position: absolute;
  top: 0;
}

.square-grid__cell:after {
  content: '';
  display: block;
  padding-bottom: 100%;
}

// Sizes  Number of cells per row

.square-grid__cell--10 {
  flex-basis: 10%;
}

.square-grid__cell--9 {
  flex-basis: 11.1111111%;
}

.square-grid__cell--8 {
  flex-basis: 12.5%;
}

.square-grid__cell--7 {
  flex-basis: 14.2857143%;
}

.square-grid__cell--6 {
  flex-basis: 16.6666667%;
}

.square-grid__cell--5 {
  flex-basis: 20%;
}

.square-grid__cell--4 {
  flex-basis: 25%;
}

.square-grid__cell--3 {
  flex-basis: 33.333%;
}

.square-grid__cell--2 {
  flex-basis: 50%;
}

.square-grid__cell--1 {
  flex-basis: 100%;
}

Violon: https://jsfiddle.net/patrickberkeley/noLm1r45/3/

Ceci est testé dans FF et Chrome.

Patrick Berkeley
la source
3
Pourtant, vous utilisez le fond de rembourrage pour fixer la hauteur, donc c'est en fait la même réponse que celle acceptée. La seule différence est la façon dont la grille est faite, pas la grille carrée.
extempl
0

J'utilise cette solution pour des boîtes réactives de différentes rations:

HTML:

<div class="box ratio1_1">
  <div class="box-content">
            ... CONTENT HERE ...
  </div>
</div>

CSS:

.box-content {
  width: 100%; height: 100%;
  top: 0;right: 0;bottom: 0;left: 0;
  position: absolute;
}
.box {
  position: relative;
  width: 100%;
}
.box::before {
    content: "";
    display: block;
    padding-top: 100%; /*square for no ratio*/
}
.ratio1_1::before { padding-top: 100%; }
.ratio1_2::before { padding-top: 200%; }
.ratio2_1::before { padding-top: 50%; }
.ratio4_3::before { padding-top: 75%; }
.ratio16_9::before { padding-top: 56.25%; }

Voir la démo sur JSfiddle.net

mitjajez
la source
2
il serait avantageux que vous expliquiez plus sur votre réponse ... ou même d'inclure un JSFiddle
Wavesailor