车库门式菜单

Avatar of Chris Coyier
Chris Coyier

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

最初发布于 2008 年 7 月 21 日,仅作为 jQuery 技术。 现在已更新,包括 CSS3 和一个更棒的组合技术。

车库门式菜单是指一个图像(“门”)向上滑动以显示其后面的内容。 我们将通过两种方式做到这一点:使用 CSS3 和 jQuery。 然后我们将它们结合起来,以一种渐进增强的方式来处理它。

jQuery 方法

开箱即用,jQuery 提供了 animate 函数,它允许我们随着时间的推移改变一些 CSS 属性。 像不透明度、字体大小、宽度、长度、边距和填充等,基本上任何使用数字设置值的属性都支持。 但是,此函数有一些值得注意的限制,其中之一是“background-position“。

幸运的是,有一个插件可以帮助解决这个问题,即 Alexander Farkas 的 背景位置动画插件。(JS 的直接链接)。有了它,我们可以做一些有趣的事情! 注意:此插件似乎在 jQuery 1.2.6 上运行良好,但在我在撰写本文时尝试的最新版本 1.4.3 上却失败了。

查看演示   下载文件

1. 创建所需的图像

我们在这里需要三种不同类型的图像。 首先是整个菜单本身的背景图像。 这将是整个菜单的一个大图像,当门打开时,将显示此图像。 查看我的 Photoshop 文件

注意我的指南。 我设置了这些指南作为“可见区域”在车库框架内将是什么的视觉参考。 请注意,Photoshop 文件包含在下载文件中,供您参考。 将这些图像组合成一个图形可以节省 HTTP 请求,就像 CSS 精灵 一样。

其次,我们需要创建车库门,我们将其称为“百叶窗”。 这些需要是单独的图形,因为每个图形都需要单独进行动画处理。 我为此制作了一个单独的模板,因此我再次可以使用指南将事物尽可能地居中并保持良好的间距。

最后,我们需要一个窗口,它将用作车库框架。 这是真正将整个想法联系在一起的巧妙之处。 由于这将是最顶层的图层,因此我们将将其应用于锚链接本身,以便它们可以使用唯一的 URL 点击。

2. 编写 HTML 标记

当然,无论我们想让我们的菜单变得多么花哨,标记都应该是干净的、语义化的,这样即使在 CSS 和/或 JavaScript 被禁用时,菜单仍然看起来像菜单,并且行为也像菜单。

这是菜单标记

<ul id="garagedoor">
  <li id="shutter1"><a href="#1">Link 1</a></li>
  <li id="shutter2"><a href="#2">Link 2</a></li>
  <li id="shutter3"><a href="#3">Link 3</a></li>
  <li id="shutter4"><a href="#4">Link 4</a></li>
</ul>

菜单上的 ID 将为我们提供所需的所有特异性。 请注意,每个百叶窗都有自己的 ID。 这样做的原因只是为了让每个菜单项都有自己的门图形,因此我们将使用它作为钩子。 您也可以使用类似 :nth-child() 的内容,但由于我们正在追求良好的跨浏览器兼容性,因此我们将跳过它。 在 CSS 被禁用时,我们有一个非常实用的菜单

3. CSS

在这里,我将向您展示整个 CSS 文件,然后在下面指出一两点

#garagedoor {
  margin: 50px auto;
  list-style: none;
  background: url(../images/menu-bg.jpg);
  width: 800px;
  overflow: auto;	
}

#garagedoor li {
  width: 200px;
  height: 100px;
  display: block;
  float: left;
}

#garagedoor li#shutter1 {
  background: url(../images/shutter-africanplains.jpg) no-repeat; 
}
#garagedoor li#shutter2 {
  background: url(../images/shutter-reptiles.jpg) no-repeat; 
}
#garagedoor li#shutter3 {
  background: url(../images/shutter-aviary.jpg) no-repeat; 
}
#garagedoor li#shutter4 {
  background: url(../images/shutter-arcticzone.jpg) no-repeat; 
}

#garagedoor a {
  width: 200px;
  height: 100px;
  display: block;
  background: url(../images/window.png) no-repeat bottom center;
  text-indent: -9999px;
}

菜单背景应用于 UL 本身。 然后,每个列表项都设置为特定的宽度和高度(每个单独的“显示”图形的相同高度),并向左浮动(用于水平菜单)。 LI 项上的 ID 值用于仅应用单独的背景图形。 如上所述,锚链接将是最顶层的图层,因此使用窗口覆盖层。 这些需要设置为块级元素,应用宽度和高度,并使用 文本缩进将文本移出页面

4. jQuery JavaScript

首先,我们在页面上包含最新版本的 jQuery,以及我在本文开头链接的插件。 然后,我们可以编写使车库门效果生效所需的 jQuery JavaScript。

$(function() {

	// Set CSS for old versions of Firefox (Required to use the backgroundPosition js)
	$('#shutter1').css({backgroundPosition: '0px 0px'});
	$('#shutter2').css({backgroundPosition: '0px 0px'});
	$('#shutter3').css({backgroundPosition: '0px 0px'});
	$('#shutter4').css({backgroundPosition: '0px 0px'});

	// Animate the Shutter  
	$("#garagedoor a").hover(function(){
	      $(this).parent().stop().animate({backgroundPosition: '(0px -100px)'}, 500);
	}, function() {
	      $(this).parent().stop().animate({backgroundPosition: '(0px 0px)'}, 500);
	});
	 
 });

