“CSS 选项卡”的概念已经存在很长时间了。如果您在 Google 上搜索它,您会发现很多都是关于样式化的 CSS 选项卡,但关于构建真正功能性选项卡区域的内容却很少。至少,在功能性上,我们认为今天的选项卡区域是:点击一个选项卡,看到一个新的内容区域,而没有页面刷新。
解决功能性 CSS 选项卡的历史并不悠久。Brad Kemper 在 2008 年就开始尝试,试图利用:checked
伪选择器和单选按钮以及相邻同级组合器。这是一种非常酷的技术,可以用来做一些事情,比如展开/收缩树形菜单或用图形视觉地替换表单元素(由 Ryan Seddon 首创)。
我个人曾经尝试过使用功能性选项卡,并想出了七种不同的方法。大多数方法都围绕着:target
伪类选择器,而大多数这些技术都很糟糕。只有一个还不错。它们都有一个主要缺陷,那就是需要使用 URL 哈希,这会导致页面跳到具有匹配 ID 的元素,这完全是不可预期的,跳跃的,而且总体体验很差。
使用单选按钮/:checked
技术要好得多,但有一个长期存在的 WebKit 错误,它阻止了伪类选择器和相邻同级组合器一起工作。好消息!从 Safari 5.1 和 Chrome 13 的稳定浏览器版本开始,这个问题已经修复了。
所以,让我们用:checked
方法来完成这件事,我认为这是目前和未来几年内最干净的方法。

