Сбалансированное расположение столбцов в CSS3
Я пытаюсь создать сбалансированный (2-) столбец-макет.
Содержимое не является текстовым, а блокирует и изменяется по высоте.
Содержимое должно располагаться поочередно слева и справа, если "слева" и "справа" имеют (примерно) одну и ту же высоту.
т.е. на этом изображении:
Пробел между 1 и 3 не должен быть там.
Или на этом изображении:
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]()
-
Как это работает
Вместо того, чтобы плавать все ваши элементы "слева" и создавать промежутки, мы плаваем каждый контейнер в соответствии со стороной/столбцом, в котором они находятся.