“侧边栏”模式 是在网页上布置内容的不同方式,而不仅仅是垂直排列。 例如,导航可以放置在“画布”(可见浏览器窗口)的左侧边缘之外,并根据需要滑入。 Anthony Colangelo 创建了 jPanelMenu 来实现这一点。 Hakim El Hattab 的 Meny 更花哨,但其功能类似。
它们都使用 JavaScript。 我认为尝试只使用 CSS 来重新创建 Anthony 的 jPanelMenu 会很有趣。 这是可行的——有几个优点和缺点。

查看演示
两列,一列折叠
此处的布局技术本质上是一个两列网格。 默认情况下,只有左列宽度为 0%,右列宽度为 100%。 左列是我们打算根据需要显示的导航。 通过隐藏溢出,此列将完全隐藏。
<!-- I am collapsed by default -->
<nav id="main-navigation" class="navigation">
<a href="#">Nav Links</a>
<!-- more -->
</nav>
<!-- I am full width by default -->
<div class="page-wrap">
<header>
<a href="#main-navigation">Menu</a>
<h1>Title</h1>
</header>
<!-- content -->
</div>
.navigation {
/* Collapsed */
width: 0;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
height: 100%;
}
.page-wrap {
width: 100%;
float: right;
}
打开菜单状态,使用 :target
注意这个链接
<a href="#main-navigation">Menu</a>
与 ID 匹配
<nav id="main-navigation" class="navigation">
这是一个普通的哈希链接。 页面将“跳转”到该元素。 对我们来说更重要的是,它将使此选择器匹配
#main-navigation:target {
}
因此,单击该链接时,我们可以通过增加其宽度来取消隐藏菜单。 也可以让它很好地滑出来。
.navigation {
transition: width 0.3s ease;
}
#main-nav:target {
width: 20%;
}
我们可以到此为止,菜单将与内容重叠(确保它具有更高的 z-index)。 这将是完全可以的。 但我们确实有选择。 我们可以将内容“推”到内容的右侧边缘。 例如,这就是 Facebook 在其移动应用程序中显示左侧菜单时所做的事情。 或者我们可以压缩主要内容,使其成为 20%/80% 的网格。 这就是我们在这里要做的。
但等等……我们如何在菜单打开时仅选择 .page-wrap 的特定状态? 我们可以使用 相邻兄弟选择器!
#main-nav:target + .page-wrap {
width: 80%;
}
就是这样。
要关闭菜单,我们只需要从 URL 中删除哈希链接。 本质上,在任何地方提供类似这样的链接
<a href="#">Close Menu</a>
如果您想变得更花哨,可以隐藏/显示位于完全相同位置的不同链接,以创建“切换链接”。
优点
全部都是 CSS! 总体代码量更少。 加载的资源更少。 在没有 JavaScript 的情况下也能正常工作。 过渡比 JavaScript 过渡更流畅。
缺点
浏览器支持有限。 :target 是 IE9+(如果 :target 不起作用,整个过程就会失败)。 过渡 是 IE 10+。 通过更改类或使用 JavaScript 隐藏/显示/动画,可以克服任何浏览器限制。 此外,您将拥有更多关于标记如何安排的自由,而不是被强制使用此处呈现的特定顺序。 也许语义上略好,不需要分别链接打开和关闭菜单。
太棒了,一些 iPad 应用程序有这种功能。 就像 Twitter、Facebook 的 iPad 应用程序,这种最初隐藏的导航位于主布局的后面。
谢谢。
你能用标签、隐藏的复选框和 :checked 选择器做一些类似的事情(不需要额外的标记)吗? 我想选择器会更复杂一些,但应该是可行的。
事实证明,可以! 这在标题本身中稍微简洁一些标记,但缺点是必须添加复选框本身。 还有一个好处是不需要更改浏览器的历史记录。
http://codepen.io/jetpacmonkey/pen/ktIJz
是的。 这被称为复选框技巧。 事实上,Chris 给你展示了一些你可以用它做的事情: https://css-tricks.org.cn/the-checkbox-hack。 我要补充一点,使用复选框可能会使 jQuery 的向后兼容性更容易一些,因为你可以根据复选框是否处于 :checked 状态编写条件语句。
真正好用的应该是 Tab Atkins 的切换状态想法: http://www.xanthir.com/b4Kn0
好主意! 与
:target
相比,这可能的一个缺点是选择菜单项不会折叠菜单,这意味着用户必须手动再次点击标签才能关闭,或者您必须使用 Javascript 取消选中该框。 但是,这完全取决于您的特定实现,自动关闭是否必要。很酷的演示! 另一个缺点是这种方法会影响浏览器历史记录。 这可以通过使用历史记录 API 来解决,但这个想法是不使用 Javascript。
完全同意。 这让概念很好,但在应用中不切实际。 此外,仅仅让宽度减小会导致嵌套图像和布局出现问题,使其看起来很奇怪。 仍然相信 JS 是这种方法的最佳解决方案。
非常酷,但我反对这种方法的最大论点是,由于使用了 :target,每次打开和关闭菜单时都会添加一个新的历史记录条目,这反过来意味着后退按钮会被完全搞砸。
这对我也一直是个问题。 幸运的是,Jeremy 做了一个没有这个问题的版本: http://codepen.io/jetpacmonkey/pen/ktIJz
我太喜欢这个了! 我也喜欢 Anthony 的插件。
我刚刚尝试了一些添加的媒体查询,以显示/隐藏扩展/折叠导航: http://codepen.io/Jenn/pen/tIFaH
不错的演示,但我更喜欢 :checked 解决方案,因为它没有历史记录问题(是的,手机有后退按钮,并且在使用中……)并且要注意移动设备上的支持(使用这两种技术)
小心 jPanelMenu,它在某些浏览器中不起作用……(例如 Android 2.1)
导航和用户问题消失了……始终使用“不良”浏览器进行测试!
如果我用 CSS 开始做这个,我会使用一个复选框,选中时显示菜单。 然后我会使用
:checked
选择器和+
选择器。这去掉了 URL 中难看的哈希,但浏览器支持是否更好?
不错的演示,Chris!
我个人非常喜欢这种导航实现,但需要注意的是,在智能手机横屏模式下菜单的可用性。 如果导航中有许多链接,那么无法访问它们,因为导航面板是固定的(不会滚动)。
http://cl.ly/Kjwy
也许在打开状态添加
overflow:scroll
可以作为一种解决方法……非常感谢您分享这一点。 这真的很酷。
我要去测试一下 :-)
我喜欢这个概念,但如果菜单从左侧而不是从顶部滑入,三线菜单图标对我来说似乎不太自然。这个图标让我想要抓住它并把它拖下来。有什么更好的图标想法吗?
不错的演示。我在几个不同的项目中尝试过这个。我还发现它在创建无 JS 的选项卡部分时非常有效。不过,正如你所说,它在旧浏览器中失败了。
<a href=”#”> 关闭菜单的缺点是跳转到页面顶部,而不是停留在打开菜单之前的位置。
这只会发生在沿着滚动的菜单,即 `position: fixed;`,但大多数情况下,这会导致移动设备上出现很大的延迟。因此,在大多数情况下,用户已经位于页面顶部。如果你仍然想要防止这种情况发生,我认为你可以使用 jQuery 阻止默认操作。
不错。这是一个使用通用兄弟组合器的画布外示例。
http://www.vinceallen.com/offcanvas/index.html
更重要的是,Coyer 先生!你是怎么得到这个 “☰” 字符的!与大家分享一下!
Unicode 9776 -> ☰
这个不错!感谢 Jeremy!
我认为这在移动设备上最有用。由于没有运行 IE8 及以下版本的移动设备,有限的浏览器支持是否是一个问题?
一如既往,很棒的文章!谢谢!
在没有 JS 的情况下使它工作,这很棒!但是,我更喜欢绝对/相对定位,并将你的侧边栏滑入(同时将主面板滑出),这样你就不会有文本重排(这可能会影响复杂页面的性能)
几周前我做了类似的事情。但使用 jQuery 更强大。
查看它(使用以下登录:D4DD)
我喜欢,因为你不会得到错误的水平滚动条,但是…后退按钮太…由于点击打开和关闭菜单的按钮/链接,糟糕?
很高兴看到它在没有 JS 的情况下工作。更多菜单项需要具有 `overflow: scroll`。
嗨,在第一个框中,nav 元素的 ID 不应该是 “main-nav” 而不是 “main-navigation” 吗?
不,所有 CSS 等都基于 “main-navigation”,虽然你可以随时根据需要调用它,例如 “main-nav”——只要你在整个 CSS 和锚点 href 中保持一致。
当然…我指的是一致性。
Chris 在 HTML 中调用了 #main-navigation,然后在 CSS 中调用了 #main-nav…
我以为我还检查了这一点,以确保这一点,但你在这方面完全正确。
太棒了,感谢分享!我以此为基础,实现了一个版本,其中文本没有被挤压,而是被推到一边(类似于 Facebook),以及一些内容框的漂亮过渡效果
http://pixels-paper.nl/labs/nav/index.html
你还有文本没有被挤压而是被推到一边的示例吗?
干杯
嘿,Jelmer… 与 Laszlo 的问题相同:你能帮助将 page-wrap 推开,与 main-nav 的宽度相同吗?
如果你想要获得将整个页面滑到一边的不错效果,可以使用 CSS 转换,例如将此样式应用于页面包装器
感谢你只使用 CSS 的菜单。我有一个问题,如果菜单处于打开状态,我想禁用 page-wrap 容器中的所有点击事件,以避免用户点击 page-wrap 内部的任何链接,或者我想在用户点击 page-wrap 时关闭菜单。这可能吗?
嗨,
你能够关闭菜单吗?
干杯
只是在移动格式菜单上调整了一下,它没有正常工作,所以找到了如何在移动或平板电脑视图中将菜单的宽度更改为 75% 的方法 http://codepen.io/riwakawebsitedesigns/pen/xHrIo
删除了我的链接,很快将制作新版本,并将新的链接发布在这里的页面上。
Chris,很棒的工作,
有没有办法让 .page-wrap 的宽度为(100% - #main-nav 宽度)?
我不想让我的 #main-nav 在宽屏幕上显示完整的 20%,所以我将 #main-nav:target 的样式设置为
#main-nav:target{
width: 20%;
max-width: 180px;
min-width: 130px;
}
任何指导都将不胜感激 :-)
嗨,Chris 和大家。我想知道这里有人(或者你 Chris)能帮助我解决 iOS 7 中的弹出菜单问题 吗?
我认为自己对 CSS 的掌握水平是中高级,但我就是无法解决这个问题。我将感谢任何关于上述 SO 问题的提示!
太棒了,感谢分享!