使用 jQuery(例如 matchHeight.js)有很多实现等高列的解决方案。基本思路是测量所有列的高度,然后将所有列的高度设置为最高列的高度。
但是,如果有多行块,而您只想将高度增加以匹配当前行呢?这可能是由于每个框中具有不同大小的缩略图或不同数量的文本造成的。
Stephen Akins 发布了一个巧妙的想法 来解决这个问题。这个想法大体相同,测试 div 的高度并将它们设置为最高的高度,但在执行此操作之前,它会测量顶部位置。由此,它能够确定哪些 div 属于哪一行,并且只影响该行内的 div。
这是整个代码。我只是从 Stephen 的原始代码中稍微调整了一下,使其效率更高。
// 立即执行函数 (IIFE)
(function() {
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array();
function setConformingHeight(el, newHeight) {
// 将高度设置为新值,但记住原始高度以防发生更改
el.data(“originalHeight”, (el.data(“originalHeight”) == undefined) ? (el.height()) : (el.data(“originalHeight”)));
el.height(newHeight);
}
function getOriginalHeight(el) {
// 如果高度已更改,则发送 originalHeight
return (el.data(“originalHeight”) == undefined) ? (el.height()) : (el.data(“originalHeight”));
}
function columnConform() {
// 查找行中最高的 DIV,并将所有 DIV 的高度设置为与其匹配。
$(‘.blocks’).each(function() {
// “缓存”
var $el = $(this);
var topPosition = $el.position().top;
if (currentRowStart != topPosition) {
// 我们刚刚进入新的一行。设置已完成行上的所有高度
for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) setConformingHeight(rowDivs[currentDiv], currentTallest); // 设置新行的变量 rowDivs.length = 0; // 清空数组 currentRowStart = topPosition; currentTallest = getOriginalHeight($el); rowDivs.push($el); } else { // 当前行上的另一个 div。将其添加到列表中,并检查它是否更高 rowDivs.push($el); currentTallest = (currentTallest < getOriginalHeight($el)) ? (getOriginalHeight($el)) : (currentTallest); } }); // 处理最后一行 for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) { setConformingHeight(rowDivs[currentDiv], currentTallest); } } // 如果内容可能会更改... 可能需要去抖动并运行此函数。 // $(window).resize(function() { // columnConform(); // }); // DOM 就绪 // 如果图像导致块高度不一致,您可能还需要等到 window.onload $(function() { columnConform(); }); })(); $('.blocks')
将更改为使用您需要均衡的任何 CSS 选择器。或者让函数接受选择器作为参数或其他什么。
流体宽度怎么办?
不使用表格的主要原因之一是,浮动 div 可以根据可用的水平空间重新排列自身,这对于流体宽度非常有用。我们也可以调整上述代码来处理这种情况。基本上,第一次运行此代码时,我们将测量每个块的高度并使用 jQuery 的 data() 方法记住它。然后,当窗口大小调整大小时,再次运行代码,但使用原始大小来调整行,而不是新大小。
此演示具有流体宽度。如果您需要该代码,只需查看源代码并获取它即可。
希望它没有 jQuery 依赖项?
- Ben Howdle:轻松实现等高
- Vitalii Skorokhod:javascript 等高块
\
谢谢!我会在我的网站上尝试一下。
哦,Chris……你什么时候开始将表现与 JavaScript 混合使用了?
哦,BFRED.IT……当这些解决方案很巧妙并且解决了现实世界中的问题时,我就会发布它们。听起来你对此有异议,所以请阐明一下。
也许可以使用 display: table-cell; http://bfred.it/b/full-height.html
我刚刚创建了它,我还没有在 WebKit 之外测试它,它可能不优雅,但它应该即使在 JS 关闭时也能工作。
我个人不喜欢
display: table-cell;
。如果要走这条路,使用 div 并使其表现得像表格与直接使用实际表格(这将具有更广泛的浏览器支持)之间没有区别。也就是说,如果要显示的数据本质上是表格形式的,那么表格比使用 JavaScript 更好的解决方案。
当然有区别,表格是表格,div 是通用容器。使用 `table-cell` 的 div 在机器看来是容器,而不是表格。
抱歉我一开始这样开始对话,我一直认为这是一个“已解决的问题”。
对于每个自愿提供宝贵提示的人,总会有一个“是的,但是……”的人可以在自己的网站上拼凑出一个未经测试的版本。:)
无论如何,干杯并感谢分享 - 我设想未来会有很多机会使用等高来实现多列。
如果论点是提高 div 相对于表格单元格的语义,那么是的,如果它是非表格数据,则确实存在好处。
这里最初的问题是“不使用 JavaScript 的用户被排除在外”,这是事实,但如果您使用 display table-cell,则更多的人会被排除在外。
IE7 = 约 6%
无 JS = 约 2%
(当然,这取决于网站)
说得对,然后我们可以有条件地在
lte IE7
上添加上述 JS 解决方案,让每个人都满意:)对此要谨慎,与表格相关的任何 CSS - 即使是使用 CSS 生成的表格 - 都可能很快出现问题。尝试将这些单元格设置为 position:relative,并在其中包含绝对定位的元素,看看会发生什么。(CSS 2.1 规范明确将此定义为未定义 :( )
我记得有一个解决方法,例如在“表格单元格”内使用一个 div 并定位其中的内容。但是,是的,这取决于您需要做什么。如果您只需要创建文本列,它就可以正常工作。事实上,它可以用作不支持 CSS3 文本列的浏览器的后备方案。
我不确定 div 修复在这里是否有效,它不会是单元格的高度,如果您想要底部定位的内容,您将回到原点。
如果您真的必须这样做,您会找到一种方法来在您遇到的特定情况下进行绝对定位(请参阅第一列中我更新的示例以了解解决方案),但我们仍在讨论文本列,最多您需要在其中浮动图像。
另一种(部分)纯 CSS 解决方案是设置
min-height
,这在静态网站或受控内容(例如帖子摘录)上效果最佳。请记住,如果决定走这条路,Chris 的示例在流体布局上不起作用。这并不意味着我们将推广使用 onresize 事件或非标准
expression()
来解决现实世界中的问题。如果目的是提高可用性或添加渐进增强,当然,请继续使用该 JavaScript,但不要将其用于布局,这让人想起 2000 年代初期的(糟糕的)部分。
天哪。
但原文*不仅*在谈论文本列。
我只是指出存在权衡 - 您可以使用 display:table-cell 并获得纯 CSS 解决方案,但您会失去可能想要的其他东西。如果您不想要它们,请务必使用 display:table-cell。我指出这一点是因为我花了太多时间试图解决这个问题,而这里其他人可能会遇到同样的问题。
是的,我认为这个脚本本质上是关于美观的,而不是布局的。我还没有尝试过这个特定的脚本,但从概念上讲,所有内容都在那里,并且除了块的底部之外,js 和无 js 之间没有任何变化。从示例“Booo”图像中可以看出,第二行所有内容都正确地顶端对齐,已清除,等等。你应该已经在你的 CSS 中这样做了,这只是使盒子高度相同,使其看起来更整齐。
BFRED.IT
不适用于流体布局?你的意思是?这是旨在用于流体布局的。它适用于一行上的任意数量的 DIV,因此如果你的窗口有空间容纳 10 个 DIV 或 2 个 DIV,则每一行上的 DIV 将具有相同的高度(每一行中最高的 DIV 的高度)。
如果你查看我的博客,你会看到一个使用 onresize 事件的版本,这样你就可以抓住窗口的边缘并尝试不同的宽度,并观察 DIV 在从一行移动到另一行时如何流动和调整大小。
还有,伙计们:谁在乎 JS 是否不起作用?修复纯粹是为了美观。没有使用 JS 浏览网页的人将遇到比 DIV 高度不匹配更严重的问题。
Stephen,我的观点也完全一样。那些说“哦,但是它在 Javascript 关闭的情况下是否有效?!”的人似乎从未承认过,99%(只是一个粗略的数字)的网页在 Javascript 关闭的情况下无法正常工作。尝试关闭它并访问你最喜欢的网站。哎呀,尝试关闭它并访问此网站。它不太好看(对 Chris 没有冒犯之意)。
我非常喜欢这个脚本。结合 960.gs 之类的东西,它非常棒。
如果这听起来很粗鲁,请原谅我……但是对于那些实际上浏览网络的极少数台式机、Mac、笔记本电脑和笔记本电脑用户来说,如果他们没有使用 javascript,那么他们真的是那些会让我们从使用网络中获利或至少从浏览我们的网站中获益的人吗?
我认为这就像一个 IE6 问题困境……很多人已经停止制作支持 IE6 的网站,不是因为它是一个糟糕的浏览器……它只是过时了……我们身处 CSS3、Jquery、HTML5、webkit 的世界,更不用说 IE9 了。我感到惊讶的是,博主和读者仍然担心 JS 的支持。
我简直不敢相信……在苦苦挣扎了三天之后,我终于找到了解决这个问题的方法,就在你发布这篇文章的两个小时后 :-))))))))))
无论如何,那些对主题感兴趣的人,可以查看这个论坛帖子
https://css-tricks.org.cn/forums/discussion/10602/wrapped-content-that-stretching-two-surrounding-div-s
我在那里发布了许多有用的链接。
代替
你可以使用 Math.max
这还可以避免你计算两次高度。
谢谢 Pete,我会在我的代码中使用你的建议。
感谢分享 Chris,我非常喜欢“equalizeThoseMoFos()”部分!
说真的,我不确定我是否会为此问题使用 javascript 解决方案。
我很有可能使用技巧来伪造它们的高度相同。
如何使用 min-height 并将其设置为最高列的高度……就完成了。
如果最高列是由内容生成的,则不起作用 ;-)
我真的很喜欢这个,我之前尝试过弄清楚如何做到这一点,但仅使用 max-height CSS 功能似乎是不可能的。我现在知道这是等高列的最佳解决方案。感谢你的想法
经过三天的研究,我不会说“这是最好的解决方案”。
有很多方法可以实现这种效果,人们应该根据情况做出决定。
根据列背景的设计,你可以通过向列的父元素添加 repeat-y 背景来实现此效果,而无需使用 Javascript。
……这被称为“css 伪列”。:-)
酷,不知道它还有个名字 :-)
问题在于,如果你想在 div 行之间留出一些空间,则需要为每一行提供一个容器,这将提供许多更简单的解决方案。
那是真的。但在大多数情况下,我认为添加一些非语义标记比依赖 JavaScript 进行布局要好。
不错的设置。我制作了一个插件可以做到这一点,但是它不适用于这个“行理念”。我的将由行本身处理。
关于顶部位置的想法绝对不错。
这是我的插件(我确实有一个更新可以提供更多功能,很快就会推出)https://github.com/madmike1029/matchheights
很棒的东西 :)
如果我在一个月前看到就好了。
哦,是的!这太棒了。检查顶部位置的想法是我从未想到过的。
顺便说一句,我真的很喜欢你的命名,例如
equalizeThoseMoFos();
。喜欢!嘿 Chris,很棒的文章!这将帮助很多试图找到获取等高列解决方案但难以找到答案的人。我期待你下一篇文章!
嘿 Chris.. 无法理解这篇文章.. 它可以通过采取一些或也……
嘿 Chris,
我认为这是一个很棒、简单/快速的解决方案,可以解决一个恼人的问题。感谢分享。
它不仅仅是 html 和 css,而且还有一些代码——如果你有很多动态生成的块,它很好(甚至很棒)。
但是,如果你只使用几行(例如在一个网站上显示 5-10 条最新新闻),使用表格会“更便宜”(没有服务器/客户端代码——而且更少)。
是的,我知道你不能用沙拉碗吃冰淇淋……但是嘿,事实证明你可以;)
我喜欢你如何让事情变得不那么可怕。我尝试使用 jquery 一段时间了,但你让它变得容易多了。你是一个传奇 Chris。
盒子高度不同真的很烦人!
为什么不直接使用表格?
完全正确!!!!!
因为你可以有可变数量的列。你无法用表格做到这一点。
看起来一个(奇怪地重复的)错字引入了一个意外的全局
“topPostion”
你进行过代码检查吗?
还有“currentDiv”也是全局变量。
“new Array()”和“.length = 0”有点像 w3schools 的风格,为什么不直接使用“[]”?
多么酷的概念,它帮助了我……
因为我想构建一个像这样执行的网站
http://linesforme.blogspot.com
我在标准的 WordPress 安装上遇到了一些问题。
让我澄清一下——如果我从 google 库手动调用 jQuery,它就可以工作。
尝试将 jQuery 加入队列或依赖于 wp_head() 中已调用的 jQuery 似乎不起作用。
有没有人有什么想法?我正在使用 Chris 关于加入队列的另一篇文章作为指南,但到目前为止还没有成功。[http://digwp.com/2009/06/including-jquery-in-wordpress-the-right-way/]
很棒的文章。我似乎经常遇到这个问题,每次不得不为非表格数据使用表格时都会感到不舒服。
这是一个非常好的执行,做得很好!
我去年某个时候做了一个类似的功能来做到这一点,但你必须指定每行的元素数量。
在这种情况下它运行良好,但重用起来却是一场噩梦。从没想过检查顶部位置——一定会重用这种技术!
谢谢 :)
我实际上发现了一种方法,只使用 CSS 就能做到这一点。是的,你可以。
http://www.isegura.es/blog/two-columns-same-height-using-css-and-no-javascript-yes-you-can
仅仅因为你可以,并不意味着你应该这样做。
我有一个版本的代码,我必须将列数作为参数设置,但这要好得多 :)
我根据此创建了一个 jQuery 插件以保持链式调用。还对其进行了压缩。
希望你不介意 :) 随意 fork 或做其他任何事情。
https://github.com/krishandley/jQuery-Equal-Height-Blocks
你的插件实际上并没有保持链式调用。你需要返回对象:http://docs.jquery.com/Plugins/Authoring#Maintaining_Chainability
以下代码应该放在“each”循环之外吗?
// 处理最后一行
for (currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
这样可以节省大量不必要的设置高度操作…
是的,我也在看那个。首先,这段代码出现了两次。第一个实例,在 if (currentRowStart != topPostion) 之后是不必要的。第二个实例(在 // 处理最后一行之后)对 jQuery 集合中的每个项目运行一次,并将处理 . 这效率低下,因为你最终为该行中的每一列设置一次高度。
理想情况下,你应该在 each() 之后为每一行只设置一次高度。我确定对于只有少量行和列来说,性能影响很小。
另一个问题是,如果你在一个项目中设置了顶部或底部填充,则高度测量不准确。只是一些需要注意的事情。Tom Deater 的 equalize columns 插件解决了填充问题:http://tomdeater.com/jquery/equalize_columns/
但是,该插件不提供按行等高列的方法——而此代码可以做到。
哇!一个月前在哪里能找到这个。尝试修复这些该死的列花了几个小时。Dubweiser.net
使用“outerHeight”来获取带有填充/边距的元素的正确尺寸。
https://api.jqueryjs.cn/outerHeight/
我一直在寻找它。非常感谢。
我测试了这么多 jQuery 等高代码和插件,这个绝对是最好的……我想知道是否可以将其制作成插件?
很棒的脚本。当
.blocks
上激活了box-sizing: border-box;
时,它无法准确工作。我的快速修复是在应用于块时将总垂直填充添加到currentTallest
中。但是,我希望有一个不需要我设置填充的解决方案。特别是因为我喜欢border-box
。对于那些有带有填充的 div 的人
currentTallest = Math.max(currentTallest, $el.height());
改为
currentTallest = Math.max(currentTallest, $el.outerHeight());
感谢这个脚本。
谢谢 Chris!
所以我在使用 Chris 演示中的流体版本,但它存在一个小问题,我似乎无法解决。
问题
此解决方案几乎适用于流体宽度布局并在顶部位置发生变化时重置高度,但在页面首次加载时将其重置为该行中当前最高元素的原始高度。这是一个问题,因为自页面首次加载以来,最高元素的高度可能发生了变化,因为使用了像 em 这样的相对单位或因为段落的自动换行。
建议的解决方案
解决方案是将行的元素的高度设置为最高元素的当前高度,而不是原始高度。
你是否在框中使用过图像?如果有很多带有图像的框或文件大小很大的图像,JavaScript 将在图像加载之前运行。当每个图像加载完成后,一些框会被裁剪。
在窗口加载时尝试一下。
我确实这样做了。但我想知道我是否必须等待整个网站加载?如果我选择一个围绕图像的 div,.load() 似乎不起作用。
这里有一些我整理的类似内容
https://github.com/Sam152/Javascript-Grids
这正是我想要的!非常感谢 Sam、Chris 和 Stephen!
太棒了。非常感谢!!! :)
我有一个修改后的版本运行良好,除了浏览器窗口宽度减小时。
我为行中的项目设置了流体宽度和高度,这些宽度和高度会随着浏览器而减小。有一些媒体查询断点会更改每行的项目数。问题是,当缩小浏览器大小时,项目会变小,直到它们达到断点,然后每行的项目数减少,项目会再次变大以适应额外的空间。脚本在断点调整之前的较小尺寸下获取设置高度,因此设置高度不正确,并且行重叠。
有没有人知道如何解决这个问题?
我需要此技术的健壮版本,该版本处理流体和响应式布局、行、延迟图像、混合填充、边距、box-sizing、任意 DOM 顺序等。
所以这是我尝试制作一个等高插件来解决我遇到的实际问题,如果它能帮助任何人
https://github.com/liabru/jquery-match-height
这是我无需 JS 即可完成此操作的版本
http://jsfiddle.net/shay/3P7Nk/
尽管我认为 flexbox 和 display:table 都足够常见,可以被视为此类问题的首选解决方案。
@Liabru – 优秀的脚本,在存在填充、边距和 box-sizing 等问题的情况下,绝对可以更好地处理等高问题。我在一个正在开发的网站上对其进行了测试,我定位的 div 的高度现在不会在移动设备上折叠,之前会折叠。
必须说,其他脚本也很好!感谢你们所有人开发这些等高脚本并不断改进它们!
@Shay Acrich – 我喜欢你解决方案背后的想法。你不能只使用伪元素而不是你用来匹配高度的前缀元素吗?否则,我们那里会有一个仅用于样式的随机 div。
@Rich Dykins,伪元素的想法很棒!
这是更新后的实现,再次强调,无需 JS:http://jsfiddle.net/Ac5qG/2/
我尝试将其制作成一个 jQuery 插件 http://codekipple.com/conformity/
这仍然是一个有用的代码片段,但需要一些修正
更正错别字:将
topPostion
改为topPosition
使用
.offset().top
代替.position().top
- 更可能按预期工作并正确区分行,尤其是在响应式布局中。使用.position()
可能会失败,因为您在行(元素)或某些父元素上设置了position:relative
。使用
[]
代替new Array()
-new Array()
带有许多陷阱且没有比[]
更好的优势,并且最好劝阻 JS 开发人员完全避免使用它。正如上面一些评论者所指出的,在页面中使用块内包含图像时,通常需要使用此方法,因此,在
$(window).load( ... )
中使用此方法的说明将很有帮助。谢谢!
这些是一些有用的技巧,欢迎向我的插件提交拉取请求!
https://github.com/codekipple/conformity
我以为这在我的新网站上可以正常工作,但这是一个它无法正常工作的案例,我绞尽脑汁也想不出它为什么无法对齐行。
网址是 http://www.drapertools.org.ukcatprods.pgm?name=Spirit%20Levels&cat=00007875
选择查看“所有产品”和“图库视图”。
页面大约向下滚动一半时,对齐方式就会出现问题。
注意:它似乎在 Chrome 和 Safari 中可以正常工作,但在 Firefox 中不行,除非是最新版本的 Firefox?
我尝试了您修改后的代码,但无法使其工作,但我看到您的演示仍然使用 Stephen 的代码。
感谢您对此的任何帮助。