Сбалансированное расположение столбцов в CSS3

Я пытаюсь создать сбалансированный (2-) столбец-макет.

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

т.е. на этом изображении: enter image description here Пробел между 1 и 3 не должен быть там.

Или на этом изображении: enter image description here 2 должны стоять на правой стороне, а 1, 3 и 4 должны стоять на левой стороне (без пробела между ними).

Я попытался использовать "плавающий <li>" как это:

HTML:

<ol class="context">
    <li class="gruppe">1</li>
    <li class="gruppe">2.0<br />2.1</li>
    <li class="gruppe">3.0<br />3.1</li>    
    <li class="gruppe">4</li>
</ol>

CSS

ol.context 
{
  border: 1px solid #048;
  list-style: none;
  margin: 0;
  padding: 0 0 8px 0;
  overflow: auto;
}

li.gruppe
{
  background: #048;
  color: white;
  float: left;
  font: bold 32px Arial, sans-serif;
  margin: 1px;
  text-align: center;
  width: calc(50% - 2px);
}

(См. попытка 1 и попытка 2)

Я также попытался использовать столбец (column-count: 2; column-fill: auto;), но это сначала не заполняет столбцы слева направо. (Сначала он заполняет сверху вниз.)

Возможно ли это без JavaScript?

Ответ 1

Я бы сказал, что это невозможно без JS. Вот скрипка, которую я сделал на основе статьи из Бен Холланд. По крайней мере, мне кажется, что вы после.

http://jsfiddle.net/QWsBJ/2/

HTML:

<body onload="setupBlocks();">
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
  <div class="block">
    <p>***Content***</p>
  </div>
</body>

CSS

.block {
  position: absolute;
  background: #eee;
  padding: 20px;
  width: 300px;
  border: 1px solid #ddd;
}

JS:

var colCount = 0;
var colWidth = 0;
var margin = 20;
var blocks = [];

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

function setupBlocks() {
    colWidth = $('.block').outerWidth();
    colCount = 2
    for(var i=0;i<colCount;i++){
        blocks.push(margin);
    }
    positionBlocks();
}

function positionBlocks() {
    $('.block').each(function(){
        var min = Array.min(blocks);
        var index = $.inArray(min, blocks);
        var leftPos = margin+(index*(colWidth+margin));
        $(this).css({
            'left':leftPos+'px',
            'top':min+'px'
        });
        blocks[index] = min+$(this).outerHeight()+margin;
    }); 
}

Array.min = function(array) {
    return Math.min.apply(Math, array);
};

Ответ 2

Обновлено: Я считаю, что это почти невозможно достичь только с помощью CSS. Существует много разных решений, но все они требуют компромиссов, если вы не хотите использовать JavaScript или какой-либо серверный код.

Использование столбцов CSS

Здесь альтернативная скрипта с использованием переупорядоченных блоков. Здесь демонстрацию скрипта с использованием столбцов CSS без переупорядочения.

Вы можете использовать CSS colunms, чтобы изменить поток блоков на вертикальные, если вы не измените порядок их вывода. Если вы можете сначала выводить нечетные числа, а затем цифры, вы выигрываете.

<div class="wrapper">
  <div class="block1">1</div>
  <div class="block3">3</div>
  <div class="block2">2</div>
  <div class="block6">4</div>
</div>

.wrapper {
    column-count: 2;
    column-width: 100px;
    -moz-column-width: 100px;
    -webkit-column-width: 100px;
    width: 260px;
}
div {
    border: 1px solid #999;
    display: inline-block;
    margin: 10px;
    width: 100px;
}
.block1 { height: 100px; }
.block2 { height: 130px; }
.block3 { height: 150px; }
.block4 { height: 100px; }

Это решение несовместимо с IE9 и ниже.

Известная высота блока

Если вы знаете высоту своего блока, вы можете решить эту проблему, используя абсолютное позиционирование.

block1 {
  height: 100px;
  position: absolute;
  left: 0; 
  top: 0;
}

block2 {
  height: 110px;
  position: absolute;
  left: 0; 
  top: 100px; /* The height of the div above it */
}

Большой недостаток - динамический контент; мы редко знаем высоту блока. Таким образом, это решение очень ограничено в своем приложении, если вы не хотите вычислять высоту блока высоты.

Если вы хотите использовать JS

Используйте плагин, подобный масонству. И в vanilla js, либо jQuery.

Другие параметры

Это дает вам следующие параметры, требующие компромиссов.

  • Группируйте блоки в столбцы. Смотрите этот скрипт для демонстрации. Это изменит поток ваших блоков на вертикальные, затем горизонтальные.

  • Используйте display: inline-block; vertical-align: top; для своих блоков. Это оставит некоторое пространство ниже ваших блоков.

  • Настройте высоту своих блоков, делая это не проблемой. Для блоков с дополнительным контентом используйте свойство overflow, чтобы разрешить прокрутку в блоке.

  • Как прокомментировали другие, вы можете попытаться вычислить высоту блоков на сервере.

Ответ 3

Вы можете попробовать сочетание flex и float (только в Firefox/IE10 и Safari 5.1.7, по моему мнению, CSS не является вашим решением)

