使用隐藏的复选框/单选按钮、:checked 伪类选择器和相邻兄弟 (~) 组合器的技巧,确实可以通过纯 CSS1 实现了某些简洁的功能可能性。如果您需要入门指南,我们最近使用此方法 构建了一个功能性选项卡区域。
让我们再次利用它来构建“展开式弹出窗口”。也就是说,您可以**点击**链接/按钮以显示类似工具提示的丰富 HTML 弹出内容。

HTML 结构
我们需要一个复选框来实现开启/关闭的可点击功能(不用担心,它是隐藏的)。然后紧随其后的是一个标签。像任何好的标签一样,for
属性与输入的 id
属性匹配。这样我们就可以点击它来切换复选框。
标签在其内部包含多个 span 元素。.box
span 是丰富 HTML 弹出窗口的容器。换句话说,您可以将任何内容放在其中。好吧,任何您想要作为内联元素的内容。使用 div
和标题标签等元素很诱人,但某些浏览器不兼容,会将这些元素渲染在标签外部而不是内部。将 .box 放在标签外部并不是什么大问题,因为我们可以链接 ~
选择器来使其隐藏/显示,但将它们放在内部意味着我们可以相对于标签的位置定位弹出窗口,就像“弹出窗口”应该做的那样。
<input type="checkbox" id="popup" class="popUpControl">
<label for="popup">
Click me!
<span class="box">
Super cool popup content
</span>
</label>
CSS 基础
我们对 .box 的目标是将其相对于其所在的标签进行绝对定位,以便它弹出并附加到标签上。默认情况下,它将通过设置为零的不透明度而隐藏。我们还将将其缩放到零、倾斜并添加过渡。然后,当我们通过复选框被选中来显示它时,我们将将其放大,移除倾斜,并通过将不透明度恢复到 1 来使其可见。
.box {
position: absolute;
left: 0;
top: 100%;
z-index: 100;
/* Prevent some white flashing in Safari 5.1 */
-webkit-backface-visibility: hidden;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
width: 260px;
padding: 20px;
opacity: 0;
-webkit-transform: scale(0) skew(50deg);
-moz-transform: scale(0) skew(50deg);
-ms-transform: scale(0) skew(50deg);
-o-transform: scale(0) skew(50deg);
-webkit-transform-origin: 0px -30px;
-moz-transform-origin: 0px -30px;
-ms-transform-origin: 0px -30px;
-o-transform-origin: 0px -30px;
-webkit-transition: -webkit-transform ease-out .35s, opacity ease-out .4s;
-moz-transition: -moz-transform ease-out .35s, opacity ease-out .4s;
-ms-transition: -ms-transform ease-out .35s, opacity ease-out .4s;
-o-transition: -o-transform ease-out .35s, opacity ease-out .4s;
}
.popUpControl {
display: none;
}
.popUpControl:checked ~ label > .box {
opacity: 1;
-webkit-transform: scale(1) skew(0deg);
-moz-transform: scale(1) skew(0deg);
-ms-transform: scale(1) skew(0deg);
-o-transform: scale(1) skew(0deg);
}
box 的实际 CSS 有一些额外的样式,但这是重要的功能性内容。获取随本教程提供的下载以获取完整的 CSS 集。
打开时更改按钮文本
这对于这里的想法来说并不重要,但此演示中的另一个巧妙技巧是在弹出窗口打开时更改按钮的文本。这是通过在 :checked 时实际隐藏按钮内的文本并插入新文本来实现的。基础知识
<input type="checkbox">
<label>
<span>Default text</span>
</label>
[type=checkbox]:checked ~ label span {
display: none;
}
[type=checkbox]:checked ~ label:before {
content: "Text to show when checked";
}
另一个“技巧”(不好,因为生成的 content 可访问性不高 或不可选择)。但是,嘿,我们仍然玩得很开心,对吧?
1 是的,但是……JavaScript
这绝对是“关注点分离”的界限。即使我是在“纯”CSS 中创建的,但我实际上认为这种类型的行为可能更适合 JavaScript。而“使用 JavaScript”是指我实际上会怎么做
- 为 .box 切换“打开”和“关闭”的类名,而不是使用复选框。
- 通过 JavaScript 更改文本,而不是使用 CSS 生成的内容。
但其他所有内容都应该保留在 CSS 中。样式、过渡、转换……这些都是样式,而不是功能。
哇,我真是个伪君子,哈哈?
致谢
感谢 Victor Coulon 向我发送了 这个想法,我以此为基础进行了改进。
我真的很期待看到狗狗 :(
哈哈,看起来你抢先一步了!
由于互联网上的每只猫都至少值 2.5 条狗,我认为我们在这场比赛中领先了。
演示中显示了更多的狗狗和一只猫!我只能想到这个功能的数十亿种用途——我还没有检查过,但您知道这在旧版浏览器中是如何工作/不工作的吗?
一如既往地棒!
很棒的效果!感谢分享!
Chris……我注意到链接上的弹出窗口(弹出)在两个方向(弹出和收回)上都缓动;但是,照片只是触发然后缓动退出。这是预期的效果还是 FF6.0 仍然缺少您的一些预期功能?
是的,在尝试关闭 FF6 上的弹出窗口时,我也遇到了问题。
很棒的技巧!
很棒的效果。源代码比我想象的要少。感谢分享。
我认为您应该有一个
cursor: pointer;
在 CSS 中,因为它会让链接看起来不可点击。
我还认为在按钮上添加 :hover 会很好,只是为了获得更好的视觉效果。
遗憾的是,它在使用移动版 Safari 的 iOS 设备上不起作用。
或者在 Opera Mobile 上。
它可以,这只是使用 JavaScript 的问题,就像我在文章底部推荐的那样。
太棒了 Chris ;)
非常棒的效果!
很不错。在 Windows 中,Chrome 会使用效果显示和隐藏弹出窗口。有趣的是,Firefox 会立即弹出(没有效果),但在隐藏时会缓动收回。
是的……超级奇怪。现在正在查看。我不明白为什么会这样(测试了 Firefox 7)。可能是生成的 content 更改?太奇怪了。
一如既往地很棒,但我有一点不明白,在这行代码中
“~” 和 “>” 是什么作用?
看起来 CSS Tricks 的这篇文章可能会帮助您了解“~” 和 “>” 的作用:子元素和兄弟元素选择器。
如果您有任何其他问题,我很乐意提供帮助 :)
感谢您分享这篇文章 Aaron!理解这一点对于理解本教程至关重要。从本质上讲,它允许我们在前一个元素处于不同状态(在本例中)时选择不同的元素。
我认为将“弹出”窗口和标签(或文本链接,如演示中所示)都设置为不可选择,可以防止在有时双击以显示弹出窗口时选择它们(有些人会这样做)。也许是
-webkit-user-select: none;
或类似的东西?这很奇怪。我在 Safari 5.0.6 中浏览示例时,链接示例中的“气泡”弹出窗口下面有蓝色下划线(就像链接一样)。
是的,我忘了提这一点,但我故意保留了它。text-decoration: underline 属性会传播到子元素,即使子元素已明确将其关闭。这只是那些奇怪的事情之一。CSS3 规范有一些解决方法,但目前还没有实现。
您好,我有一个问题,如果我想对多个链接使用此效果该怎么办?当我这样做时,所有链接都会打开第一个弹出窗口。
这可能是因为您没有为每个复选框和标签更改 id。
查看此示例以了解更多信息(我删除了一些 CSS - 仅限 Webkit 的 CSS3 - 只是为了使其更方便)。
我必须点击两次才能使其弹出,然后点击两次才能使其收回……(Chrome)
它在我的 iPad 上不起作用…… :(
我没有看到那只猫
完美 - 除了那只猫,它正是我需要的 - 它倾斜的角度有点奇怪,但我猜这可以改变?
它不起作用。只有猫。糟糕的示例 :)
Chris……按钮在 FF6 中没有动画打开;但是,它确实可以动画关闭。(锚链接确实可以双向动画)——这是 FF6 中已知的问题,还是您编写的代码的特性,或者?
【我无法相信您的新网站风格看起来有多好!至少对我来说,这是自从我关注您的网站以来,最友好和最吸引人的一个!我希望您很快就能制作关于您如何实现它的具体方法的屏幕截图或帖子……】
有一件事可以肯定,如果任何动物都能上天堂,那一定是猫。我的意思是,我们从哪里得到竖琴的琴弦?有一次,我故意碾过了一只猫……第二天早上醒来时我感到很难过,但现在我不再难过了。原因是:它可能无家可归,我帮助它找到了一个更好的家:天堂……我可能不应该这么说。
我当时想做一些这样的事情。我不能也不喜欢使用 JS,所以对我来说这不是一个选择。我能想到的最好的方法是使用悬停选择器(参见我的演示)。
然后这篇文章出现了。
因为我想要多个按钮并且一次只打开一个,所以我使用了单选按钮。并添加了一个额外的按钮作为关闭按钮。
只需查看我的演示网站即可
http://tuinderijdevork.nl/demo/
在以下浏览器中运行良好:Opera 11.51 和 FF 6.0
关闭按钮在 Midori 0.4.0 和 Chromium 12.0.742.112 中已损坏
我还没有尝试在 Webkit 浏览器中修复它,因此欢迎提供建议(和其他测试结果)。
我对整个 transition/transform 属性还很陌生,但也许我们中的一些人没有在 Firefox 中看到动画效果的原因是缺少 ease-in 声明?
像这样
我在我构建的 javascript 触发的版本中实现了这个的变体,并且成功了;它现在可以在 Firefox(6.01)、Chrome 和 Safari 中进行淡入淡出动画。
奇怪的是,即使没有这些声明,Chrome/Safari 仍然可以对其进行动画处理。
很棒的教程,很棒的网站,Chris。当我在排查某种(对我来说)新的 CSS 形式时,这很快成为首选资源。出色的工作。
顺便说一句,当我查看演示页面时,我妻子走过我的电脑旁。她喜欢那只猫。 :)
此示例在 IE8 中不起作用,并且整个重新设计的网站的布局在 IE7 或 8 中也不起作用,所有元素重叠等,都是一团糟。
忘记 IE 吧。也许在 IE9 中,一些新功能可以工作,但我认为围绕 IE 的所有缺点进行工作是浪费金钱和时间。我赞成向 IE 访问者显示纯文本版本,并附上切换到真正浏览器的建议。(也许还有一些解释你为什么要这样做……)
太棒了。我打算在我的下一个项目中尝试使用它。谢谢。
你好,
我对 CSS/HTML 还比较陌生,所以请不要因为我的愚蠢问题而嘲笑我 :)
是否可以使用链接甚至在带有映射的图像上实现此功能(在我的案例中我有一个这样的解决方案)?我不知道如何更改 INPUT 标签以外的代码。
提前感谢!
有没有办法在按下或将鼠标光标移到映射图像的特定区域时使 CSS 弹出窗口?我的图像有几个区域应该调用不同的弹出窗口。
我查看了“de vries”发布的演示链接并尝试了一些东西,但似乎我的技能还不足以做到这一点。
我的演示的第一部分(当鼠标移过时弹出窗口显示)可能最容易理解。该代码位于 css 文件中(http://tuinderijdevork.nl/demo/css/de_vork.css)在 /* FANCY MENU */ 下。/* FANCY MENU 2.0 */ 下的代码用于演示的第二部分。
css 代码可能有点混乱,因为它是我正在处理的 joomla 模板的一部分。
ps. 我仍然不明白为什么它在 Webkit 中不起作用。当我打开一个弹出窗口然后通过更改页面上的任何 css 代码使浏览器重新渲染页面时,它就修复了。(如果我只能期望我的访问者这样做……)有什么想法?任何人?
“但其他所有内容都应该保留在 CSS 中。样式、过渡、转换……这些都是样式,而不是功能。”
HTML = 内容,CSS = 表示,JS = 行为
我喜欢 CSS3 中提供的新功能,但我是否唯一一个认为像工具提示和类似此折叠弹出窗口这样的交互应该留给 JS 的人?对我来说,这确实是功能、行为和用户交互。我可以看到双方都有论点,但我只是觉得如果我们继续添加更多像动画这样的功能,CSS 将会超出其目的。
只是一个讨论的开始 :)
Chris。您使用哪个插件进行语法突出显示?
Google-code-prettify
感谢添加。我一直在寻找这样的东西!
嘿,很棒的效果
非常简洁!
不过必须分解代码才能完全理解它。
谢谢!
CSS 做得很好——就像您所说的,总有一些地方 Javascript 可能更合适,这取决于您要实现的目标。
我认为,在一段时间内,使用 html/css 进行动画仍然会是一个问题……
非常感谢,
Darren。
不错的 CSS,但如果您有关于 javascript 的教程,请通知我..
非常感谢,
Faris
所以这个例子很棒并且运行良好,但是有没有办法将其应用于 YouTube 视频,考虑到嵌入使用块级元素?
我尝试将其封装在 p 中,但可惜它就像教程中提到的那样显示在代码下方。
感谢你的代码,Chris!:) 虽然已经快3年了,但仍然很有用。
我没有像你的代码那样在‘label’里嵌套‘span’,而是尝试嵌套一个包含很多内容(大量代码)的‘div class=”popout-box” ’。所以‘/label’的位置被放到代码很后面,这不太语义化。如果我在div class之前关闭label标签,弹出框就无法工作。有没有什么建议可以让我既保持语义化又能让它弹出?
非常感谢任何帮助、评论或建议 :)
点击
我的天,你创建那个三角形的方式真是太疯狂了!膜拜!
它在火狐浏览器27.0版本上无法工作。我该如何解决?