web-dev-qa-db-fra.com

Aligné à gauche sur la dernière ligne de la grille centrée

J'ai un tas de blocs de même taille définis à display:inline-block à l'intérieur d'un div qui a text-align:center défini pour aligner les blocs. 

|        _____   _____   _____   _____       |
|       |     | |     | |     | |     |      |
|       |  1  | |  2  | |  3  | |  4  |      |
|       |_____| |_____| |_____| |_____|      |
|        _____   _____   _____   _____       |
|       |     | |     | |     | |     |      |
|       |  5  | |  6  | |  7  | |  8  |      |
|       |_____| |_____| |_____| |_____|      |
|                                            |

Les blocs remplissent la division horizontalement et, à mesure que la fenêtre du navigateur se réduit, certains blocs se cassent en nouvelles lignes, créant ainsi plus de lignes et moins de colonnes. Je veux que tout reste toujours centré, avec la dernière rangée alignée à gauche, comme ceci: 

|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  1  | |  2  | |  3  |       |
|       |_____| |_____| |_____|       |
|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  4  | |  5  | |  6  |       |
|       |_____| |_____| |_____|       |
|        _____   _____                |
|       |     | |     |               |
|       |  7  | |  8  |               |
|       |_____| |_____|               |
|                                     |

Ce qui se passe actuellement est la suivante:

|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  1  | |  2  | |  3  |       |
|       |_____| |_____| |_____|       |
|        _____   _____   _____        |
|       |     | |     | |     |       |
|       |  4  | |  5  | |  6  |       |
|       |_____| |_____| |_____|       |
|            _____   _____            |
|           |     | |     |           |
|           |  7  | |  8  |           |
|           |_____| |_____|           |
|                                     |

Je ne peux pas ajouter de divs de remplissage supplémentaires comme une suggestion, car il pourrait y avoir un nombre quelconque de blocs et le nombre de lignes et de colonnes varie en fonction de la largeur du navigateur. Je ne peux pas non plus appeler directement le bloc 7 pour la même raison. Les blocs doivent toujours rester centrés quel que soit le nombre de colonnes. 

Voici un stylo pour mieux démontrer:

http://codepen.io/anon/pen/IDsxn

Est-ce possible? Je pense que ça devrait l'être. Je préférerais ne pas utiliser flexbox car c'est seulement ie10 +, et je voudrais ie9 +. J'aimerais vraiment une solution CSS pure, mais si vous me dites que JS est le seul moyen, j'aimerais voir cela en action.

Pour référence - des questions similaires, bien qu'aucune n'ait été expliquée à fond:

Comment aligner la dernière ligne/gauche dans une flexbox à plusieurs lignes

CSS - Aligner à gauche la dernière ligne d'images dans un div centré

Correction du centrage de la dernière ligne d'éléments dans la grille du conteneur de fluide pour qu'elle reste alignée pendant que le conteneur reste centré

Centrer plusieurs blocs en ligne avec CSS et aligner la dernière ligne à gauche

46
Ivan Durst

Voici une solution JavaScript très simple (et quelques modifications mineures dans votre CSS):

http://jsfiddle.net/ha68t/

Cela fonctionne bien pour moi.

CSS:

.container {
  margin: 0 auto;
  max-width:960px;
  background-color: gold;
}

.block {
  background-color: #ddd;
  border:1px solid #999;
  display: block;
  float: left;
  height: 100px;
  margin: 4px 2px;
  width: 100px;
}

JavaScript:

$(document).ready(function(){
    setContainerWidth();
});

$(window).resize(function(){
   setContainerWidth();
});

function setContainerWidth()
{
    $('.container').css('width', 'auto'); //reset
    var windowWidth = $(document).width();
    var blockWidth = $('.block').outerWidth(true);
    var maxBoxPerRow = Math.floor(windowWidth / blockWidth);
    $('.container').width(maxBoxPerRow * blockWidth);
}

jQuery est obligatoire :)

12
mahega

Solution avec écran inline-block

Cette grille adaptive est beaucoup plus simple: moins de balisage et moins de CSS, ce qui facilite son implémentation sur un site de production et son adaptation à vos besoins.

= >> DEMO << = (redimensionne la fenêtre de résultat pour voir l'effet)

html, body {
    margin:0;
    padding:0;
}
#container{
    font-size:0;
    margin:0 auto;
    width:1000px;
}
.block {
    font-size:20px;
    width: 150px;
    height: 150px;
    margin:25px;
    background: gold;
    display:inline-block;
}

@media screen and (max-width: 430px) {
    #container{
        width:200px;
    }
}

