【问题标题】:How to split a nested navigation into columns with almost equal heights如何将嵌套导航拆分为高度几乎相等的列
【发布时间】:2012-12-13 01:37:05
【问题描述】:

我正在开发一个带有导航覆盖(节点和子节点)的响应式网站。导航应拆分为 4 列用于桌面视图或 2 列用于平板电脑视图。它是一个嵌套列表导航,因此在其周围构建了一个带有<ul /> 的列。我的想法是,只需将导航写在 1 列中,然后使用 jquery 将其动态排列为 4 或 2 列。

html:

<!-- overlay -->
<nav class="overlay"> 
    <!-- ul for column -->
    <ul>
        <!-- nodes & subnodes -->
        <li><a href="#">node</a>
            <ul>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
            </ul>
        </li>
        <li><a href="#">node</a>
            <ul>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>                    
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
                <li><a href="#">subnode</a></li>
            </ul>
        </li>
        <li><a href="#">node</a> ...
    </ul>
</nav>

我写了这个函数:

    $.fn.arrangeObjects = function(wrapWith, maxCols) {

        this.each(function() {
            if ($(this).parent(wrapWith).length) $(this).unwrap();
        });

        this.parent().each(function() {
            var $el = $(this).children();
                amount = $el.length,
                wrapAmount = amount / maxCols;

            for (var i = 0; i < amount; i += wrapAmount) {
                $el.slice(i, i + wrapAmount).wrapAll('<'+ wrapWith +'/>');
            }
        });
    };

为台式机而生:

$(".overlay > ul > li").arrangeObjects('ul', 4);

为平板电脑拍摄:

$(".overlay > ul > li").arrangeObjects('ul', 2);

此解决方案将节点等分拆分为列。不幸的是,这样看起来不太好:
http://bern09.ch/notgood.png

我想要实现的是具有几乎相同的列高的排列,如下所示:
http://bern09.ch/good.png

我必须以某种方式尊重子节点的数量,但我真的不知道如何实现这一点。也许有人有很好的提示,我们将不胜感激。

【问题讨论】:

  • 似乎节点数只是您应该考虑的标准之一。您可能需要计算里面的内容量。有关在这些节点中可以找到的内容的更多信息将很有帮助。我喜欢你的想法,我现在正在研究我的解决方案:)我会在完成后立即分享:)
  • 感谢您的努力 op1ekun。您询问有关节点内容的更多信息,您的确切含义是什么信息?我的问题只是关于拆分导航条目(这就是我对“节点”的意思)。请让我知道我是否应该编辑上面的代码以获取更多信息。
  • 好的,你只需要它来导航,而且都是关于链接的 :) 我固定在更通用的解决方案上,这就是我要求内容的原因。

标签: jquery html split responsive-design


【解决方案1】:

首先 - 排序和分组应尽可能在后端进行,在这种情况下也是如此。

当您在 UL 的每一列中对结果进行排序和分组后,您可以将 CSS3 列与旧浏览器的 jQuery 后备一起使用,explained here

.overlay {
    -moz-column-count: 4;
    -moz-column-gap: 10px;
    -webkit-column-count: 4;
    -webkit-column-gap: 10px;
    column-count: 4;
    column-gap: 10px;
}

但是,如果你坚持使用 JavaScript 来做所有事情,you could use Multi Column List jQuery plugin.
它似乎提供了您需要的解决方案。但是它是在不久前编写的,因此您可能需要针对最新的 jQuery 版本修改其中的部分内容,并且可能会稍微满足您的需求。

【讨论】:

  • 我不能同意你的观点......虽然可以在后端进行排序(并且在大多数情况下这是一个更好的解决方案),但我相信分组似乎是一项前端工作。
  • 但是,您会为 CSS 列和隐式获得 +1 ;) 链接到 Masonry 插件。谢谢!
  • +1 用于 CSS 教程中的伟大砌体。使用 CSS 是一个简单而快速的解决方案,但不幸的是不是 100% 支持的。所以我选择了 JavaScript,我们无论如何都要使用它。
  • 另一个布局库metafizzy.co/blog/packery-preview 修复了几个砌体问题:)
【解决方案2】:

好的。我懂了。这有点棘手。昨天我开始计算每一列的高度,但我相信这种方法更灵活:

    this.parent().each(function () {
        var $subnodes       = $(this).children();

        // true will cause counter increment
        // false will cause counter decrement
        var inc     = true;
        var cols    = [];

        for (var i = 0; i < maxCols; i++) {
            cols.push($('<ul></ul>'));
            cols[i].appendTo($(this));    
        }

        function sortByHeight(a, b) {
            return $(a).height() > $(b).height() ? 0 : 1;
        }

        $subnodes = $subnodes.sort(sortByHeight);

        var i = 0;
        $subnodes.each(function () {
            // logic for left and right boundry
            if (i < 0 || i === maxCols) {
                inc = !inc;
                // this will cause node to be added once again to the same column
                inc ? i++ : i--;
            }

            cols[i].append($(this));

            inc ? i++ : i--;
        });
    });

这是一个概念。首先,我按所​​有节点的高度(从最高到最低)对所有节点进行排序,然后将它们附加到从左到右再到后的列(由 maxCols 指定)。它不如你的漂亮,不幸的是打破了 wrapAll 的使用(我非常喜欢它)。我已经在进行一个小优化,它将使用threshold 参数。当最短和最长列之间的高度差大于阈值时,最长列的最后一个元素将移动到最短列。那么它应该看起来更自然。让我知道这是否是您正在寻找的。​​p>

【讨论】:

  • 万分感谢队友 :) 这看起来是一个非常聪明的解决方案。我有一个类似的想法,特别是使用阈值参数。至少它失败了,因为缺乏对小而重要的细节的关注。我会尽快给你的美女试一试,然后回来!
  • 没问题 :) 很有趣 ;)
  • 首先,祝你新年快乐 op1ekun :) 我尝试了你的解决方案,令我惊讶的是,它可以通过一对一的粘贴来工作,很好的工作伙伴!这些块的排列高度几乎相同,看起来好多了。唯一的问题是(这是我的错,因为我忘了提及)导航块应该尊重 HTML 中的顺序。我将尝试更改您的脚本以使其正常工作。如果您有解决此问题的主要想法,最好更新解决方案,否则我会将其标记为已接受,因为您向我展示了要走的路。这次真是万分感谢。我会及时通知你的。
  • 太棒了 :) 很高兴能帮上忙!关于你的问题。这是否意味着排序不再是一种选择?
  • ...或者我们必须更改参数函数以根据顺序对高度进行排序?
猜你喜欢
  • 2011-10-15
  • 2018-10-04
  • 1970-01-01
  • 2011-03-22
  • 2015-02-24
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 2021-09-17
相关资源
最近更新 更多