web-dev-qa-db-fra.com

CSS flottantes à hauteur variable

J'ai un nombre infini de divs d'une largeur de 100px, ce qui peut tenir dans un parent de largeur 250px. Indépendamment de la hauteur, j'ai besoin que les divs soient affichés en rangées, comme indiqué dans l'image. J'ai essayé de résoudre cela, mais la hauteur de la div semble être en train de gâcher.

enter image description here

J'apprécierais vraiment votre aide. Merci :)

        <style>
            #holder{
            width:250px;
            border:1px dotted blue;
            display:inline-block;
        }
        .box{
            width:100px;
            height:150px;
            background-color:#CCC;
            float:left;
            text-align:center;
            font-size:45px;
            display:inline-block;
        }
        .one{
            background-color:#0F0;
            height:200px;
        }

        .two{
            background-color:#0FF;
        }

        .three{
            background-color:#00F;
        }

        .four{
            background-color:#FF0;
        }
    </style>

    <div id="holder">
        <div class="box one">1</div>
        <div class="box two">2</div>
        <div class="box three">3</div>
        <div class="box four">4</div>
    </div>

Voici le jsfiddle

Voici ce que j'ai fait et réalisé en utilisant javascript https://jsfiddle.net/8o0nwft9/

81
stevenmc

À ma connaissance, il n’existe aucun moyen de résoudre ce problème avec du CSS pur (qui fonctionne dans tous les navigateurs courants):

  • Flotteurs ne fonctionne pas .
  • display: inline-blockne fonctionne pas .
  • position: relative avec position: absolute nécessite réglage manuel du pixel . Si vous utilisez un langage côté serveur et que vous travaillez avec des images (ou quelque chose dont la hauteur est prévisible), vous pouvez gérer le réglage des pixels "automatiquement" avec un code côté serveur.

Au lieu de cela, utilisez jQuery Masonry .

67
thirtydot

en supposant que vos besoins ressemblent davantage à votre code d'exemple coloré, puis:

.box:nth-child(odd){
    clear:both;
}

s'il doit y avoir 3 lignes, alors nth-child(3n+1)

37
FatherStorm

Je donne cette réponse car même s’il existe de bonnes solutions offrant une solution ( avec la maçonnerie ), on ne sait toujours pas très bien pourquoi il est impossible d’y parvenir en utilisant des flotteurs.

(ceci est important - # 1 ).

Un élément flottant se déplacera aussi loin que possible à gauche ou à droite à la position où il se trouvait initialement

Donc, exprimez-le de cette façon:

Nous avons 2 div

<div class="div5">div5</div>
<div class="div6">div6</div>

.div-blue{
    width:100px;
    height:100px;
    background: blue;
}

.div-red{
    width:50px;
    height:50px;
    background: red;
}

sans float ils seront l'un en dessous de l'autre

enter image description here

Si nous float: right le div5, le div6 est positionné sur la ligne où le div5 était ,

/*the lines are just for illustrate*/

enter image description here

Donc, si maintenant nous float: left le div6 il se déplacera aussi loin que possible à gauche, " dans cette ligne " (voir n ° 1 ci-dessus), donc si div5 change sa ligne, div6 le suivra.

Ajoutons maintenant d'autres div dans l'équation

<div class="div4">div4</div>
<div class="div5">div5</div>
<div class="div6">div6</div>

.div-gree{
    width:150px;
    height:150px;
    background: green;

    float:right;
}

Nous avons ceci

enter image description here

Si nous définissons clear: right au div5, nous le forçons à prendre la ligne ci-dessous div4

enter image description here

et div6 flottera dans cette nouvelle ligne à droite ou à gauche.

Utilisons maintenant comme exemple la question qui m’a amené ici à cause d’un doublon Forcer la pile de div de gauche à droite

Voici l'extrait pour le tester:

div{
    width:24%;
    margin-right: 1%;
    float: left;
    margin-top:5px;
    color: #fff;
    font-size: 24px;
    text-align: center;
}

.one{
    background-color:red;
    height: 50px;
}

.two{
    background-color:green;
    height:40px;
}

.three{
    background-color:orange;
    height:55px;
}

.four{
    background-color:Magenta;
    height:25px;
}

.five{
    background-color:black;
    height:55px;
}
<div class="one">1</div>
<div class="two">2</div>
<div class="three">3</div>
<div class="four">4</div>
<div class="five">5</div>

<div class="one">1*</div>
<div class="three">2*</div>
<div class="four">3*</div>
<div class="two">4*</div>
<div class="five">5*</div>

enter image description here

Dans l'image ci-dessus, vous pouvez voir comment div.5 est stocké juste à côté de div.3 c'est parce que dans sa ligne (définie par la case de ligne de div.4) c'est aussi loin que ça peut aller, div.1*, div.2*, etc, flottent également à gauche de div.5 mais comme ils ne rentrent pas dans cette ligne, ils vont à la ligne ci-dessous (définie par la case de ligne de div.5)

Notez maintenant que lorsque nous réduisons la hauteur de div.2* assez pour être inférieur à div.4* comment il a laissé passer à div.5*:

enter image description here

J'espère que cela aide à préciser pourquoi cela ne peut pas être réalisé avec des flotteurs. Je clarifie seulement en utilisant floats (pas inline-block) à cause du titre " Divs flottantes CSS à hauteur variable" et parce que la réponse est assez longue pour le moment.

35
Yandy_Viera

Comme cela a été souligné à juste titre, cela est impossible avec CSS seul ... heureusement, j'ai maintenant trouvé une solution dans http://isotope.metafizzy.co/

Cela semble résoudre complètement le problème.

8
stevenmc

Avec un peu d'aide de ce commentaire ( CSS Block float left ), j'ai trouvé la réponse.

Sur chaque "ligne" que je crée, j'ajoute un nom de classe left.
Sur chaque "rangée" que je crée, j'ajoute un nom de classe right.

Ensuite, je flotte à gauche et flotte à droite pour chacun de ces noms de classe!

La seule complication est que mon ordre de contenu est inversé sur les "bonnes" lignes, mais cela peut être résolu avec PHP.

Merci pour votre aide les gens!

#holder{
  width:200px;
  border:1px dotted blue;
  display:inline-block;
}
.box{
  width:100px;
  height:150px;
  background-color:#CCC;
  float:left;
  text-align:center;
  font-size:45px;
}
.one{
  background-color:#0F0;
  height:200px;
}