@media screen and (min-width: 431px) and (max-width: 630px) {
   #container{
        width:400px;
    }
}
@media screen and (min-width: 631px) and (max-width: 830px) {
   #container{
        width:600px;
    }
}
@media screen and (min-width: 831px) and (max-width: 1030px) {
   #container{
        width:800px;
    }
}
<div id="container">
    <div class="block">1</div>
    <div class="block">2</div>
    <div class="block">3</div>
    <div class="block">4</div>
    <div class="block">5</div>
    <div class="block">6</div>
    <div class="block">7</div>
    <div class="block">8</div>
    <div class="block">9</div>
    <div class="block">10</div>
    <div class="block">11</div>
    <div class="block">12</div>
    <div class="block">13</div>
</div>

Ça implique :

  1. 4 requêtes de support pour des blocs de 200 pixels de large et un conteneur extensible jusqu'à 1 000 pixels. En fonction de la largeur de vos éléments de grille et de la largeur totale de votre conteneur, vous devrez peut-être en faire plus ou plus.

  2. suppression des espaces blancs entre les éléments inline-block (dans la démonstration suivante, j'ai utilisé la technique de la taille de la police mais vous pouvez en utiliser d'autres (voir Comment supprimer l'espace entre les éléments inline-block? for other techniques)

  3. marges fixes entre blocs

Le nombre de blocs d'une ligne s'adapte à la taille du conteneur. La propriété text-align reste à la valeur par défaut left de sorte que les derniers éléments soient alignés à gauche.


Flotteurs avec marges adaptatives entre les blocs et le conteneur

= >> DEMO << = (vous devez redimensionner la fenêtre de résultat sous 750px pour la voir en action)

html, body {
    margin:0;
    padding:0;
    min-width:150px;
}
.wrap {
    float:left;
    position:relative;
}
.foto {
    width: 150px;
    height: 150px;
    background: gold;
    position:absolute;
}

#warning{display:none;}
@media screen and (min-width: 631px) {
    .wrap {
        width:20%;
        padding-bottom:25%;
    }
    .wrap:nth-child(4n+2), .wrap:nth-child(4n+3){
        
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-30px;
    }
    .wrap:nth-child(4n+2){
        margin:0 5% 0 7.5%;
    }
    .wrap:nth-child(4n+3){
     margin-right:7.5%;
    }
    .wrap:nth-child(4n+2) .foto{
        left:50%;
        margin-left:-75px;
    }
    .wrap:nth-child(4n+3) .foto{
        right:50%;
        margin-right:-75px;
    }
    .wrap:nth-child(4n) .foto{
        left:-30px;
    }   
    #container{
        margin-top:-45px;
    }
}

@media screen and (min-width: 481px) and (max-width: 631px) {
    .wrap {
        width:25%;
        padding-bottom:33.3%;
    }
    .wrap:nth-child(3n+2){
        margin:0 12.5%;        
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-37px;
    }
     .wrap:nth-child(3n+2) .foto{
        left:50%;
        margin-left:-75px;
    }
     .wrap:nth-child(3n) .foto{
        left:-37px;
    }
    #container{
        margin-top:-37px;
    }
}


@media screen and (min-width: 331px) and (max-width: 480px) {
    .wrap {
        width:33.3%;
        padding-bottom:50%;
        clear:left;
    }
    .wrap:nth-child(even) {
        float:right;
        clear:right;
    }
    .wrap .foto {
        top:-75px;
        margin-top:100%;
        right:-50px;
    }
    .wrap:nth-child(even) .foto {
        left:-50px;
    }
    .wrap:nth-child(4n+3) .foto, .wrap:nth-child(4n+4) .foto {
        bottom:-75px;
        margin-bottom:100%;
    }
    #container{
        margin-top:-25px;
    }
}


@media screen and (max-width: 330px) {
    .wrap {
        width:50%;
        padding-bottom:100%;
        clear:left;
    }
    .wrap:nth-child(odd) .foto {
        right:-75px;
        bottom:0;
        bottom:-75px;
        margin-bottom:100%;
    }
    .wrap:nth-child(even) .foto {
        top:0px;
        right:-75px;
        top:-75px;
        margin-top:100%;
    }
}

@media screen and (min-width: 751px) {
    #warning{
        color:#fff;
        display:block;
        position:fixed;
        width:100%;
        height:50%;
        top:25%;
        left:0;
        background:#000;
        text-align:center;
        font-size:30px;
}
<div id="container">
    <div class="wrap"><div class="foto">1</div></div>
    <div class="wrap"><div class="foto">2</div></div>
    <div class="wrap"><div class="foto">3</div></div>
    <div class="wrap"><div class="foto">4</div></div>
    <div class="wrap"><div class="foto">5</div></div>
    <div class="wrap"><div class="foto">6</div></div>
    <div class="wrap"><div class="foto">7</div></div>
    <div class="wrap"><div class="foto">8</div></div>
    <div class="wrap"><div class="foto">9</div></div>
    <div class="wrap"><div class="foto">10</div></div>
    <div class="wrap"><div class="foto">11</div></div>
    <div class="wrap"><div class="foto">12</div></div>
    <div class="wrap"><div class="foto">13</div></div>
    <div class="wrap"><div class="foto">14</div></div>
    <div class="wrap"><div class="foto">15</div></div>
