Cos*_*ert 41 html css css3 flexbox
有没有办法在多列中对齐项目,列数取决于最宽的项目?项目高度和容器宽度都是固定的,但项目宽度是动态的.
我正在寻找一种只有CSS的方法来实现以下行为:
(假设父容器的宽度为300px.)
- 如果最宽的项目大于150px,请使用单个列
- 如果最宽的项目介于100px和150px之间,请使用两列
- 如果最宽的项目小于100px,请使用三列
- ...
- 如果最宽的项目小于容器宽度/ N,请使用N列
获得此行为的一种可能方法是使用JavaScript并使用JavaScript display:inline-block
将width
属性设置为容器中最宽元素的宽度.
请参阅此JSFiddle以获取示例:
但是,我认为应该只有CSS这样做.可能吗?
如果没有,也许有一种优雅的CSS方式将动态大小的项目分发/捕捉到具有固定宽度的容器中的列?
Abh*_*lks 25
...我正在寻找一种只有CSS的方法来实现以下行为......如果最宽的项目比...更宽
......我认为应该只有一种CSS的方式来做到这一点......
如@ Paulie-D所示,CSS无法检测到您孩子div
的宽度变化,因此不存在纯CSS唯一解决方案.
这是因为您希望获得所有元素的宽度,然后获取其中的最大值,然后使用该宽度将元素分配到列中.这个计算超出了CSS.你需要Javascript才能做到这一点.
如果没有,也许有一种优雅的CSS方式将动态大小的项目分发/捕捉到具有固定宽度的容器中的列?
我将分两部分解释:
当我们说我们希望内容在列中时,它意味着从上到下的流而不是从左到右的包装流.为此我们需要CSS Columns.
诀窍是指定 auto
的column-count / column-width
.这将自动将内容分配到父宽度内所需的列数.
我在上面的陈述中犯了一个根本性的错误(因此另一个编辑).根据这里的规范,算法说:
(01) if ((column-width = auto) and (column-count = auto)) then (02) exit; /* not a multicol element */
这是我之前错的地方.当两个column-count
和column-width
被设置为auto
那么它被视为不是MULTICOL元件.当其中一个属性设置为非自动值时,则另一个属性由此确定.
从上面的参考:
如果
column-count
设置为auto
,则列数将由其他属性确定(例如,column-width
如果它具有非自动值)并且如果column-width
设置为auto
,则列宽将由其他属性确定(例如column-count
,如果它有一个非自动值)
一个例子是设置column-width
为固定宽度,比如说120px
(稍后我们将在第2部分中处理):
.container { -webkit-columns: auto 120px; columns: auto 120px; }
Run Code Online (Sandbox Code Playgroud)
这将使容器在尽可能多的列中匹配内容,以使列宽度120px
在其自己的宽度内.如果增加容器宽度,它将获得更多列.如果减小容器宽度,当没有足够的可用空间时,它将获得更少的列,最终会折叠到单个列.
请参阅下面的代码段中的完整示例:
例1:
* { box-sizing: border-box; padding: 0; margin: 0; }
p { margin-left: 16px; }
.container { width: 400px; border: 1px solid #f00; margin: 16px; }
.container.col { -webkit-columns: auto 120px; columns: auto 120px; }
.container > div {
-webkit-column-break-inside: avoid; column-break-inside: avoid;
display: block; padding: 8px; border: 1px solid #ccc;
}
#one { width: 200px; }
#two { width: 300px; }
Run Code Online (Sandbox Code Playgroud)
<p>Small Container (1-column):</p>
<div id="one" class="container col">
<div class="item-min">Maudie Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
<p>Medium Container (2-column):</p>
<div id="two" class="container col">
<div class="item-min">Maudie Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
<p>Large Container (3-column):</p>
<div id="three" class="container col">
<div class="item-min">Maudie Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
Run Code Online (Sandbox Code Playgroud)
小提琴1:http://jsfiddle.net/abhitalks/tgwp4b7a/2/show
在上面的代码片段中,我们column-count: auto
在容器上使用,并且是任意的column-width: 120px
(仅用于演示).这就是它的全部.上面的代码中有三个例子:(1)容器宽度小,内容分布在一列,因为它们受到column-width
; (2)容器中等宽度,内容分为两列,因为现在有更多可用空间; (3)容器宽度大得多,可容纳三根柱子.
作为副作用,如果容器的宽度以百分比表示,那么整个装置也会自动响应.在较大的屏幕上显示更多列,并在较小的屏幕上折叠到一列.
但是,这取决于您为容器提供的固定宽度,column-width
因此也可以称为幻数解决方案.但是,这不是我们想要的.我们不希望根据容器的宽度确定列,我们希望列由内容宽度确定.我们将在后面的第2部分中看到如何消除这种依赖性.
既然我们已经确定了元素可以由CSS自动分布在列中,具体取决于父级可用的宽度,我们可以扩展它以消除我们通过Javascript对固定宽度的依赖.
回到你的问题:
......如果最宽的项目比...更宽
为了确定最宽的项目并将宽度应用于其余项目,您需要的只是一个众所周知的双线Javascript:
var maxWidth = Math.max.apply(null, $("div.item").map(function () {
return $(this).width();
}).get());
Run Code Online (Sandbox Code Playgroud)
我们还设置子项div
以inline-block
防止包装以识别实际宽度.所以,你必须添加到我们在第1部分中编写的CSS中的是:
.container > div {
display: inline-block;
white-space: nowrap; /* prevents wrapping and helps getting actual width */
}
Run Code Online (Sandbox Code Playgroud)
然后我们需要做两件事:(1)将column-width
on容器设置为我们上面计算的最大宽度; (2)将这个宽度设置给所有孩子div
,以便他们整齐地堆叠.此外,我们不需要column-count / column-width
在CSS中设置,因为我们必须在Javascript中这样做.
$("#container").css({ "column-width": maxWidth }).find('div').width(maxWidth);
Run Code Online (Sandbox Code Playgroud)
请参阅下面的代码段中的完整示例:
例2:
//large
var maxWidth = Math.max.apply(null, $("#one > div").map(function () { return $(this).outerWidth(); }).get());
$("#one").css({ "-webkit-column-width": maxWidth, "column-width": maxWidth }).find('div').outerWidth(maxWidth);
// medium
var maxWidth2 = Math.max.apply(null, $("#two > div").map(function () { return $(this).outerWidth(); }).get());
$("#two").css({ "-webkit-column-width": maxWidth2, "column-width": maxWidth2 }).find('div').outerWidth(maxWidth2);
// small
var maxWidth3 = Math.max.apply(null, $("#three > div").map(function () { return $(this).outerWidth(); }).get());
$("#three").css({"-webkit-column-width": maxWidth3, "column-width": maxWidth3 }).find('div').outerWidth(maxWidth3);
Run Code Online (Sandbox Code Playgroud)
* { box-sizing: border-box; padding: 0; margin: 0; }
p { margin-left: 16px; }
.container { width: 450px; border: 1px solid #f00; margin: 16px; }
.container > div {
-webkit-column-break-inside: avoid; column-break-inside: avoid;
display: inline-block; white-space: nowrap;
padding: 8px; border: 1px solid #ccc;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Normal children (wrapping):</p>
<div class="container">
<div class="item">Maudie Mcmanus</div>
<div class="item">Remedios Arrington</div>
<div class="item">Chaya B</div>
<div class="item">Duncan</div>
<div class="item">Lashonda Tatum Walls</div>
</div>
<p>Large children (1-column):</p>
<div id="one" class="container">
<div class="item-min">Maudie Mcmanus Mcmanus Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
<p>Medium children (2-column):</p>
<div id="two" class="container">
<div class="item-min">Maudie Mcmanus Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
<p>Small children (3-column):</p>
<div id="three" class="container">
<div class="item-min">Maudie Mcmanus</div>
<div class="item-min">Remedios</div>
<div class="item-min">Chaya B</div>
<div class="item-min">Duncan</div>
<div class="item-min">Lashonda</div>
</div>
Run Code Online (Sandbox Code Playgroud)
小提琴2:http://jsfiddle.net/abhitalks/ojd57678/4/show
(更改了上面的代码片段和小提琴.感谢@Yandy_Viera,他指出.outerWdith
应该使用jQuery 而不是.width
(忽略box-sizing: border-box
,导致设置不正确的宽度).
在上面的代码片段中,我们现在使用三个示例变体:(1)其中子div
s的宽度较大,并且由于它们受到容器宽度的约束而分布在一列中; (2)儿童div
的宽度较小,分布在两列,因为现在有更多的空间; (3)儿童div
的宽度非常小,可容纳三列.
如您所见,CSS可以帮助根据可用宽度将内容分配到列中,但无法计算并将最宽的元素宽度应用于每个元素宽度.对于这个,双线Javascript可以让你完成你最初想要的.
注意:当我第一次阅读您的问题时,我的印象是您已经拥有了一个有效的Javascript解决方案,而且我不确定您是否想要一个.然而,在第二次阅读时,我意识到你没有,并且Javascript角度对于理解是必不可少的.因此,这个编辑添加了一个Javascript部分.
注2:这个答案的前一个版本存在一个缺陷,我在列属性的自动值中出现了一个基本错误.这需要另一个编辑.
Yan*_*era 10
他们在评论中所说的一切,都不存在一个只有CSS的解决方案,所以我想给你一个很好的解决方案js
,你甚至不必迭代寻找最宽的项目,一切都来自一组CSS和数学.
您可以更改元素的内容,您将看到如何调整列数,如果最宽项小于容器宽度/ N,它将自动使用N列.
这个想法是很简单的,你set width: 'auto'
,display: 'inline-block'
要container
允许它适合它是由最宽的元素的宽度限定其内容看到它在波纹管IMG:
现在你可以使用宽度container
来知道最宽项目的宽度,这可以避免你必须迭代寻找它.现在你可以使用这个宽度来设置剩下的项目,但是让我们做得更好一点,我们可以让元素占用整个宽度,container
只需要一个litter calc:
var div = Math.floor(initialWidth / widestItemWidth); /*this is to get as many items fit with the width of the widest element*/
var itemWidth = initialWidth / div; /*for the width of the item occupy the entire container*/
Run Code Online (Sandbox Code Playgroud)
因此,如果最宽的项目小于容器宽度/ N,它将自动使用N列,它们将适合宽度container
,这就是你要做的全部,只需设置一个css属性,做一点计算,你有什么你想实现.
$(document).ready(function() {
var $container = $('.container');
var $item = $('.item');
var initialWidth = $container.outerWidth();
$container.css({ /*to allow it to fit its contents which is defined by the width of the widest element*/
width: 'auto',
display: 'inline-block'
});
var widestItemWidth = $container.outerWidth(); /*Now this is the width of the widest item*/
var div = Math.floor(initialWidth / widestItemWidth); /*this is to get as many items fit with the width of the widest element*/
var itemWidth = initialWidth / div; /*for the width of the item occupy the entire container*/
/*if you don't want the items occupy the entire width of the container just use 'widestItemWidth' as width of $item*/
$item.css({
width: itemWidth,
float: 'left'
});
$container.css({ /*restoring the initial styles*/
width: initialWidth,
display: 'block'
});
})
Run Code Online (Sandbox Code Playgroud)
.container {
width: 400px;
overflow: hidden;
}
.container .item {
padding: 8px;
border: 1px solid rgb(216, 213, 213);
}
*{
box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">Maudie Mcmanus</div>
<div class="item">Remedios Arrington</div>
<div class="item">Chaya B</div>
<div class="item">Duncan</div>
<div class="item">Lashonda Tatum Walls</div>
</div>
Run Code Online (Sandbox Code Playgroud)
如果你想为你的物品添加保证金,你只需要在做这样的数学时考虑它:
$(document).ready(function() {
var $container = $('.container');
var $item = $('.item');
var initialWidth = $container.outerWidth();
$container.css({
width: 'auto',
display: 'inline-block'
});
var currentWidth = $container.outerWidth();
var itemMargin= parseInt($item.css('margin-right'));
var div = Math.floor(initialWidth / currentWidth);
var itemWidth = initialWidth / div - itemMargin; /*subtracting the item's margin from the compute width*/
$item.css({
width: itemWidth,
float: 'left'
});
$container.css({
width: initialWidth,
display: 'block'
});
})
Run Code Online (Sandbox Code Playgroud)
.container {
width: 400px;
overflow: hidden;
}
.container .item {
padding: 8px;
border: 1px solid rgb(216, 213, 213);
margin-right: 3px;
}
*{
box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">Maudie Mcmanus</div>
<div class="item">Remedios Arrington</div>
<div class="item">Chaya B</div>
<div class="item">Duncan</div>
<div class="item">Lashonda Tatum Walls</div>
</div>
Run Code Online (Sandbox Code Playgroud)