.two{
  background-color:#0FF;
}

.three{
  background-color:#00F;
  float:right;
}

.four{
  background-color:#FF0;
  float:right;
}
.left{float:left;}
.right{float:right;}
<div id="holder">
  <div class="box one left">1</div>
  <div class="box two left">2</div>
  <div class="box four right">4</div>
  <div class="box three right">3</div>
</div>
</body>
3
stevenmc

Grâce à Thirtydot, j'ai réalisé que ma réponse précédente ne résolvait pas correctement le problème. Voici ma deuxième tentative, qui utilise JQuery en tant que solution uniquement CSS semble impossible:

<html>
    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
        <script type="text/javascript" language="javascript">
            $(document).ready(function() {
                var numberOfColumns = 3;
                var numberOfColumnsPlusOne = numberOfColumns+1;
                var marginBottom = 10;  //Top and bottom margins added
                var kids = $('#holder:first-child').children();
                var add;
                $.each(kids, function(key, value) {
                    add = numberOfColumnsPlusOne+key;
                    if (add <= kids.length){
                        $('#holder:first-child :nth-child('+(numberOfColumnsPlusOne+key)+')').offset({ top: $('#holder:first-child :nth-child('+(key+1)+')').offset().top+$('#holder:first-child :nth-child('+(key+1)+')').height()+marginBottom });
                    }
                });
            });             
        </script>
        <style>
            #holder{
                width:270px;
                border:1px dotted blue;
                display:inline-block; /* Enables the holder to hold floated elements (look at dotted blue line with and without */
            }
            .box{
                width:80px;
                height:150px;
                background-color:#CCC;
                margin:5px;
                text-align:center;
                font-size:45px;
            }
            .one{
                height:86px;
            }
            .two{
                height:130px;
            }
            .three{
                height:60px;
            }
            .four{
                clear:both;
                height:107px;
            }
            .five{
                height:89px;
            }
            .six{
                height:89px;
            }
            .left{float:left;}
            .right{float:right;}
        </style>
    </head>
    <body>      
        <div id="holder">
            <div class="box one left">1</div>
            <div class="box two left">2</div>
            <div class="box three left">3</div>
            <div class="box four left">4</div>
            <div class="box five left">5</div>
            <div class="box six left">6</div>
        </div>
    </body>
</body>

Le seul problème qui reste à ma solution est ce qui se passe quand une boîte a deux largeurs de boîte au lieu d'une seule. Je travaille toujours sur cette solution. Je posterai quand complet.

1
stevenmc

Si quelqu'un cherche encore des alternatives, en voici une. Essayez d’utiliser la propriété (-moz -/- webkit-) column-width. Il prend en charge le problème de hauteur variable div. Cependant, largeur de colonne ajoute un nouveau div à la fin de la colonne.

Sinon, la maçonnerie jQuery fonctionne mieux.

1
rodiwa

Ce n'est peut-être pas la solution exacte pour tout le monde mais je trouve que (littéralement) sortir des sentiers battus fonctionne dans de nombreux cas: au lieu d'afficher les cases de gauche à droite, vous pouvez souvent remplir la colonne de gauche en premier, puis allez au milieu, remplissez cela avec des cases et finalement remplissez la colonne de droite avec des cases. Votre image serait alors:

order of filling :

Si vous utilisez un langage de script tel que php, vous pouvez également remplir les colonnes de gauche à droite en y ajoutant une nouvelle zone et en les affichant lorsque toutes les colonnes sont remplies. par exemple (code php non testé):

$col1 = '<div class="col1"> <div>box1</div>';
$col2 = '<div class="col2"> <div>box2</div>';
$col3 = '<div class="col3"> <div>box3</div>';
$col1 .= '<div>box4</div> </div>'; //last </div> closes the col1 div
$col2 .= '<div>box5</div> </div>';
$col3 .= '<div>box6</div> </div>';
echo $col1.$col2.$col3;

$ col1, $ col2 et $ col3 peuvent avoir des valeurs float: left et width: 33%, définissez les cases situées à l'intérieur de la div en largeur et sans flottement.

Évidemment, si vous utilisez javascript/jquery pour charger les boîtes dynamiquement, il vaut mieux les styler de cette façon aussi, comme expliqué dans d'autres réponses à ce fil.

0
bolvo