</div>

<!-- FOLLOWING JUST FOR THE DEMO -->
<div id="warning">I haven't written the code for windows bigger than 751px.<br/>
    You must resize this window under 751px.</div>

Cette technique implique:

  1. des flotteurs
  2. position:absolute;
  3. :nt-child() css selector
  4. questions des médias

Il centre les blocs dans leur conteneur et donne la même marge en haut/gauche/serré/bas de tous les blocs + côtés du conteneur. Comme cette solution utilise des éléments flottants, la dernière ligne est alignée à gauche.

Le nombre de blocs d'une ligne s'adapte à la largeur de la fenêtre.

16
web-tiki

Pour ce que ça vaut: Nous sommes maintenant en 2017 et le module d'agencement de la grille le fait immédiatement.

* {
    margin:0;
    padding:0;
}

.container {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  grid-gap: 10px;
  justify-content: center;
  align-content: flex-start;
  margin: 0 auto;
  text-align: center;
  margin-top: 10px;
}
.block {
  background-color: #ddd;
  border: 1px solid #999;
  height: 100px;
  width: 100px;
}
<div class="container">
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
  <div class="block">Foo</div>
</div>

((Démo de Codepen)) .

Si le support du navigateur vous convient, utilisez la grille. Si non, alors lisez la suite ....


Comme mentionné dans la réponse de @ Web-tiki, le mieux que vous puissiez faire avec CSS est une série de requêtes multimédia.

Cela étant dit, si vous utilisez un préprocesseur tel que LESS, la tâche n'est pas si difficile ni sujette aux erreurs. (bien que, oui, le CSS sera toujours long et moche)

CODEPEN MIS &AGRAVE; JOUR (Redimensionne la fenêtre pour voir les résultats)

Voici comment tirer parti de MOINS pour configurer les requêtes multimédia:

Commencez par définir quelques variables en fonction du modèle dont vous avez besoin:

@item-width:100px;
@item-height:100px;
@marginV: 4px;
@marginH: 2px;
@min-cols:2;
@max-cols:9; //set an upper limit of how may columns you want to write the media queries for

Ensuite:

Configurez un mix d'itération comme ceci: (Vous pouvez coller ce code dans http://less2css.org )

.loopingClass (@index-width) when (@index-width <= @item-width * @max-cols) {
    @media (min-width:@index-width) {
        .container{
            width: @index-width;
        }
    }

    .loopingClass(@index-width + @item-width + 2*@marginH);
}

.loopingClass (@item-width * @min-cols + @min-cols*@marginH*2);

Le mixin ci-dessus va cracher une série de requêtes médiatiques sous la forme:

@media (min-width: 208px) {
  .container {
    width: 208px;
  }
}
@media (min-width: 312px) {
  .container {
    width: 312px;
  }
}
@media (min-width: 416px) {
  .container {
    width: 416px;
  }
}
@media (min-width: 520px) {
  .container {
    width: 520px;
  }
}
@media (min-width: 624px) {
  .container {
    width: 624px;
  }
}
@media (min-width: 728px) {
  .container {
    width: 728px;
  }
}
@media (min-width: 832px) {
  .container {
    width: 832px;
  }
}

Avec les CSS restants (MOINS):

.container {
  margin: 0 auto;
  text-align: center;
  overflow: auto;
    min-width: @min-cols * @item-width;
    max-width: @max-cols * @item-width;
    display: block;
    list-style:none;
}
.block {
  background-color: #ddd;
  border:1px solid #999;
  box-sizing:border-box;
  float: left;
  height: @item-height;
  width: @item-width;
  margin:@marginV @marginH;
}

... vous obtenez le résultat souhaité. 

... et il est très facile de personnaliser la mise en page:

Tout ce que je dois faire est de changer les variables que j'ai utilisées dans le mixin LESS en fonction de mes besoins - je reçois la mise en page exacte que je suis après.

9
Danield

Avec flexbox, quelques pseudo-éléments, une div supplémentaire, et après beaucoup de frustration, j'ai pu y parvenir sans interrogation de média (étant donné que je devais insérer ma grille dans de nombreux éléments de tailles différentes, les requêtes de média ne fonctionneraient pas vraiment pour moi). . 

Une mise en garde: les gouttières entre les articles sont fluides.

Démo: http://codepen.io/anon/pen/OXvxEW

CSS:

