The Five Simple Steps 网站有一个响应式设计,带有一个巧妙的功能。 当浏览器窗口变窄时,右上角的菜单会从常规的链接行转换为下拉菜单。
当您在小屏幕上(此处显示 iPhone)并点击下拉菜单时,您将获得一个界面,用于选择一个选项,每个选项都很大且易于选择。
这确实比一个小链接更容易选择要前往的地方。 是的,它是两步而不是一步,但这是有争议的,因为您可能必须放大才能点击正确的链接。
HTML 代码
这两个菜单的 HTML 代码不同。 据我所知,您无法将<select>
和<option>
元素样式化为<a>
或反之。 所以我们需要两者。 您只需将两者都放在标记中。 这就是 Five Simple Steps 所做的
<nav>
<ul>
<li><a href="/" class="active">Home</a></li>
<li><a href="/collections/all">Books</a></li>
<li><a href="/blogs/five-simple-steps-blog">Blog</a></li>
<li><a href="/pages/about-us">About Us</a></li>
<li><a href="/pages/support">Support</a></li>
</ul>
<select>
<option value="" selected="selected">Select</option>
<option value="/">Home</option>
<option value="/collections/all">Books</option>
<option value="/blogs/five-simple-steps-blog">Blog</option>
<option value="/pages/about-us">About Us</option>
<option value="/pages/support">Support</option>
</select>
</nav>
我们现在就使用这种方法。
CSS 代码
默认情况下,我们将使用display: none;
隐藏选择菜单。 这实际上对可访问性有利,因为它会将冗余菜单隐藏在屏幕阅读器中。
nav select {
display: none;
}
然后,使用媒体查询,我们将在某个特定宽度进行切换。 您可以自行确定(这里有一些标准断点)。
@media (max-width: 960px) {
nav ul { display: none; }
nav select { display: inline-block; }
}
但是现在您必须维护两个菜单?
是的,这是一个问题。 也许您的菜单是动态创建的,您无法轻松控制输出。 也许您和手工制作菜单,但希望确保您不会意外使菜单不同步。 我们可以通过从原始菜单动态创建下拉菜单来解决这个问题。
使用 jQuery,我们可以用几行代码完成。
// Create the dropdown base
$("<select />").appendTo("nav");
// Create default option "Go to..."
$("<option />", {
"selected": "selected",
"value" : "",
"text" : "Go to..."
}).appendTo("nav select");
// Populate dropdown with menu items
$("nav a").each(function() {
var el = $(this);
$("<option />", {
"value" : el.attr("href"),
"text" : el.text()
}).appendTo("nav select");
});
然后,要使下拉菜单实际起作用……
$("nav select").change(function() {
window.location = $(this).find("option:selected").val();
});
但是,下拉菜单是不是有点侵入性?
有点。 如今,大多数小屏幕都是移动设备,大多数移动设备都支持 JavaScript,因此这不是一个大问题。 但是,如果您想确保它在有或没有 JavaScript 的情况下都能正常工作,我有一篇关于此的文章。
演示和下载
视频
如果您是从某个无法调整浏览器大小并进行操作以查看我们到底在谈论什么的地方阅读本文,那么这里有一个简短的视频示例。
这让我笑喷了。 我今天早上刚花了一个小时在谷歌上搜索这个问题的解决方案。 您太棒了,先生。
我个人不喜欢下拉链接菜单。 但这在某些情况下可能有用(比如您找到的示例网站)。
而且,我讨厌这种冗余。 我认为,必须使用 jQuery 来修复它并没有好多少。
这很酷。 对于大型导航菜单来说,这是一个不错的选择。 我认为我不会把它用于小型菜单。
JQuery 这里确实很冗余。 您也可以轻松地通过 DOM 甚至 ES5 方法来实现。 当前的移动浏览器引擎已经足够现代了,所以您不必担心旧的和有限的引擎,比如 IE。
jQuery 可以做的一切都是冗余的,因为它只是 JavaScript,可以用这种方式编写。 我在这里使用它,因为它使我编写的代码和演示只有几行。 但是,是的,男人,用您认为最适合您项目的任何方法重写这些代码。
Chris,您两次写了“in”(在“sh*t”和“whatever”之间)。
是的,但如果您的手机是 Windows Phone 7 呢?
Aaron,您真的要因为他在评论中两次打错“in”而纠正他吗? 拜托,伙计……您不应该做点更有意义的事情吗?
Adam,我只是看到了一个拼写错误。 只是想让 Chris 知道。 如果听起来很粗鲁,那我表示歉意。
我一直使用 display:none 来做很多事情,比如使用媒体查询,但感觉我在作弊。
别担心,最终你需要做对用户最好的事情,使用 display: none 将额外的导航隐藏在屏幕阅读器中,因此似乎不存在任何可访问性问题。
或者您的意思是使用 display:block 感觉像是在欺骗 display: inline-block? 我有时觉得我和某些 CSS 选择器之间的关系比应该的更密切
演示在我的 iPhone 上似乎不起作用。 它显示为菜单,而不是下拉菜单。
我的 iPhone 4 上也是这样! 我的 iPhone 4 上不起作用。 我要去查看代码看看发生了什么事。
演示页面不是真正适合移动设备的页面。在你的实现中,你可以使用元标记将视窗设置为设备宽度,然后媒体查询将按预期工作。
我喜欢它。我从未想过将选择框用作导航元素,但它似乎确实对移动设备有意义。
我必须说这是一个有趣的解决方案。
很快就要在一个网站上尝试一下 =)
必须说这是一个不错的技巧。
很好,但我认为如果窗口太小,导航应该变成垂直的,而不是变成选择框。
从语义上讲,选择框用于在不允许多个输入的情况下在表单中选择选项(选择你的性别:[男性] [女性] 等)。
这种论点类似于不将链接作为 JavaScript 对象(href=#),而是使用按钮作为其目的(在页面上执行操作)的论点。
简而言之,<select> 元素不应用于导航,而应作为表单元素使用。这就是 <ul> 在那里的原因。
我有点同意你的论点,即 a 从语义上讲不正确,但我认为在为移动设备设计时,有时可以为了功能而将语义置于一边,因为移动设备还处于起步阶段,需要发展很多。
另外,作为补充说明,性别示例也不正确,应该使用单选按钮来处理这种情况。
我同意皮特的观点……我们绝对希望尽可能地使用语义上合适的元素,但不能以牺牲用户体验为代价,我认为在这里进行权衡是值得的。
哇……我喜欢这个技巧.. 那么“+1”按钮在哪里呢?:)
很棒的技巧,将要实现。
我想知道你如何让你的网站适应这么多不同的浏览器尺寸。
我在我的网站上使用的是完全相同的方法!我在 Yaron Schoen 的网站上看到了它。如果你想从你的 WordPress 页面生成一个动态下拉菜单,只需使用这个函数:wp_list_pages()
非常巧妙的小技巧,感谢克里斯!
是的,不错!
真的很好,我也会在前面加上“跳转到:”的文字。
天才。再次感谢你的分享。
这非常有用,尤其是在如今许多人使用移动设备浏览网页的情况下。再次感谢克里斯提供的另一篇精彩文章!!
非常有用的教程。感谢克里斯的分享!
真的很好……:)
这是一个不错的效果,但 fivesimplesteps.com 菜单在约 767 像素处变成了下拉菜单,这是否显得太大?换句话说,视窗需要/非常/小才能使用下拉菜单吗?
克里斯,非常巧妙的技巧……你是我的五天必看之一!
一个小建议,如果你像我一样想让生活更轻松,更新更快,你可以使用 PHP 数组或从数据库中动态获取菜单,这样你只需要编辑/添加/删除菜单数据一次,然后使用循环来处理选择和 ul 部分。
选择
我直言不讳地说这是自我推销,但我并没有从中获利,所以希望在这里发布它是可以接受的。
我刚刚发布了一个 WordPress 插件,它会生成一个下拉菜单,你可以在管理区域创建这个菜单。你可以在主题中调用
wp_nav_menu()
后使用它,来实现这篇文章中演示的功能,但所有控制都通过菜单管理完成。链接
http://wordpress.org/extend/plugins/dropdown-menus/
代码示例
克里斯,很棒!我一定会在我的项目中使用它。谢谢!
嘿克里斯!好主意,实现也很棒。感谢分享!
克里斯,这是一个很棒的想法。响应式网页设计每天都越来越流行。
嘿克里斯,我最近尝试构建类似的东西,但我想要将嵌套的 ul 转换成 optgroups(想想将下拉菜单导航转换为选择菜单)。我无法完全按照我想要的方式让它工作,所以我把这个问题发布到 stackoverflow 上,“Enki”给出了两个很棒的解决方案;快来看看吧!
http://stackoverflow.com/questions/6797684/convert-ul-to-select-w-optgroups
//从菜单创建 DD
var markUp = [“”], $li, $a;
$(“#menu > li”).each(function(){
$li = $(this);
if($li.find(“ul > li”).length){
markUp.push(“a”).text()+”‘>”);
$li.find(“ul > li”).each(function(){
$a = $(this).find(“a”);
markUp.push(“”+$a.text()+””)
});
markUp.push(“”);
}
else{
$a = $li.find(“a”);
markUp.push(“”+$a.text()+””)
}
});
markUp.push(“”);
$(“#menu”).append(markUp.join(”));
$(“#menu select”).change(function(){ window.location = $(this).val(); });
不错,但我不喜欢你的 HTML 中有未使用的标签,或者需要依赖 JavaScript。每个都不是最好的解决方案。
嗨克里斯。
我希望你不介意。你的文章让我想了很多。这里是我的成果:http://www.itmitica.com/en/articles/css3/s-menu/
简而言之,菜单链接的容器元素应该相应地行动,并提供可滚动的方式和有限的空间,使菜单更适合小屏幕。
我个人认为这个例子是一种倒退。我的意思是,当我用移动设备访问你的网站时,需要多做一步才能找到我需要的东西?真的吗?你给出的例子一开始并没有很大的导航,对吧?他们可以去掉首页链接(并将 FSS 徽标链接到 index.html),这样导航就可以在一行中显示。我认为只有在网站本身具有非常大的导航和子导航的情况下,下拉菜单才会有用。我认为 ESPN 移动网站做得很好。添加额外的步骤而不是重新考虑你的小型导航并不令人满意。
CSS 技巧真的很棒,我是通过 Google 找到的……现在我探索了 CSS 技巧,发现它是一个所有设计师都应该去的地方……
你们做得很好……感谢你们提供如此有用的教程。
@Chris Coyier
你可以轻松地为下拉菜单提供标记,而无需使用 JavaScript。
至少这是我的想法,我已经做到了,我可以提供一些关于如何使用媒体查询提供这种标记的巧妙示例……
有一些缺点,但如果你有兴趣,请给我发邮件,我会把示例发给你。
如何在不使用 JavaScript 的情况下根据屏幕尺寸有条件地提供标记?如何在没有 JavaScript 的情况下测试屏幕尺寸?某种 UA 嗅探?它是秘密的吗?很想看看例子,发布 JS 技巧 =)
嗨!这个解决方案太棒了!感谢您,像上面很多人一样,我在 Google 上搜索了很多,但以前没有人像您一样给我完整的解决方案。
我是否应该为我的网站的解析度问题找到解决方案,因为如果解析度小于 1280*1024,我的内容会从菜单中掉下来。
请给我一个解决我问题的正确解决方案。
期待您的回复,
Narendran,
在 Twitter 上关注我 @MyNaren89,
9487693560.
看起来很棒,伙计!但是,我们用 HTML 选择元素作为锚点遇到了问题。重要的是在它旁边添加一个“Go”按钮,以便用户只有在单击时才会被带走。这是为了可用性
不错,伙计。谢谢您的脚本。
它在 iPhone 上不起作用,因为 iPhone 的分辨率是 960,当分辨率小于 960 时,下拉菜单的 display:none 属性会失效。
真的很酷的东西…感谢分享
非常好,我还想在它前面显示一个“跳转到”文本
谢谢您的代码。这非常有效。不过我想到了一些补充。如果您的原始菜单有子菜单,那么在选择菜单中反映这一点将很不错。这是一个补充
对于具有这种标记的菜单
<nav id="main-nav">
<ul id="menu">
<li id="item-1">
<a href="/">首页</a>
</li>
<ul class="sub-menu">
<li id="item-2">
<a href="#">示例</a>
</li>
</ul>
</ul>
</nav>
新的 JavaScript
// 使用菜单项填充下拉菜单
$("nav a").each(function() {
var el = $(this);
var da = '';
if($(this).parents('.sub-menu').length){
da = '- ';
}
$("<option />", {
"value" : el.attr("href"),
"text" : da + el.text()
}).appendTo("nav select");
});
谢谢 - 非常有效!
如果您想要更多级别的菜单
等等…
谢谢!这真的很有帮助。
嗨。
是否可以只将级别的父级设置为粗体?
谢谢。
嘿,Chris,
这里有一个在较小屏幕尺寸下替代下拉导航的简单方法:将导航从页面上显示的前几个元素之一移动到显示的最后几个元素之一。在页面顶部,放置一个列表图标的图像,该图像锚定到新重新定位的导航。为了使此方法有效,必须进行平滑的页面滚动。就这样。
以下是我喜欢此解决方案的原因
(1) 新手设计师/编码人员可以轻松地将其应用到项目中;(2) 有更多空间可以立即查看内容;(3) 一些人(通常是年龄较大的人)不知道小列表图标图像代表菜单。这些访问者将继续向下滚动页面以在底部找到导航。
但我相信这个“解决方案”并不新鲜。
谢谢,这非常有效!
嗨,我在下拉菜单中添加了一个背景图像,用于单击菜单。在桌面上的悬停图像工作正常。而在 iPhone 或 iPad 上,悬停背景图像无法正常工作。
嗨,我使用了您的代码,在调整屏幕大小后,我得到了 2 个转到框。我做错了什么?有什么建议吗?
谢谢
这种模式不是一个好的解决方案,因为您只是为了一个备用导航元素创建了额外的标记。我称之为 hack。最好的解决方案是只使用一个导航元素并对其进行布局。
对我来说效果很好,但在移动版本中,检查图标始终显示我位于“转到…”页面,无法识别我是否位于其他部分。
从链接中删除 # 导致了这个问题。
对此有任何解决方案吗?谢谢。