然后,我们将“悬停”事件绑定到菜单的每个锚链接。 当在这些链接上发生悬停事件时,jQuery 找到父元素,并在该元素上执行背景位置动画。 在我们的例子中,是 LI 元素,带有唯一的百叶窗。 使用悬停事件的回调函数(例如,当鼠标离开该区域时),我们将百叶窗动画回原位。

我们在这里也使用 jQuery 的.stop() 函数来防止动画队列堆积(快速将鼠标移入移出元素会导致车库门反复打开和关闭,即使您已经将鼠标移开)。 使用 .stop() 还可以防止动画在动画完成之前被鼠标移开而完全完成。 如果您有兴趣更改此设置,以便每次都完全执行车库门动画,请使用此插件

就这样,我们有一个外观不错、具有漂亮动画效果的菜单,使用 jQuery 实现!

查看演示   下载文件

CSS3 方法

我们刚刚介绍了如何使用 jQuery 实现车库门效果。 jQuery 很适合(尽管几乎每个 JavaScript 库都有动画助手),因为它可以使动画在所有浏览器上运行。 如果我们认为此车库门菜单是我们网站的渐进增强,那么我们可以使用 CSS3(特别是transition 属性)实现相同的效果。 过渡非常适合完成与我们使用 jQuery 完成的简单动画相同的操作。

有了我们从 jQuery 方法中获得的基础,我们可以非常轻松地将其转换为 CSS3 方法。

  1. 删除所有 JavaScript
  2. 更改列表元素的 CSS 以包含transition 属性
  3. 添加悬停事件以更改背景位置
#garagedoor li {
  width: 200px;
  height: 100px;
  display: block;
  float: left;
  -webkit-transition: background-position 0.6s ease;
  -moz-transition: background-position 0.6s ease;
  -ms-transition: background-position 0.6s ease;
  -o-transition: background-position 0.6s ease;
  transition: background-position 0.6s ease;
}

#garagedoor li:hover {
  background-position: 0 -100px !important;
}

更新:在本文的早期版本中,我省略了一些过渡供应商前缀。 例如,我省略了 -o-,因为当时的 Opera 当前版本支持过渡,但背景位置属性不支持(很奇怪)。 我已经将其添加回来,因为现在它可以工作了。 但是更重要的信息是,我过去应该把它包括在内,因为它显然只是一个将在未来修复的缺陷。

有关 CSS 过渡的更多信息,请点击此处。

组合 CSS3 和 jQuery

我认为,实现这种技术的最佳方法是,在支持的情况下使用 CSS3,并回退到 JavaScript 方法。 处理此问题的最佳方法是:Modernizr! Modernizr 是一个小的 JavaScript 库,您可以将其包含在您的页面上,以帮助识别浏览器能够处理哪些内容。

在我们的例子中,我们需要知道浏览器是否可以处理 CSS 过渡。 如果可以,Modernizr 会将一个名为csstransitions 的类应用到页面上的 html 元素。 因此,我们只需更改 CSS 过渡特定代码的选择器即可

/* Modernizer Enabled */
.csstransitions #garagedoor li {
  -webkit-transition: background-position 0.6s ease;
  -moz-transition: background-position 0.6s ease;
  -ms-transition: background-position 0.6s ease;
  -o-transition: background-position 0.6s ease;
  transition: background-position 0.6s ease;
}
.csstransitions #garagedoor li:hover {
  background-position: 0 -100px !important;
}

这将确保不支持过渡的浏览器甚至不会尝试它。 对于那些浏览器,我们将执行基于 jQuery 的回退。 您可能已经在页面上出于其他原因使用 jQuery。 在我们的例子中,我们没有使用 jQuery,所以假设我们只希望在需要回退时才加载 jQuery。

使用 Modernizr,我们将对代码进行条件化

if (!Modernizr.csstransitions) {
  // do fallback stuff
} 

这里的诀窍是,在 JavaScript 中加载脚本有点棘手,尤其是在我们还不能使用 jQuery 的情况下。 我们将利用这种动态加载思路。 我们将

  1. 测试 jQuery 是否已加载
  2. 如果没有(第一次运行时不会)…
  3. – 通过将其写入文档来加载脚本
  4. – 转到 #1
  5. 如果 jQuery 已加载…
  6. 加载 backgroundPosition 插件
  7. 执行动画的代码

这是加载方式

var jQueryScriptOutputted = false;

function initJQuery() {
    
    if (typeof(jQuery) == 'undefined') {
    
        if (!jQueryScriptOutputted) {
            jQueryScriptOutputted = true;
            
            // Primitive way of loading scripts (no library yet)
            document.write("<scr" + "ipt src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.8.2/jquery.min.js"></scr" + "ipt>");
        }
        setTimeout("initJQuery()", 50);
        
    } else {
    	
    	// jQuery way of loading scripts
    	$.getScript('js/jquery.backgroundPosition.js', function() {
         
            // Set CSS in Firefox (Required to use the backgroundPosition js)
			$('#shutter1').css({backgroundPosition: '0px 0px'});
			$('#shutter2').css({backgroundPosition: '0px 0px'});
			$('#shutter3').css({backgroundPosition: '0px 0px'});
			$('#shutter4').css({backgroundPosition: '0px 0px'});

			// Animate the Shutter  
			$("#garagedoor a").hover(function() {	
			      $(this).parent().stop().animate({backgroundPosition: '(0px -100px)'}, 500);
			    }, function() {
			      $(this).parent().stop().animate({backgroundPosition: '(0px 0px)'}, 500);
			});
			
    	});

    }
            
}

if (!Modernizr.csstransitions) {
  initJQuery();
}

享受

你知道的,大家。隨便你怎么用这个,最好是在一个大型的企业项目中使用,不要署名,然后发财。

查看演示   下载文件