.wrapper {
    display: flex;
    flex-wrap: wrap;
    border: 2px solid #ffc0cb;
    max-width: 1100px;
    margin: 0.5rem auto;
    justify-content: center;
}

.wrapper:after {
    content: ' ';
    flex: 1;
    height: 100%;
    border: 1px solid #00f;
    margin: 0.5rem;
}

.child {
    flex: 1;
    border: 2px solid #ffa500;
    min-width: 300px;
    margin: 0.5rem;
    text-align: center;
}

.child-contents {
    width: 300px;
    border: 2px solid #008000;
    height: 100px;
    margin: 0 auto;
}

HTML:

<div class='wrapper'>
    <div class='child'>
        <div class='child-contents'></div>
    </div>
    <div class='child'>
        <div class='child-contents'></div>
    </div>
    <div class='child'>
        <div class='child-contents'></div>
    </div>

    ...etc., more .child's...

</div>

Le résultat final est quelque chose comme ceci, où les rectangles verts sont divs. Les bordures rose/orange sont juste pour référence afin que vous puissiez voir ce qui se passe. Si vous supprimez les bordures rose/orange, vous devriez obtenir la grille que vous recherchez (encore une fois, notez que les gouttières sont fluides).

 enter image description here

2
Nick Budden

À ce jour, la seule solution propre à cet égard est la

Module de disposition de grille CSS ( Démo Codepen )

Fondamentalement, le code pertinent nécessaire se résume à ceci:

ul {
  display: grid; /* (1) */
  grid-template-columns: repeat(auto-fill, 120px); /* (2) */
  grid-gap: 1rem; /* (3) */
  justify-content: center; /* (4) */
  align-content: flex-start; /* (5) */
}

1) Faire de l’élément conteneur un conteneur de grille

2) Définissez la grille avec une quantité 'auto' de colonnes de largeur 120px. (La valeur de remplissage automatique est utilisée pour les mises en page réactives).

3) Définissez les espaces/gouttières pour les lignes et les colonnes de la grille.

4) et 5) - Similaire à la flexbox.

body {
  margin: 0;
}
ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, 120px);
  grid-gap: 1rem;
  justify-content: center;
  align-content: flex-start;
  
  /* boring properties: */
  list-style: none;
  width: 90vw;
  height: 90vh;
  margin: 2vh auto;
  border: 5px solid green;
  padding: 0;
  overflow: auto;
}
li {
  background: tomato;
  height: 120px;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
</ul>

Démo Codepen (Redimensionner pour voir l'effet)


Support de navigateur - Caniuse

Actuellement pris en charge par Chrome (Blink) et Firefox, avec prise en charge partielle de IE et Edge (voir cet article de Rachel Andrew) 


Lectures complémentaires sur les grilles CSS:

1
Danield

Utilisez flexbox:

.container {
  display: -webkit-flex;
   display: flex;
   -webkit-flex-direction: row; 
   flex-direction: row;
   -webkit-justify-content: flex-start;
   justify-content: flex-start;
   flex-wrap:wrap;
}

.block {
  background-color: #ddd;
  border:1px solid #999;
  display: inline-block;
  height: 100px;
  margin: 4px 2px;
  width: 100px;
}

Terminé.

1
hawkeye126

Il n’existe pas de solution "normale" à votre problème, mais uniquement les "solutions de contournement" mentionnées. 

La situation est la suivante: votre conteneur de blocs remplira l’espace disponible jusqu’au maximum disponible/configuration, puis cassera tous les blocs internes à la ligne suivante, ce qui entraînera un débordement du conteneur. Également avec d'autres configurations comme flottante, le comportement sera le même. C’est ainsi que fonctionne le rendu - chaque fois qu’il est gourmand dans l’espace pour calculer le comportement des éléments internes.

Peut-être que l'avenir Flexboxes rendra cela possible - mais je n'ai pas lu toutes les spécifications. Juste une supposition ...

0
Möhre

Essayez ceci avec un simple css:

CSS:

.row {text-align: center; taille de la police: 0;} . block {text-align: center; affichage: bloc en ligne; largeur: 150px; hauteur: 15px; marge: 5px; bordure: 1px solide #dddddd; taille de la police: 13px;}

HTML:

<div class="row">
  <div class="block"></div> 
</div>

.row{text-align:center;font-size:0;}
    .block{text-align:center;display:inline-block;width:150px;height:150px;margin:5px; border:1px solid #dddddd;font-size:13px;line-height:150px;}
<div class="row">
      <div class="block">1</div> 
      <div class="block">2</div> 
      <div class="block">3</div> 
      <div class="block">4</div> 
      <div class="block">5</div> 
      <div class="block">6</div> 
      <div class="block">7</div> 
      <div class="block">8</div> 
    </div>

0
Rakesh Vadnal