Плавающие блоки CSS с переменной высотой

У меня есть бесконечное количество div шириной 100 пикселей, которые могут поместиться в родительский элемент шириной 250 пикселей. Независимо от высоты, мне нужно, чтобы блоки отображались в строках, как показано на изображении. Я попытался решить эту проблему, но высота div, похоже, испортила.

введите описание изображения здесь

Буду очень признателен за вашу помощь. Спасибо :)

        <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>

Вот jsfiddle

Вот что я сделал и чего добился с помощью javascript https://jsfiddle.net/8o0nwft9/


person stevenmc    schedule 08.03.2011    source источник
comment
как насчет столбца CSS? , содержимое распространяется от столбца к следующему jsfiddle.net/XFX55/90   -  person G-Cyrillus    schedule 15.01.2016


Ответы (10)


Насколько мне известно, нет способа решить эту проблему с помощью чистого CSS (который работает во всех распространенных браузерах):

  • Поплавки не работают.
  • display: inline-block не работает.
  • position: relative с position: absolute требует ручной настройки пикселей. Если вы используете серверный язык и работаете с изображениями (или чем-то с предсказуемой высотой), вы можете выполнять настройку пикселей «автоматически» с помощью серверного кода.

Вместо этого используйте jQuery Masonry.

person thirtydot    schedule 08.03.2011
comment
@stevenmc: Нет проблем, но вы определенно не нашли решения заданного вами вопроса: "I have infinite number of divs of a 100px width, which can fit into a 250px width parent. Regardless of height, I need the divs to be displayed in rows, as shown in the image.". - person thirtydot; 08.03.2011
comment
В настоящее время это вполне разумно сделать с помощью столбцов CSS, например: w3bits.com/css-masonry - person thirtydot; 07.08.2017
comment
Столбцы CSS не решат проблему полностью, если выравнивание должно происходить, как указано выше. Столбцы CSS приведут к макету, в котором столбец 1 будет содержать элементы 1,2,3, а столбец 2 - элементы 4,5,6. - person Stefan Müller; 06.10.2017
comment
Можно ли сделать то же самое с помощью flexbox? - person iChido; 24.10.2018
comment
@iChido: Я не думаю, что flexbox помогает решить эту проблему, но я не уверен. Я давно не пробовал делать это только с помощью CSS, я всегда использую JavaScript, потому что он просто работает. Библиотека Masonry в моем ответе больше даже не полагается на jQuery. Может ли это сделать только CSS, зависит от ваших конкретных требований. - person thirtydot; 24.10.2018

при условии, что ваши потребности больше похожи на ваш цветной пример кода, тогда:

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

если это будет 3 строки, тогда nth-child(3n+1)

person FatherStorm    schedule 08.03.2011
comment
Я не хочу ничего уточнять. - person stevenmc; 08.03.2011
comment
Это лучшее работающее решение css. - person superluminary; 30.11.2012
comment
Это решило мою проблему, поскольку мне действительно нужен был другой макет, но на самом деле это не ответ на этот вопрос SO. Изменить: PS: Нет поддержки ie8 для nth-child. - person Eirik H; 16.12.2013
comment
У меня было 2 столбца, для меня это было лучшее решение :) - person Ruub; 19.01.2015
comment
Пример этого можно найти здесь (для 3 столбцов) codepen.io/anon/pen/dPZvbb - person veganista; 06.02.2015
comment
Это полностью решило мою проблему. Интересно, почему это не работает у других парней - person Michael Walter; 05.09.2015
comment
Отлично, спасибо, что поделились! - person Marc Ruef; 06.03.2018

Я даю этот ответ, потому что даже если есть хорошие, которые предлагают решение (с использованием масонства), все еще не Совершенно непонятно, почему этого нельзя добиться с помощью поплавков.

(это важно - №1).

Плавающий элемент переместится как можно дальше влево или вправо в том положении, в котором он был изначально

Так что скажите это так:

У нас есть 2 див

<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;
}

без float они будут один под другим

введите описание изображения здесь

Если мы float: right div5, div6 расположится на линии, где был div5,

/*the lines are just for illustrate*/

введите описание изображения здесь

Итак, если теперь мы float: left div6, он переместится как можно дальше влево, «в этой строке» (см. №1 выше), поэтому, если div5 изменит свою строку, div6 последует за ней.

Теперь добавим еще один div в уравнение

<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;
}

У нас есть это

введите описание изображения здесь

Если мы установим clear: right в div5, мы заставим его принять строку ниже div4

введите описание изображения здесь

и div6 будет плавать в этой новой строке вправо или влево.

Теперь давайте используем в качестве примера вопрос, который привел меня сюда из-за повторяющегося принуждения стек слева направо

Вот фрагмент для проверки:

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>

введите описание изображения здесь

На изображении выше вы можете увидеть, как div.5 хранится рядом с div.3, потому что в его строке (определяемой полем строки div.4), которая находится максимально далеко, div.1*, div.2* и т. Д. Также плавают слева от div.5, но поскольку они не помещаются в эту строку, они переходят к строке ниже (определяется рамкой строки div.5)

Теперь обратите внимание, что когда мы уменьшаем высоту div.2* настолько, чтобы она была меньше div.4*, как она передается до div.5*:

введите описание изображения здесь

Надеюсь, это поможет прояснить, почему этого нельзя достичь с помощью поплавков. Я поясняю использование float (а не inline-block) только из-за заголовка «CSS Floating Divs At Variable Heights» и потому, что сейчас ответ довольно длинный.

person Yandy_Viera    schedule 20.08.2015
comment
Это блестящее и ясное объяснение, и оно действительно заслуживает большего одобрения. - person Immutable Brick; 18.09.2015

