向上移动菜单

Avatar of Chris Coyier
Chris Coyier 发布

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

有一段时间前,我收到了 Dirk Tucholski 的一封电子邮件,他向我展示了一个名为 FLOWmarket 的网站。他想知道菜单系统是如何工作的。我觉得它看起来很整洁,所以开始着手用我的方式构建它。这个想法是,有一个很长的垂直链接菜单,并非所有链接都可见。当您上下滚动鼠标时,菜单会自动滚动以显示更多菜单项,并突出显示鼠标当前悬停的链接。

查看演示   下载文件

HTML

一个典型的菜单

<div id="menu">

	<ul>

		<li><a href="#">Nature</a></li>
		<li><a href="#">Receivability</a></li>
		<li><a href="#">Alone time</a></li>

 		<!-- etc -->

	</ul>

</div>

初始 CSS

我们正在设置一个静态高度,因此让我们确保溢出值(目前)设置为 overflow: auto; 这样,无论 JavaScript 如何,菜单都将滚动且可访问。否则就是基本的样式。

#menu { 
  height: 360px;
  overflow: auto;
}

#menu ul { 
  list-style: none; 
}

#menu a { 
  text-decoration: none; 
  display: block; 
  color: black; 
}

初始 JavaScript

这里的想法是等待菜单链接被悬停,然后相应地进行调整。我们将应用一个悬停类进行样式设置,然后上下移动一个内部 div(我们将附加它)以实现效果。但是到底向上或向下移动多少?为此,我们需要确切地知道我们正在悬停哪个链接。位置较高的链接(列表中更靠下)需要比位置较低的链接滚动列表更远。我们将获取此位置并应用速度乘数以获得要偏移的距离。要获取位置,我们将循环遍历它们并应用数据属性。

$("#menu").css("overflow", "hidden").wrapInner("<div id='mover' />");

var $el,
    speed = 13.5,    // needs to be manually tinkered with
    items = $("#menu a");
    				
items
.each(function(i) {
	$(this).attr("data-pos", i);
})
.hover(function() {

	$el = $(this);
	$el.addClass("hover");	
	
	$("#mover").css("top", -($el.data("pos") * speed - 40));
	// 40 is the top padding for the fadeout
						
}, function() {
	$(this).removeClass("hover");
});

请注意,您可以访问 HTML5 数据属性(例如 <div data-pos=1>),例如 $("div").data("pos");,这简洁而酷炫。

淡出效果

如果您在 WebKit 浏览器中查看演示,您会看到菜单在滚动时从顶部和底部淡出。我只是通过使用在菜单顶部和底部绝对定位的 :before 和 :after 伪元素来实现这一点,这些伪元素具有白色到透明的渐变。

#menu:before { 
  content: " "; 
  position: absolute; 
  top: 0; 
  left: 0; 
  height: 50px;
  width: 100%; 
  z-index: 2; 
  background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255,255,255,100)),color-stop(1, rgba(255,255,255,0))); 
}

#menu:after { 
  content: " "; 
  position: absolute; 
  bottom: 0; 
  left: 0; 
  height: 50px; 
  width: 100%; 
  z-index: 2;
  background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255,255,255,0)),color-stop(1, rgba(255,255,255,100))); }

根据需要使用 其他浏览器前缀

这个“速度”问题

每个菜单项向上或向下移动的距离受速度乘数的影响。您可以在上面的 JavaScript 中看到它被设置为一个看起来相当随意的 13.5。我玩了一会儿,试图找到一种数学方法来根据菜单项数量、高度等计算完美的速度乘数,但没有得到任何好的结果。如果您能想到什么,请告诉我。当然,最好不必每次菜单更改时都调整该乘数。

键盘导航

以当前速度,这个菜单很难导航到您选定的精确菜单链接。为了帮助解决这个问题,我们可以添加一些键盘导航。这是通过监视 document 上的 keydown 事件并触发一个函数来完成的。为了减少代码重写,我们将跟踪当前活动的菜单项,根据向上箭头或向下箭头是否被按下调整它,然后相应地触发 mouseentermouseleave 事件,这些事件已设置为处理菜单功能。

$(document).keydown(function(event) {

	cur = $(".hover").attr("data-pos");
				
	// Down arrow
	if (event.keyCode == 40) {
									
		$("[data-pos=" + cur + "]").trigger("mouseleave");
		if (cur != max) { cur++; }
		$("[data-pos=" + cur + "]").trigger("mouseenter");
		
	}
	
	// Up arrow
	if (event.keyCode == 38) {
	
		$("[data-pos=" + cur + "]").trigger("mouseleave");
		if (cur > 0) { cur--; }
		$("[data-pos=" + cur + "]").trigger("mouseenter");
		
	}
	
});

这里唯一未显示的部分是我们设置 cur 变量并在悬停函数中设置它的位置,但所有这些都在实时演示中。

查看演示   下载文件

关于可用性的胡言乱语!

这个想法的核心,即比用户预期更快地滚动菜单,不利于可用性。由于不熟悉且敏感的移动,难以选择您要查找的确切链接。我意识到了这一点。键盘导航在一定程度上有所帮助,但这可能也是一个不熟悉的想法。

这不是适用于世界上每个长菜单的解决方案(另请参见 此处)。这更像是一种有趣的效果。也许对于菜单不太重要的网站。也许作为显示诗歌的一种方式。它是一种很酷的使用体验,因此,如果这种体验确实适合该网站,那么可能可以接受一点可访问性方面的损失。我认为 FLOWmarket 网站(此效果的来源)很棒。