http://codepen.io/gcyrillus/pen/zgAiw

Но в любом случае CSS, который вы выбираете, лучше всего перевести на mansonry script. CSS на самом деле не адаптирован к такому виду макета. В это время у вас есть много методов CSS для макета и в основном: отображение и поплавок.

Вы можете легко использовать это вместе в своей структуре дерева html, но эти методы не должны смешиваться. Коробка будет floatting, ящик inline-level-box или block-level-box, и каждый из них предположительно будет взаимодействовать в потоке. Float, разбивает строку перед собой после неплавающего элемента или скользит вниз, пока у него недостаточно места, что вы отправляете вправо/влево с помощью CSS r not.

встроенный блок удаляется от элементов floatting и разбивает строку, если осталось недостаточно места, элементы floatting среди встроенных блоков будут продолжать разбивать строку перед плаванием.

Столбец CSS будет заполнять столбцы содержимым один за другим. см. http://codepen.io/gcyrillus/pen/AtazJ

Элементы Inline-flex, похоже, работают с элементами floatting... но предполагается ли это, что это проверенное правило?

Мне кажется, что мне нужно использовать javascript для ожидаемого макета и ретрансляции по плавающей позиции или отображения: inline-block + width как откат.

Последнее решение - подумать об этом на своей стороне сервера и отправить свои товары в 2 контейнера с другой подходящей разметкой, если это возможно (нет представления о вашем реальном содержании жизни, отправленном в вашем ol li).

CSS для теста FLEX:

li.gruppe
{
  background: #048;
  color: white;
  font: bold 32px Arial, sans-serif;
  text-align: center;
  box-sizing:border-box;
  border-bottom:1px solid white;
   border-bottom:1px solid white;
    display: -webkit-inline-flex;
  display: -moz-inline-flex;
  display: -ms-inline-flex;
  display: inline-flex;  
  width:50%;
 }
li:nth-child(even){
  float:right;
  clear:right;
  border-left:1px solid white;
  margin-top:0;
}

Ответ 4

РЕДАКТИРОВАТЬ: Это интересное решение, но, к сожалению, оно не решает проблему, которая была запрошена.

Решение, которое я предлагаю здесь, помещает последующие элементы в чередующиеся столбцы, таким образом: 1 → слева, 2 → справа, 3 → слева, 4 → справа и т.д.

Это интересная проблема сама по себе, но не то, о чем просили.

Спасибо @Nils в комментариях за указание на это.

Оригинальный ответ

Вот моя попытка с flex!
https://jsfiddle.net/vqLr8t3e/

Я не уверен, работает ли он в IE11.

Код

.the-beginning {
  background: green;
  color: white;
  font-weight: bold;
  text-align: center;
  cursor: pointer;
}

.the-end {
  background: red;
  color: white;
  font-weight: bold;
  text-align: center;
  cursor: pointer;
}

.container-outer {
  overflow: hidden;
}

.container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  max-height: 19999px;
  margin-top: -10000px;
}

.container > div {
  width: 50%;
  box-sizing: border-box;
  border: 5px solid grey;
  padding: 5px;
  background: white;
  order: 1;
}

.container > div:nth-child(odd) {
  order: -1;
}

.container > div:nth-child(1),
.container > div:nth-child(2) {
  margin-top: 10000px;
}
<div class="the-beginning">THE BEGINNING</div>
<div class="container-outer">
  <div class="container">
    <div>LEFT 0</div>
    <div>RIGHT 0<br>RIGHT 0</div>
    <div>LEFT 1<br>LEFT 1<br>LEFT 1</div>
    <div>RIGHT 1</div>
    <div>LEFT 2</div>
    <div>RIGHT 2<br>RIGHT 2<br>RIGHT 2</div>
  </div>
</div>
<div class="the-end">THE END</div>

Ответ 5

Я не уверен, прав ли я.,

"2 должны стоять на правой стороне, а 1, 3 и 4 должен стоять на левой стороне (без пробела между ними). ​​

HTML:

<div id="box">
    <div class="data">1</div>
    <div class="data" style="float:right">2<br/>2<br/>2<br/>2</div>
    <div class="data">3<br/>3</div>
    <div class="data">4</div>
</div>

CSS

#box {
    width:100%;
    height:auto;
    float:left;
}
.data {
    height:auto;
    width:50%;
    float:left;
    background-color:#ccc;
    border-bottom:solid 1px #000;
}

Фид: http://jsfiddle.net/YdEW9/26/

Это чистый css. Все есть floated left, а затем дал inline-css float:right в div с (4) 2's

Я вроде как не знаю, как установить inline-css без javascript. Возможно, серверная сторона? но я сомневаюсь, что вы можете получить высоту элементов.

Хорошо, в любом случае надеюсь, что это поможет.

Ответ 6

PURE CSS SOLUTION:

Добавьте в свой файл css следующее:

ol.context li:nth-child(even) {
float: right;
}

НЕ меняйте свой html или что-то еще.

Результат в FF:

Firefox rendering

-

Как это работает

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