25
...I am looking for a CSS-only way to achieve the following behavior...If the widest item is wider than...
…我正在寻找一种只有css的方法来实现以下行为……如果最宽的项比…
...I am thinking that there should also be a CSS-only way of doing this...
…我认为应该有一种只有css才能做到的方式……
As indicated by @Paulie-D, CSS can't detect varying widths in your child div
s and hence a pure CSS only solution is not existent.
正如@Paulie-D所指出的,CSS无法检测子div中不同的宽度,因此不存在纯的CSS唯一解决方案。
This is because you are wanting to get the widths of all elements, then get the max of those, and then use that width to distribute elements into columns. This computation is beyond CSS. You will need Javascript to do that.
这是因为您希望获得所有元素的宽度,然后获得它们的最大值,然后使用该宽度将元素分配到列中。这种计算超出了CSS。这需要Javascript来实现。
If not, perhaps there is an elegant CSS-only way of distributing / snapping the dynamically-sized items to the columns in a container with a fixed width?
如果没有,也许有一种优雅的仅使用css的方式,将动态大小的项目分配到具有固定宽度的容器中的列中?
I will explain that in two parts:
我将分两部分来解释:
Part 1, the CSS:
When we say that we want content to be in columns, it means a top-to-down flow instead of just left-to-right wrapping flow. For this we require CSS Columns.
当我们说我们希望内容在列中,它意味着一个自上而下的流,而不是仅仅从左到右的包装流。为此,我们需要CSS列。
The trick would be to specify
auto
for
column-count / column-width
. This will automatically distribute the content into the number of columns required within the parent width.
诀窍是为列数/列宽指定auto。这将自动将内容分配到父宽度中所需的列的数量。
I made a fundamental mistake in the above statement (hence another edit). As per the specs here the algorithm says:
我在上面的语句中犯了一个根本性的错误(因此又一次编辑)。根据这里的规格,算法说:
(01) if ((column-width = auto) and (column-count = auto)) then
(02) exit; /* not a multicol element */
This is where I was wrong earlier. When both column-count
and column-width
are set to auto
then it is treated as not a multicol element. When one of these properties is set to non-auto value, then the other property is determined by this one.
这是我之前错误的地方。当列数和列宽都设置为自动时,它就被视为非多列元素。当其中一个属性被设置为非自动值时,另一个属性由这个属性决定。
From the above ref:
从上面的参考:
if column-count
is set to auto
, then the number of columns will be determined by other properties (e.g., column-width
, if it has a non-auto value) and if column-width
is set to auto
, then the column width will be determined by other properties (e.g., column-count
, if it has a non-auto value)
如果将列数设置为auto,那么列的数量将由其他属性决定(例如,列宽,如果它有非自动值),如果列宽设置为auto,那么列宽将由其他属性决定(例如,如果列宽没有自动值,那么列数)
An example would be to set column-width
to a fixed-width, say 120px
(we will deal that in part 2 a little later):
例如,将列宽设置为一个固定的宽度,比如120px(稍后我们将在第2部分中对此进行讨论):
.container { -webkit-columns: auto 120px; columns: auto 120px; }
This will cause the container to fit the content in as many columns as it can for a column width of 120px
within its own width. If you increase the container width, it will get more columns. If you decrease the container width, it will get less columns eventually collapsing to a single column when there is not much space available.
这将使容器在其自己的宽度为120px的列中尽可能多地容纳内容。如果您增加容器的宽度,它将获得更多的列。如果减少容器的宽度,当没有足够的空间时,最终压缩到单个列的列就会减少。
See the complete example in snippet below:
参见下面代码片段中的完整示例:
Example 1:
示例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; }
Small Container (1-column):
Maudie Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Medium Container (2-column):
Maudie Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Large Container (3-column):
Maudie Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Fiddle 1: http://jsfiddle.net/abhitalks/tgwp4b7a/2/show
小提琴1:http://jsfiddle.net/abhitalks/tgwp4b7a/2/show
In the above snippet, we are using column-count: auto
on the container, and an arbitrary column-width: 120px
(just for demo). It is all there is to it. There are three examples in the code above: (1) where container is of small width and content is distributed in one columns as they are constrained by the column-width
; (2) where container is of medium width and content is distributed in two columns as there is now more space available; and (3) where container is of much larger width and can accommodate three columns.
在上面的代码片段中,我们在容器上使用了column-count: auto,以及一个任意的column-width: 120px(仅供演示)。这就是一切。在上面的代码中有三个例子:(1)容器的宽度很小,内容分布在一个列中,因为它们受到列宽的约束;(2)容器中等宽度,内容以两列形式分布,空间更大;(3)容器的宽度大得多,可以容纳三列。
As a side-effect, if the container's width is in percent, then the whole apparatus automatically becomes responsive as well. On larger screens showing more columns, and on smaller screens collapsing to one column.
作为副作用,如果容器的宽度是百分比,那么整个设备也会自动响应。在显示更多列的大屏幕上,在缩小为一列的小屏幕上。
However, this is dependent on the fixed-width that you give to the container's column-width
and hence can also be called a magic-number solution. But, this is not what we want. We do not want to determine columns based on container's width, we want the columns to be determined by the content width. We'll see how to eliminate that dependency in the part 2 that follows.
但是,这依赖于容器的列宽的固定宽度,因此也可以称为魔术数字解决方案。但是,这不是我们想要的。我们不希望根据容器的宽度来确定列,我们希望这些列由内容宽度决定。我们将在下面的第2部分中看到如何消除这种依赖性。
Part 2, extending it with Javascript:
Now that we have established that elements can be distributed automatically by CSS in columns depending on the width available on parent, we can extend this to eliminate our dependence on fixed-width via Javascript.
既然我们已经确定了元素可以由CSS根据父元素的宽度自动地以列的形式分布,那么我们就可以扩展它,通过Javascript消除对固定宽度的依赖。
Coming back to your question of:
回到你的问题:
...If the widest item is wider than...
…如果最宽的项比…
In order to determine the widest item and apply that width to the rest of them, all that you require is just a well-known two-liner Javascript:
为了确定最宽的项并将该宽度应用于其他项,您所需要的只是一个众所周知的两行Javascript:
var maxWidth = Math.max.apply(null, $("div.item").map(function () {
return $(this).width();
}).get());
We also set child div
s to inline-block
prevent wrapping to identify the real width. So, all you have to add to the CSS we wrote in part 1 is this:
我们还将子div设置为inline-block防止包装以识别真正的宽度。所以,你要添加到我们在第1部分中所写的CSS中:
.container > div {
display: inline-block;
white-space: nowrap; /* prevents wrapping and helps getting actual width */
}
Then we need to do two things: (1) set the column-width
on container to this max-width that we calculated above; and (2) set this width to all of the child div
to allow them to stack neatly. Also, we will not be needing column-count / column-width
to be set in CSS, because we have to do that in Javascript anyway.
然后我们需要做两件事:(1)将容器上的列宽设置为上面计算的最大宽度;并且(2)将此宽度设置为所有子div,以允许它们整齐地堆叠。同样,我们也不需要在CSS中设置列数/列宽,因为我们必须在Javascript中这样做。
$("#container").css({ "column-width": maxWidth }).find('div').width(maxWidth);
See the complete example in snippet below:
参见下面代码片段中的完整示例:
Example 2:
示例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);
* { 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;
}
Normal children (wrapping):
Maudie Mcmanus
Remedios Arrington
Chaya B
Duncan
Lashonda Tatum Walls
Large children (1-column):
Maudie Mcmanus Mcmanus Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Medium children (2-column):
Maudie Mcmanus Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Small children (3-column):
Maudie Mcmanus
Remedios
Chaya B
Duncan
Lashonda
Fiddle 2: http://jsfiddle.net/abhitalks/ojd57678/4/show
小提琴2:http://jsfiddle.net/abhitalks/ojd57678/4/show
(Changed the above snippet and fiddle. Thanks to @Yandy_Viera, who pointed out the fact that jQuery .outerWdith
should be used instead of .width
(which ignores box-sizing: border-box
, causing incorrect widths to be set.)
(更改了上面的代码片段并进行了修改。感谢@Yandy_Viera,他指出了jQuery . outerwdith应该被使用的事实,而不是。width(忽略了框的大小:边界框,导致设置不正确的宽度)。
In the above snippet, we are now using three variations of examples: (1) where child div
s are of larger width and are distributed in one column as they are constrained by the container's width; (2) where child div
s are of smaller width and are distributed in two columns as there is now more space available; and (3) where child div
s are of very small width and can be accommodated in three columns.
在上面的代码片段中,我们现在使用了三种不同的示例:(1)子divs的宽度较大,并且由于受容器宽度的限制而分布在一列中;(2)子divs的宽度较小,并且由于现在有更多的空间,因此被分成两列;和(3)子div的宽度非常小,可以容纳在三列中。
As you can see, CSS can help in distributing content into columns based on available width but cannot calculate and apply widest of the element widths to each of them. For this a two-liner Javascript would get you done what you initially wanted.
正如您所看到的,CSS可以根据可用的宽度将内容分发到列中,但是不能计算并将最宽的元素宽度应用到每个列中。为此,两行Javascript将完成您最初需要的工作。
Note: When I first read your question I was under the impression that you already have a working Javascript solution with you, and I wasn't sure if you wanted one. However, on a second read I realized that you hadn't, and the Javascript angle was essential to understand. Hence, this edit to add a Javascript part.
注意:当我第一次读到您的问题时,我感觉您已经有了一个可用的Javascript解决方案,我不确定您是否需要它。然而,在第二次阅读时,我意识到您没有这样做,理解Javascript的角度非常重要。因此,此编辑将添加一个Javascript部分。
Note 2: There was a flaw in the previous version of this answer, where I let in a fundamental mistake in auto values of the columns properties. This necessitated another edit.
注意2:在这个答案的前一个版本中有一个缺陷,我在列属性的自动值中犯了一个根本性的错误。这需要另一个编辑。