草庐IT

html - 用于将元素拆分为动态数量的列的纯 CSS 解决方案

coder 2023-07-31 原文

有没有办法在几列中对齐元素,其中列数取决于最宽的元素?元素高度和容器宽度都是固定的,但元素宽度是动态的。

我正在寻找一种仅使用 CSS 的方法来实现以下行为:

(Assume that the parent container is 300px wide.)

  • If the widest item is wider than 150px, use a single column
  • If the widest item is between 100px and 150px, use two columns
  • If the widest item is less than 100px, use three columns
  • ...
  • If the widest item is less than container width / N, use N columns


一种可能的方法是使用 display:inline-block和设置 width使用 JavaScript 将属性设置为容器中最宽元素的宽度。

this JSFiddle例如:



但是,我认为也应该有一种仅使用 CSS 的方法来做到这一点。是否可以?

如果没有,也许有一种优雅的 CSS-only 方法可以将动态大小的元素分配/捕捉到具有固定宽度的容器中的列?

最佳答案

...I am looking for a CSS-only way to achieve the following behavior...If the widest item is wider than...

...I am thinking that there should also be a CSS-only way of doing this...



As indicated by @Paulie-D ,CSS 无法检测您 child 的不同宽度 div s,因此不存在纯 CSS 唯一解决方案。

这是因为您想要获取所有元素的宽度,然后获取其中的最大值,然后使用该宽度将元素分布到列中。这种计算超出了 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?



我将分两部分解释:

第 1 部分,CSS:

当我们说我们希望内容在列中时,这意味着自上而下的流程,而不仅仅是从左到右的包装流程。为此,我们需要 CSS 列。



诀窍是指定 autocolumn-count / column-width .这将自动将内容分配到父宽度内所需的列数。

我在上述陈述中犯了一个根本错误(因此又进行了一次编辑)。根据 specs here算法说:

(01) if ((column-width = auto) and (column-count = auto)) then
(02)      exit; /* not a multicol element */ 


这是我之前错的地方。当两者column-countcolumn-width设置为 auto然后它被视为不是 multicol 元素。当这些属性之一设置为非自动值时,另一个属性由该属性确定。

来自 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)



一个例子是设置 column-width到固定宽度,比如 120px (稍后我们将在第 2 部分中讨论):
.container { -webkit-columns: auto 120px; columns: auto 120px; }

这将导致容器适合 中的内容尽可能多的列对于 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; }
<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>


fiddle 1:http://jsfiddle.net/abhitalks/tgwp4b7a/2/show

在上面的代码片段中,我们使用了 column-count: auto在容器上,和任意​​ column-width: 120px (仅用于演示)。这就是它的全部。上面的代码中有三个例子:(1)容器的宽度很小,内容分布在一列中,因为它们受column-width约束。 ; (2) 容器为中等宽度且内容分布在两列中,因为现在有更多可用空间; (3) 容器的宽度要大得多,可以容纳三列。

作为一个副作用,如果容器的宽度是百分比,那么整个设备也会自动响应。在较大的屏幕上显示更多列,在较小的屏幕上折叠为一列。

但是,这取决于您赋予容器 column-width 的固定宽度。因此也可以称为魔数(Magic Number)解。 但是,这不是我们想要的。我们不想根据容器的宽度确定列,我们希望列由内容宽度确定。 我们将在接下来的第 2 部分中看到如何消除这种依赖性。

第 2 部分,使用 Javascript 扩展它:

既然我们已经确定元素可以根据父级可用的宽度由 CSS 自动分布在列中,我们可以扩展它以通过 Javascript 消除对固定宽度的依赖。

回到你的问题:

...If the widest item is wider than...



为了确定最宽的元素并将该宽度应用于其余元素,您只需要 a well-known两行 Javascript:
var maxWidth = Math.max.apply(null, $("div.item").map(function () {
    return $(this).width();
}).get());

我们还设置了 child div转至 inline-block防止包装以识别实际宽度。因此,您需要向我们在第 1 部分中编写的 CSS 添加以下内容:
.container > div {
    display: inline-block; 
    white-space: nowrap;   /* prevents wrapping and helps getting actual width */
}

那么我们需要做两件事:(1)设置column-width在我们上面计算的这个最大宽度的容器上; (2) 将此宽度设置为所有子项 div让它们整齐地堆叠。此外,我们将不需要 column-count / column-width要在 CSS 中设置,因为无论如何我们都必须在 Javascript 中进行设置。
$("#container").css({ "column-width": maxWidth }).find('div').width(maxWidth);

请参阅以下代码段中的完整示例:

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


fiddle 2:http://jsfiddle.net/abhitalks/ojd57678/4/show

(更改了上面的代码片段和 fiddle 。感谢@Yandy_Viera,他指出应该使用 jQuery .outerWdith 而不是 .width(忽略 box-sizing: border-box,导致设置不正确的宽度。)

在上面的代码片段中,我们现在使用了示例的三种变体:(1) where child div s 具有较大的宽度,并分布在一列中,因为它们受容器宽度的限制; (2)凡儿div s 的宽度更小,分布在两列中,因为现在有更多可用空间; (3) where child div s 的宽度非常小,可以容纳在三列中。

如您所见,CSS 可以帮助根据可用宽度将内容分配到列中,但无法计算并将最宽的元素宽度应用于每个列。为此,一个两行的 Javascript 可以让你完成你最初想要的。

注意:当我第一次阅读你的问题时,我的印象是你已经有了一个可用的 Javascript 解决方案,我不确定你是否想要一个。但是,在第二次阅读时,我意识到您没有,并且 Javascript Angular 对于理解至关重要。因此,此编辑添加了 Javascript 部分。

注 2:此答案的先前版本存在一个缺陷,我在列属性的自动值中犯了一个基本错误。这需要再次编辑。

关于html - 用于将元素拆分为动态数量的列的纯 CSS 解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32049128/

有关html - 用于将元素拆分为动态数量的列的纯 CSS 解决方案的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - capybara field.has_css?匹配器 - 2

    我在MiniTest::Spec和Capybara中使用以下规范:find_field('Email').must_have_css('[autofocus]')检查名为“电子邮件”的字段是否具有autofocus属性。doc说如下:has_css?(path,options={})ChecksifagivenCSSselectorisonthepageorcurrentnode.据我了解,字段“Email”是一个节点,因此调用must_have_css绝对有效!我做错了什么? 最佳答案 通过JonasNicklas得到了答案:No

  5. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  6. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  7. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  8. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  9. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  10. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

随机推荐