超长下拉菜单的解决方案

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我喜欢对文章标题充满信心,但现实情况是,对于超长下拉菜单,这只是一个**可能的**解决方案。超长下拉菜单的问题在于,下拉菜单本身可能会超出网站的“折叠”区域。也就是说,超出浏览器窗口的可见区域。因此,为了访问这些位于底部的菜单项,您需要滚动浏览器窗口。对于我们这些鼠标上带有某种滚轮的人来说,这不是什么大问题。但对于没有滚轮的人来说,这些较低的菜单项完全无法访问,因为使用浏览器滚动条意味着鼠标要离开菜单(并且可能导致菜单关闭)。

 

查看演示   下载文件

 

我第一次在 Media Temple 账户中心页面上看到这个想法的实际应用。他们有一个用于“域名”的下拉菜单,其中列出了您在他们那里托管的每个域名。这可能是一个非常长的列表。Media Temple 实现了一种技术,当您向下滚动时,菜单实际上会以加速的方式移动。

当然,当我准备截取屏幕截图时,我发现他们之前采用的那个很酷的解决方案已经不见了。这让我有点好奇他们遇到了什么麻烦,但不管怎样,让我们继续吧。以下是尝试可视化这个想法:

jQuery 实现

我将把所有代码都放在这里,以便快速参考。我已经添加了注释,因此应该很容易理解。代码超过 60 行,但不要担心,它相当简单。

  1. 为下拉菜单设置最大高度
  2. 悬停时显示子菜单
  3. 根据子菜单的高度计算速度倍数
  4. 监视菜单中的鼠标移动
  5. 根据倍数滚动菜单
  6. 鼠标移出时关闭菜单
var maxHeight = 400;

$(function(){

    $(".dropdown > li").hover(function() {
    
         var $container = $(this),
             $list = $container.find("ul"),
             $anchor = $container.find("a"),
             height = $list.height() * 1.1,       // make sure there is enough room at the bottom
             multiplier = height / maxHeight;     // needs to move faster if list is taller
        
        // need to save height here so it can revert on mouseout            
        $container.data("origHeight", $container.height());
        
        // so it can retain it's rollover color all the while the dropdown is open
        $anchor.addClass("hover");
        
        // make sure dropdown appears directly below parent list item    
        $list
            .show()
            .css({
                paddingTop: $container.data("origHeight")
            });
        
        // don't do any animation if list shorter than max
        if (multiplier > 1) {
            $container
                .css({
                    height: maxHeight,
                    overflow: "hidden"
                })
                .mousemove(function(e) {
                    var offset = $container.offset();
                    var relativeY = ((e.pageY - offset.top) * multiplier) - ($container.data("origHeight") * multiplier);
                    if (relativeY > $container.data("origHeight")) {
                        $list.css("top", -relativeY + $container.data("origHeight"));
                    };
                });
        }
        
    }, function() {
    
        var $el = $(this);
        
        // put things back to normal
        $el
            .height($(this).data("origHeight"))
            .find("ul")
            .css({ top: 0 })
            .hide()
            .end()
            .find("a")
            .removeClass("hover");
    
    });
    
    // Add down arrow only to menu items with submenus
    $(".dropdown > li:has('ul')").each(function() {
        $(this).find("a:first").append("<img src='images/down-arrow.png' />");
    });
    
});

HTML 和 CSS

我犹豫是否要在这里放置大量的 HTML 和 CSS 代码,因为它们真的没什么意思。无论如何,您可以下载代码,所以可以去那里看看。它只是一个普通的语义嵌套无序列表和一些非常基本的样式。

测试

我从 IE 6 开始,在所有浏览器中都进行了测试,看起来效果不错。

 

查看演示   下载文件