【问题标题】:How to make a list of elements on 2 columns with equilibrated height?如何在具有平衡高度的 2 列上制作元素列表?
【发布时间】:2014-06-27 18:14:24
【问题描述】:

我有一个文章列表,必须分两列显示。

一切都很好,只是文章的高度可能有很大不同,结果是我可以有一列比另一列长得多。

这不是一个大问题,但结果并不干净。你可以看看附上的图片看看。

这是因为,在我循环之前,我计算了所有文章并将结果除以 2:

这是代码(在我的模板中稍微复杂一点,但它只是 html 的东西)

// make a query to get the number of articles
$count_articles = 20;
$i = 0;

if ($i == 0) {
    echo '<div class="column_1">';
}

if ($i <= 10) {
    echo '<div style="float:left;width:350px;">';
    echo $articles
    echo '</div><div style="clear:both;"></div>';
    $i++;
}

if ($i == 11) {
    //close column_1, open column_2
    echo '</div><div class="column_2">';
}

if ($i >= 11 && $i <= 20) {
    echo '<div style="float:right;width:358px">';
    echo $articles
    echo '</div>';

    if ($i ==20) {
        //close column_2
        echo '</div>';
        }
    $i++;
}

您是否知道在我进行循环之前获取文章高度的方法或其他方法(可能使用 javascript)?

【问题讨论】:

  • 我是否认为您希望以确保列表高度相似的方式将文章分布在每一侧?
  • 什么是$articles?每篇文章都是一个数组吗?
  • @AndrewPolland 是的,高度非常相似(如果不完美也没关系)但我想避免第 1 列和第 2 列之间的巨大差异
  • @MarkM $articles 包含所有文章。我做了一个 foreach 循环来列出所有的文章。

标签: javascript php jquery html css


【解决方案1】:

两种方法:服务器端或客户端。 (同样是float: left 解决方案,但这是不可预测且难以控制的,或者可能是新的 CSS3 列布局)。

它们都采用相同的算法将文章分成两个(大约)等高的列:

let totalHeight, leftColumnHeight = 0
let leftColumn, rightColumn = []

foreach article do
    totalHeight += getHeightOf(article)
end

foreach article do
    if leftColumnHeight < totalHeight / 2 then
        push article to leftColumn
        leftColumnHeight += getHeightOf(article)
    else
        push article to rightColumn  
end

这两种方式的区别在于getHeightOf的实现。

客户端,使用jQuery,可以使用$('#articleId').outerHeight()。这具有精确的优点,但要求预先呈现所有文章(outerHeight 不适用于隐藏元素或未附加到 DOM 的元素),从而导致显示错误在算法开始之前给用户布局($(document).ready 之后的某个时间)。您可以通过在屏幕外呈现文章 (position: absolute; left: -9999px;) 来缓解这种情况,但随后用户可能会盯着一个空的文章列表,直到 JavaScript 代码启动。

服务器端可以近似文章的高度。您实际上并不需要像素高度,只需要文本的总行数,具体取决于最大线宽。如果您还有内嵌图像,这会很困难并且可能会导致与what's actually displayed in browsers 不同的值。但是,如果您设法提出了一个足够好的算法,您就不必担心最终用户可以看到突然的布局更改或延迟渲染。

因此,总而言之,没有完美的解决方案,因为问题有很多变数,其中大部分与文章的实际内容有关。 JavaScript 是最受欢迎的,但在我看来,它有一些最终用户不会欣赏的非常强硬的权衡。服务器端实现起来很棘手并且如果做得不好(视图中的逻辑,即使它是布局逻辑),也会在某种程度上破坏 MVC 约定。

【讨论】:

  • 很好的解释。我知道没有完美的解决方案,我选择了 Javascript 解决方案。您如何看待 AndrewPolland 的回答?好像是神一样的。
  • 是的,它会起作用,但正如我所说,在应用该代码之前,您可能需要将 #temp 置于屏幕外。
  • 是的,#temp 是隐藏的,否则用户可以在很短的时间内看到它。
【解决方案2】:

所以我只是快速地把一些东西放在一起用 jQuery 来做这件事。可能需要一些工作来适应您的情况,但基本想法似乎运作良好。

所以基本上我有一个带有文章的&lt;div&gt;。然后每列还有一个&lt;div&gt;。像这样:

<div id="col1"></div>
<div id="col2"></div>
<div id="temp">
    <!--Articles Here-->
</div>

然后我使用一些 jQuery 循环遍历每篇文章,检查每列的高度和 append() 文章到最短的列。

$( document ).ready(function() {

    $( ".article" ).each(function( index ) {
        var col1Height= $("#col1").height();
        var col2Height= $("#col2").height();

        if(col1Height < col2Height){
            $("#col1").append($(this));
        }else{
            $("#col2").append($(this));
        }
    });

});

这应该使列的高度相当均匀,而不需要太多努力。我确信还有其他方法可以使列的高度更接近,但正如我所说,我认为这是一个不错的简单解决方案。

jsFiddle 在这里:http://jsfiddle.net/4kpLr/1/

【讨论】:

  • 接受的答案:非常好的和简单的解决方案。一件事更难解决​​。最初,文章是按字母顺序排列的(使用 php),现在顺序是错误的。我想很难将字母顺序和基于每列高度的顺序结合起来。
  • @SébastienGicquel 很高兴你喜欢它。 :) 我认为,只要您首先按字母顺序列出元素,这将为您提供最接近的信息。因为它会首先对列表中较高的那些排序,所以它们仍然具有优先权。
  • 也许他希望“第一”篇文章在顶部,而不是在第一列。这将更难实现。
  • @SergiuParaschiv 抱歉,可能解释得不好。但这基本上就是他会得到的。它将在合并的 2 列中按字母顺序向下排列,但向下不会有完美的分隔线。
  • 酷,对不起,你是对的,这正是你的版本所做的。
【解决方案3】:

例如,您可以使用 jquery

$('.classofblock').each(function(index, elem) {
    var heightOfElem = $(elem).height();
    // you can even console this height
    console.log(heightOfElem);
    // or do something else things
    // if you want set height, so do next
    $(elem).css('height', 1000'); // it's automatically in px
});

但你应该把这段代码包装在

$(document).ready(function() {
    // here is your code...
});

【讨论】:

    【解决方案4】:

    对于具有平衡高度的 2 列,在 jquery 代码下方添加

    $(document).ready( function(){ var oneHeight = $(".column_1").height(); var twoHeight = $(".column_2").height(); if (oneHeight > twoHeight){ $(".column_2").height(oneHeight)} else{ $(".column_1").height(twoHeight)}; })

    【讨论】:

    • 我理解你的回答,但在这里不起作用。参见 AndrewPolland 解决方案
    猜你喜欢
    • 1970-01-01
    • 2013-02-20
    • 2018-07-18
    • 2018-03-19
    • 2020-09-19
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多