Как было правильно указано, это невозможно только с помощью CSS ... к счастью, теперь я нашел решение в http://isotope.metafizzy.co/

Вроде решает проблему полностью.

person stevenmc    schedule 04.05.2011
comment
Я действительно думаю, что вы должны были дать этот ответ @thirtydot - он / она предложил использовать масонство, которое является единственным способом добиться этого. Изотоп - это (добровольно) оплачиваемая версия масонства, созданная одним и тем же человеком. - person iamkeir; 17.09.2012
comment
Согласен, ответ должен был быть отправлен на @thirtydot - person Toby; 28.12.2012
comment
Это ничего не решает. Все элементы имеют одинаковую ширину и позиционируются абсолютно. - person Henry Brewer; 13.12.2018

С небольшой помощью этого комментария (CSS Block float left) я понял ответ.

В каждую создаваемую «строку» я добавляю имя класса left.
В каждую другую создаваемую «строку» я добавляю имя класса right.

Затем я плаваю влево и вправо для каждого из этих имен классов!

Единственная сложность заключается в том, что мой порядок содержимого в «правильных» строках меняется на обратный, но это можно решить с помощью PHP.

Спасибо за вашу помощь, ребята!

#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>

person stevenmc    schedule 08.03.2011
comment
За исключением того, что ваша демонстрация не похожа на вашу картинку. И это не сработает для бесконечного количества div, как вы задали в своем вопросе. Попробуйте адаптировать код в этом вашем ответе, чтобы использовать, например, 8 разной высоты .box div. - person thirtydot; 08.03.2011
comment
Кроме того, не имеет смысла иметь float: left или float: right и display: inline-block в одном элементе. display: inline-block будет преобразован в display: block (div по умолчанию) правилом float. Другими словами, display: inline-block ничего не делает. - person thirtydot; 08.03.2011
comment
Хорошо, вы правы, display: inline-block неверен ... Я соответствующим образом отредактировал свое решение. - person stevenmc; 14.03.2011
comment
Хм. Хорошо, ты прав ... Я все еще работаю над решением. Я опубликую здесь, когда закончу. Спасибо, тридцатидот. - person stevenmc; 14.03.2011
comment
Изменение порядка расположения одного из столбцов - не лучшее решение. HTML не должен ничего знать о том, как он будет оформлен. - person superluminary; 30.11.2012
comment
высота первого div составляет 100 пикселей - person Vishal B; 21.09.2017
comment
есть ли какое-либо решение для динамического преобразования 1,2,3,4 ... n - person Pratik Bhalodiya; 04.01.2018

Благодаря тридцати точкам я понял, что мой предыдущий ответ не решил проблему должным образом. Вот моя вторая попытка, которая использует JQuery как решение только для CSS, кажется невозможной:

<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>

Единственная проблема, которая остается для моего решения, - это то, что происходит, когда ширина коробки равна двум, а не одной. Я все еще работаю над этим решением. Я выложу, когда закончу.

person stevenmc    schedule 14.03.2011
comment
Вот моя вторая попытка ..? КАКИЕ? Почему вы публикуете все свои попытки как разные ответы ..? Вы можете просто отредактировать свой ответ и обновить его по своему усмотрению. - person T J; 18.10.2014

Если кто-то все еще ищет альтернативы, вот одна. Попробуйте использовать свойство (-moz - / - webkit-) column-width. Он решает проблему с переменной высотой div. Однако ширина столбца добавляет новый div в конец столбца.

В противном случае лучше всего работает jQuery Masonry.

person rodiwa    schedule 08.05.2014

Возможно, это не точное решение для всех, но я считаю, что (в буквальном смысле) нестандартное мышление работает во многих случаях: вместо отображения полей слева направо во многих случаях вы можете сначала заполнить левый столбец, чем перейдите в середину, заполните ее полями и, наконец, заполните правый столбец полями. Тогда ваше изображение будет:

порядок заполнения:

Если вы используете язык сценариев, такой как php, вы также можете заполнять столбцы слева направо, добавляя к нему новое поле и выводя данные, когда все столбцы заполнены. например (непроверенный код PHP):

$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 и $ col3 могут иметь значения float: left и width: 33%, установите поля внутри div на полную ширину и не используйте float.

Очевидно, что если вы используете javascript / jquery для динамической загрузки ящиков, вам лучше стилизовать их таким образом, как описано в других ответах на этот поток.

person bolvo    schedule 13.08.2015

для отображения просто поместите этот CSS в свой div, и тогда у вас будет желаемый макет. нет необходимости в плагине или JS.

 .Your_Outer {
    background-color: #FFF;
    border: 1px solid #aaaaaa;
    float: none;
    display:inline-block;
    vertical-align:top;
    margin-left: 5px;
    margin-bottom: 5px;
    min-width: 152.5px;
    max-width: 152.5px;
}

вы можете редактировать код в соответствии с вашими требованиями :)

person Shahid Amin    schedule 28.08.2015

В современных браузерах вы можете просто:

display: inline-block;
vertical-align: top;
person Flavio Tordini    schedule 21.08.2012
comment
Почему это было отклонено? - person superluminary; 30.11.2012
comment
См. Этот stackoverflow.com/a/5234858/428302 - person vinay; 05.12.2012
comment
Что ж, это действительно работает, и фрагмент, на который вы ссылаетесь, тоже работает (по крайней мере, в Chrome). Так что вы можете дать нам лучшее объяснение. - person Flavio Tordini; 29.01.2013
comment
Предыдущий вопрос связывает следующую скрипку, которая показывает, как получается этот метод: jsfiddle.net/bCgea/1 Неплохо, но и не то, что ищут. Поток в колонке не является непрерывным. - person Eric G; 01.02.2013