HTML 结构
整个组的包装器,然后每个选项卡都是一个 div,包含单选按钮(用于功能)、标签(选项卡)和内容 div。
<div class="tabs">
<div class="tab">
<input type="radio" id="tab-1" name="tab-group-1" checked>
<label for="tab-1">Tab One</label>
<div class="content">
stuff
</div>
</div>
<div class="tab">
<input type="radio" id="tab-2" name="tab-group-1">
<label for="tab-2">Tab Two</label>
<div class="content">
stuff
</div>
</div>
<div class="tab">
<input type="radio" id="tab-3" name="tab-group-1">
<label for="tab-3">Tab Three</label>
<div class="content">
stuff
</div>
</div>
</div>
CSS 布局
基本上
- 隐藏单选按钮(我们不需要看到它们,我们只需要选中或取消选中它们)。
- 使选项卡浮动,以便标签落入链接行结构中。
- 将内容区域绝对定位在彼此之上。
- 当一个单选按钮被选中时,使相邻的内容区域位于顶部,并使用 z-index(在视觉上显示它并隐藏其他内容区域)。
.tabs {
position: relative;
min-height: 200px; /* This part sucks */
clear: both;
margin: 25px 0;
}
.tab {
float: left;
}
.tab label {
background: #eee;
padding: 10px;
border: 1px solid #ccc;
margin-left: -1px;
position: relative;
left: 1px;
}
.tab [type=radio] {
display: none;
}
.content {
position: absolute;
top: 28px;
left: 0;
background: white;
right: 0;
bottom: 0;
padding: 20px;
border: 1px solid #ccc;
}
[type=radio]:checked ~ label {
background: white;
border-bottom: 1px solid white;
z-index: 2;
}
[type=radio]:checked ~ label ~ .content {
z-index: 1;
}
这个 CSS 非常轻量级,并且可以通过在 HTML 中添加更多“选项卡”div 来扩展到任意数量的选项卡。
JavaScript
没有,船长!
为什么这种方法很棒
- 它不使用 :target,因此没有页面跳跃吸附和后退按钮劫持。
- 它是可访问的。奇怪的单选按钮是用 display: none 隐藏的,所以屏幕阅读器不会看到它们而感到困惑(可能),并且没有实际的内容是用 display: none 隐藏的;
- 它在 Safari 5.1+、Chrome 13+、Firefox 3.6+、Opera 10+ 和 IE 9+ 中运行。也许在 Chrome、Firefox 和 Opera 中更深入一些,但 Safari 和 IE 绝对是正确的。
为什么这种方法不完美
- 它需要为选项卡区域设置一个高度,这很糟糕。我觉得可能有一种方法可以解决这个问题,但我还没有找到。
- 单选按钮方法有点像黑客。
- 它没有最深入的浏览器支持(IE 9 要求有点高)。如果您需要更深入的支持,请使用 JavaScript。
理解了,明白了,很好
仅仅为了好玩,我在实时演示中为选项卡添加了一些过渡效果。
查看 CodePen 上的
功能性 CSS 选项卡,由 Chris Coyier (@chriscoyier) 创建。
在 CodePen 上。
完美的理论未来 – display: stack;
正如我所提到的,单选按钮方法有点像黑客。我们现在能够做到这一点,并且体验非常好,这很酷,但是我们的编码方式并不优雅或直观。Tab Atkins,他编写 CSS 规范,认为display: stack;
可能是 CSS 选项卡用户界面的未来。
“Tab Atkins”??你肯定是在开玩笑吧!
是的,他接替了 Radio Vasquez
CHRIS 从来不开玩笑。
感谢 Chris,
这在我的网站上非常有用,因为我无法使用 Js 方法,
但在手机上不起作用,您也遇到过这个问题吗?您有解决这个问题的方法吗?
再次感谢,
嗨,Chris,
我刚刚测试了演示,页面标题在切换选项卡时闪烁,很奇怪!(不是抱怨)
我在 OSX Safari 5.1 上(在 Chrome 中不会发生)
我在 Safari(而不是 Chrome)中也是这样。这与过渡有关,所以如果它是一个问题,就放弃它。
在运行 Leopard 的 Mac 上使用 Chrome 13,每次过渡后整个页面都会闪烁为黑色。奇怪的是,到目前为止还没有其他人遇到这个问题…
无论如何,这是一个非常简单/酷的演示!我可能很快就会使用类似的东西!(不过要用 js)
旧的东西,但它解决了一些旧浏览器中的问题…
http://tjkdesign.com/articles/spry/tabbed-panels_better_version.asp
我采用了 Jacob Dubail 的精彩想法,并构建了一个淡入淡出画廊 http://jsfiddle.net/chrisbuttery/fWNnr/18/
我认为这个问题是为什么它在 iOS 上不起作用,您点击选项卡但没有任何反应
我喜欢看到针对不同设计障碍的纯 CSS 解决方案。但这并不意味着我总是使用它们。如今,对于选项卡,我通常会使用 CSS 和 JavaScript 方法,其中所有内容都可见(通常是堆叠的),如果 JavaScript 不可用。
无论如何,感谢您的工作。它让我的思维活跃起来:)
在处理这类事情时,CSS 在可用性方面几乎总是很糟糕。就我个人而言,我不理解这种使用视觉显示语言来更改网页功能和行为的迷恋。这正是 Javascript 的用途。
我知道,我知道,测试语言的极限很棒。但我经常想知道,有什么意义呢?
+1
我同意,虽然用 CSS 做这件事很酷;)
我原则上同意你的观点。我认为这个博客有时会为了纯粹的 CSS 解决方案而寻找它,仅仅因为可以做到。但是,选项卡更像是“视觉显示”方法,还是“功能”或“行为”?它们是如此基础和无处不在,似乎没有必要引入 Javascript。
https://css-tricks.org.cn/13758-functional-css-tabs-revisited/
@jon 这是一个公平的问题,但我认为不是。界面元素的普遍性或其他因素不应影响它应该在哪个层面上实现。我认为选项卡的交互方面总是存在的,无论它们是一个多么常见的视觉元素,并且这种交互仍然应该由行为层处理,同时它仍然是一个独立的层。
非常棒。我一直想做这样的事情,但我就是找不到我喜欢的办法。
只需要添加一个 iOS 特定的菜单,该菜单完全更改页面。
谢谢,Chris!我想在这里添加的是,在选项卡悬停时
cursor: pointer
:)在火狐浏览器中,当选中左侧选项卡时,会显示一个“缺失”的像素。这是因为白色底边框对整个选项卡宽度处于活动状态。将 border-bottom 设置为零已为我解决了这个问题。
[type=radio]:checked ~ label {
background-color:#FFFFFF;
border-bottom:0px; /* 细微的火狐浏览器故障 – 第一个选项卡的左下角有一个缺失的边框像素 */
z-index:2;
}
Ben Cavens,那么它至少在 Opera 和 Chrome 中显示来自
.tab label
选择器的底边框(没有在 IE 和 Safari 中测试它)。不好!抱歉,是我的错,它没有 :)
这很酷。
在我看来,对于选项卡,你实际上需要片段标识符(
#tab1
、#tab2
等)进行链接,因此,使用 Jenna Smith(以及其他人)用于无 JS 灯箱(例如这个)的相同技术的解决方案应该是可能的。并且它将具有更广泛的浏览器支持的优势,一直到 IE6(全球市场份额 9.7%——但下降速度很快,感谢神灵)。缺点在那里(而且很大),它可能只对页面上的主选项卡有用,因为它确实接管了片段标识符,并且可能只有在页面没有滚动时才能正常工作。在 Chrome 15 中,从恶魔猫选项卡切换到另一个选项卡时,它会过渡到新选项卡,然后闪烁猫的图片,然后再次显示该猫选项卡的真实内容。最好删除动画——对于任何人来说——因为它在多个浏览器中存在 bug。
非常好,
我喜欢这种简单的方法。
我可以看到一些相当容易的增强功能可以与 Javascript 一起添加,而以它为基础。
在 Windows 上的 Chrome 9 中无法使用……
浏览器支持在上面的文章中列出。Chrome 自动更新并在 v13 中稳定。你关闭自动更新了吗?我甚至不知道这是否可能。
你能做一个视频吗?我的意思是解释所有这些选择器
谢谢,Chris。我刚开始为我的网页实现选项卡解决方案,这个解决方案非常完美。感谢你的文章,并教导像我这样的人如何成功地修改网站。每天,我越来越像一名设计师,这要归功于像这样的好文章。我很高兴的是它没有使用 Javascript。非常感谢
在我的 Chrome XP 上无法使用。它在 Ubuntu Linux 上的 Chrome 上可以使用。
我这边也是一样。
但这可能是因为我在虚拟机上运行 XP。
我可能会在我的一个项目中使用它,如果我这样做,我会展示一下。
这里还有一个演示 http://jsfiddle.net/laukstein/fWNnr/39/
哇,没有 Javascript!就是这样!:)
使用复选框的巧妙想法 :)
但是如果选项卡内容有不同的高度,就会出现问题。
所以我创建了自己的版本,没有使用
position:absolute
(和clear: both, float:left
),并且 html 结构不像你的那么好。我使用
:checked + * + label
,所以更多的选项卡需要更多的+ * +
:(这是代码 http://jsfiddle.net/bUjQm/18/
之前的版本无法与最新的 Chrome 13 和 Safari 5.1 一起使用,但我找到了解决方案——然后我读到了你关于 Webkit 错误的新闻 :)
我的一个 Webkit 修复:
body ~ :checked {}
(或
anything ~ any_sibling_to_+_*_+ {/*empty*/}
)新代码:http://jsfiddle.net/bUjQm/21/
选项卡容器的宽度可以设置为任何值吗?
溢出怎么办?
这主要是因为,作为浏览器默认行为的一部分,单击
会自动选中不可见的单选按钮。
意外的空格实际上是
<label>
。我 *一定* 会在我的个人网站重新设计中使用它。非常感谢!
Chris,这太棒了。继续努力!:)
喜欢这个,但我希望我能设置一些 jQuery/JavaScript 来每隔 30 秒循环一次选项卡……
我用它和复选框一起使用,来创建一个树形文件浏览器。
如果选中,则显示子树。
而且最棒的是,即使在隐藏后,复选框也能记住它们的值。
很棒的 CSS 技巧,谢谢
在网站中集成滑动内容的非常不错且简单的方法,只有一点,如果我们可以在选项卡鼠标悬停时显示手形光标,而不是箭头,那就太好了。我没有尝试过,但我希望这可能。
看起来在 iPad 上无法使用。真可惜。
我之前做过一些让选项卡与更多语义化标记一起工作的尝试,比如像你在例子中展示的那样,将标题和内容“合理地”分组:http://fittopage.org/2010/05/tabs-done-right/
我的解决方案仍然依赖于 JavaScript,但这也有一个额外的好处,那就是它现在可以跨浏览器兼容。
我添加了一点额外的 HTML 和一些动画,使这些小部件可以折叠成下拉菜单。试试看吧!
我太兴奋地想玩这个了,以至于忘记了 iOS 不支持它,真可惜 :(
http://jsfiddle.net/paullferguson/Sv54G/3/
我一直想让选项卡有文本在下面,并且有内容(幻灯片)在它们上面,与选项卡面板中的文本内容相关。我没有 JS/JQ 的技能来编写它,而且我尝试过的插件等等都没有奏效。
今晚偶然发现了这个(几年前的)字符串,然后... http://jsfiddle.net/pixelsound/bwarQ/3/
我认为这会奏效!
-我在选项卡中添加了“上面”内容的 div,使用绝对定位放在它上面...(现在是文本占位符 - 当这是幻灯片时,它会与选项卡面板内容一起淡入淡出,替换之前运行的幻灯片)
-整个选项卡 div 的相对定位/高度将很好地将页脚或内容向下推。
-我认为,使用一些媒体查询,我可以将它折叠成一个小屏幕或移动设备的折叠式手风琴。
-我还认为,iOS 支持问题从 2011 年起就已经解决了...
谢谢!谢谢!谢谢!
嘿,Chris!
很棒的东西 - 一个建议(虽然我没有试过) - 将不可见的选项卡放在 body 下面(body 应该有背景),设置 z-index: -1; - 这 *应该* 解决高度问题?
有一件事 - 我正在使用 Chrome 14 - 我看到了单选按钮?并且选项卡不起作用 - 高亮发生了变化,但内容仍然停留在选项卡 2 上.. :/
等等.. 我的错 - 我认为是在看错误的演示.. 你的确实有效:D
有没有办法让它在 IE8 上不使用 JavaScript 就能工作?我目前正在为一个客户工作,他们更希望整个网站的代码都不要使用 JavaScript。他们使用 IE8 作为他们的主要浏览器(他们有很多安全问题)。
可能没有人会回答这个问题,但我发现这段代码非常方便,对我来说很容易按照我需要的方式使用...除了选项卡本身。我似乎无法弄清楚如何调整选项卡的大小,我可能读错了,因为我使用 HTML 和 Dohtml 的时间还很短。我遇到的问题是,当我输入一些内容时,比如在选项卡中输入一个长名称,选项卡会随着名称的长度而拉伸。我想要做的是,将名称分层,比如将姓放在上面,将名放在下面。我尝试在名字之间添加一个空格,但什么都没做,只是弄乱了选项卡的外观。我尝试在选项卡中添加高度,比如高度或行高,但我无法使其正常工作。我可能完全做错了或者在错误的地方做错了...。
@AJ - 要调整选项卡的高度(也就是你点击的那部分,上面写着“选项卡 1...2...3... 等”),你需要在“.tab label”类中添加一个“display:block”行,然后像往常一样添加高度和宽度属性。我认为。我不能保证这不会搞乱其他所有东西。
这是一个有用的 CSS 片段。我喜欢它。
虽然针对问题的纯 CSS 解决方案可能看起来很放纵且毫无意义(有些解决方案是),但 CSS 选项卡的一个很好的理由是在 eBay 列表中。你不能在你的列表中使用 JS,所以 CSS 在这方面是我的好朋友。由于跨浏览器兼容性问题,我一直没有在我的 eBay 列表中使用 CSS 选项卡,直到现在。
但唉,虽然上面的解决方案比我之前的尝试做得更好(更优雅地获得了相同的结果),但 Internet Explorer 仍然拒绝配合。但显然,IE 是完美的,是世界上大多数其他主要浏览器出了问题。很明显 - 我的意思是 Mozilla、Google、Opera、Apple 等都懂什么?谁还需要一个全球标准呢?
还有什么自尊心强的 web monkey 不喜欢每次想做某件事时都要为 IE 编写一个完全独立的解决方案呢?
好了,你发现我了。我只是来这里抱怨微软的。AJ,祝你获得这个意外的信息。:D
:-D
为了提供信息,在旧版本的 iOS 上让它工作的解决方案是使用一个空点击处理程序,你可以使用这段 JavaScript 代码将其应用于所有标签
该解决方案在 IE8 上不起作用,有人知道 IE 的解决方案吗?
有没有办法让选项卡控制一个在选项卡之前的区域,而内容在选项卡下面?
谢谢!
Aaron
我也想知道这一点!我想让选项卡选择触发一个在选项卡内容面板之外的 JavaScript 幻灯片的改变。
这是一个我一直在测试的非常好的选项卡插件
https://github.com/jellekralt/Responsive-Tabs
…但我遇到了可变高度问题,还希望选项卡选择确定幻灯片的切换。
对于可变高度问题,我将尝试一些 Vesa 的解决方案(见下文;http://codepen.io/Merri/pen/bytea)
你找到了解决方案吗,Aaron?我对 JavaScript 还比较陌生,但并不回避使用它来解决这个选项卡触发变化的问题...。
有人能帮忙吗?
我花了一些时间研究这些选项卡,以解决可变高度问题,这是一个很有趣的解决问题的方法。然后,我也有兴趣让它在 IE8 及更低版本中正常工作。这意味着添加 JavaScript。但是,我将 JS 保持到最低限度,而是让 CSS 在 IE8 中完成繁重的工作,以及在 IE7 和甚至 IE6 中。
我甚至使用一个简单的媒体查询在其中添加了一些响应式设计。
http://codepen.io/Merri/details/bytea
我想说,最终的结果现在是一个经过深思熟虑的基于 CSS 的选项卡。添加回退支持确实也为 HTML 添加了更多类,以避免在输入框和标签内使用时出现问题,但对任何人来说,这应该不是什么大问题。
这里唯一尚未解决的问题是选项卡内内容的可链接性,这在现实生活中可能是一个要求。许多人通过哈希链接到选项卡,但我还没有看到很多解决方案能够在链接到选项卡内内容时也打开正确的选项卡。对此,我有一个不同的解决方案
http://codepen.io/Merri/details/qsdza
它只支持 IE8+,并且需要一些代码清理,但它在功能上非常强大。
Vesa - 你的代码很棒,谢谢!唯一的一个抱怨是,如果你在页面上较低的位置设置了这个选项卡,它会在 Chrome 中向上滚动浏览器。
我可能会尝试用 JS 来弥补这一点(我将它用于我们的 WordPress 插件,并给了你荣誉),但如果你知道更好的方法,我很乐意倾听!
很棒的帖子,这里也有很棒的讨论。
看起来很棒 - 我正在尝试...。
关于上面 Aaron 的问题有什么想法吗 - 让选项卡选择影响选项卡内容之外的元素?我希望选项卡选择触发在选项卡 div 之外的 JavaScript 幻灯片的改变。JavaScript 解决方案?任何帮助都将不胜感激!
谢谢!
AK
我很想知道如何使选项卡具有固定宽度,并让选项卡内部的文本换行。(几乎是 AJ 所要求的)
否则,这是一个非常棒的实现。
O
有人知道如何在 IE8 中工作吗?
谢谢!
很棒的工作,但它在我的平板电脑上无法正常工作。我一直在尝试添加一些 JavaScript 来让它工作,但我卡住了。这段代码似乎可以工作一小段时间,但它要求用户多次点击选项卡才能使切换功能按预期显示内容。
有谁比我更懂 JavaScript,请看一看?
还有 HTML
以及
所以,我想要做的是使用切换效果来添加和移除选项卡内容。我已经困扰了四天,所以任何帮助都将不胜感激... :)
还有 HTML。我在 input type=”radio” 标签中添加了这个 onclick 事件。
澄清一下,
这是我添加到选项卡输入链接中的onclick代码
第一个选项卡
onclick=”var b = toggleAdd(‘tabc-2’); if (b) toggleRemove(tabc-1); return b;”
第二个选项卡
onclick=”var b = toggleAdd(‘tabc-1′); if (b) toggleRemove(tabc-2); return b;”
它有点有用,但用户必须在内容应被删除的选项卡上点击一次(toggleRemove),然后在他们想要看到的选项卡上点击两次(toggleAdd)。我做错了什么?:/
可以使用css轻松删除“min-height: 200px;”,使列的高度相同。您需要将**display: table**添加到这些列的父元素,并将**display: table-cell;**添加到其子元素
我必须纠正这一点(抱歉):该示例不可访问。这是因为您无法通过键盘控制选项卡。问题出在这里
.tab [type=radio] {
display: none;
}
这使得单选按钮对于键盘也“不可见”。更好的做法是像这样
.tab [type=radio] {
position: absolute !important;
height: 1px; width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
}
您好,很棒的作品 - 我想将此代码用于灵活的高度,因为我无法使用更多jQuery来确保网站正常运行。实际上您的代码对我来说运行良好,但我缺少灵活的高度。你能给我一些建议,将此功能添加到上面的代码中吗?
Alex
有史以来最糟糕的脚本!选项卡内容不会扩展!它具有固定高度!
来自Klass Moerman的Flexbox驱动的解决方案
https://kmoerman.github.io/css-tabs/