CSS-only下拉菜单真的可行吗?

3

因此,我决定开始更深入地学习CSS,并尝试实现一个纯CSS的下拉菜单/选择框。我首先研究了一些在线教程中提供的代码。

最终,我得出了这个解决方案,我认为它相当不错。然而,我已经得出结论,在某些情况下,CSS菜单可能永远无法取代JavaScript菜单,因为在放弃JavaScript时会出现一些微妙的问题。

如果您下拉菜单中的项目只是<a href链接,那么一切都应该没问题。但是,如果您希望每个链接触发JavaScript事件,则会遇到以下问题:

  • 当用户在下拉框中点击某个项目时,显然你希望下拉框消失。如果你的下拉框中的项目是 <a> 元素,则会自动发生这种情况。如果它们不是 <a> 元素,则下拉框将不会在单击时消失——这将给你留下两个选择:(A)连接一些监听 onclick 的 Javascript,然后使下拉框消失;或者(B)使用 CSS :active 选择器将下拉框的 display 属性设置为 none。 (A)很愚蠢,因为你基本上回到了 Javascript 菜单,而(B)不起作用,因为它防止 Javascript 事件在单击菜单项时触发。

  • 所以,你必须使用 <a> 标签。这意味着,如果你想将事件与菜单项选择关联起来,你需要在你的 <a> 标签中使用内联的 onclick。这很好,除非你这样做,它会防止下拉菜单消失(正如我 jsfiddle 链接中演示的那样)。因此,仅使用 CSS 的下拉菜单似乎只能在用户选择菜单项后想要通过 <a> 链接导航到另一页时起作用。我找不到任何方法来触发 Javascript 函数而不带有一些陷阱。

问题:那么,我说的准确吗?还是有一种只使用CSS创建下拉菜单的方法(A)在用户单击它时消失,并且(B)触发Javascript函数?

如果JavaScript可以更好地完成工作,或者根本就能完成工作,为什么不使用JavaScript呢? - millimoose
@Inerdial,使用JavaScript是可以的。我的问题的重点是确定CSS是否足以满足我对于这个菜单的要求。根据我目前得到的答案,似乎我可能需要回到JavaScript菜单。 - Channel72
你可以使用类似于 演示:纯CSS3渐变下拉菜单(无图像) 的菜单和JavaScript来使下拉菜单消失(.style.display='none';)。 - uınbɐɥs
@Channel72 我看到的所有仅使用CSS的菜单都存在许多明显的可用性问题。其中之一是,您甚至不能偏离菜单一个像素,否则它就会关闭 - 即使您的菜单也是如此。另一个问题是,如果菜单是分层的,则无法直接从一个项目移动到子项目; 您必须向右移动 - 同时始终保持在20px(!)宽的带中 - 然后向下。 Shaquin链接中的菜单非常好地说明了这一点:尝试选择“我的项目> N.Design Studio> Illustrator教程”。 - millimoose
这些都是本地应用程序中的菜单极力避免的问题。良好行为的Javascript菜单也是如此。这使得使用一个不“行为良好”的菜单非常令人沮丧。虽然可以制作具有相同问题的JS菜单,但我认为仅使用CSS无法解决它们。(至少第二个问题不行,因为需要区分鼠标是移动到了某个项目上还是停在那里。) - millimoose
5个回答

5
我真的不明白你的意思。为什么你“显然”想让下拉菜单消失呢?
如果是这样,那么你应该让它消失,但我不清楚这是否是你想要发生的“显然”的事情。
菜单没有消失是因为鼠标仍然停留在悬停区域上,这正是CSS应该做的。如果你想要其他行为,那么你确实需要使用JavaScript。在大多数情况下,这并不重要,因为你要么重定向到另一个页面,要么改变当前状态(例如弹出对话框或其他操作)。
就我所用过的大多数情况而言,CSS菜单很适合大多数用途。我很少使用CSS菜单来做一些既不重定向也不会导致菜单关闭的操作。
所以我的答案是,即使你有一个特定的用例使纯CSS菜单难以使用,也并不意味着它们对大多数其他用途无用。
话虽如此,仅仅因为你使用了JavaScript并不意味着你必须回到完整的JavaScript菜单。你可以简单地使用JavaScript微调标准行为,而不涉及全面的JS菜单复杂性。

2
我认为预期的行为是当你点击菜单时它会消失 - 表示你已经选择了一个项目。我的意思是,几乎每个操作系统中的每个GUI中的下拉菜单都会在单击时消失,因为你表示你已经做出了选择。 - Channel72
你说“在大多数情况下,这并不重要,因为你要么是重定向到另一个页面,要么是改变当前状态”。是的,如果你正在重定向到另一个页面,那就无所谓了。但是,如果你正在通过JavaScript函数改变当前状态,难道你不希望在单击菜单时菜单消失吗? - Channel72
@Channel72 - 如果您正在更改当前状态,则可以将菜单作为该状态更改的一部分进行更改。此外,CSS菜单不是真正的菜单..因此不能指望它们自己像真正的菜单一样运行。您正在使用CSS来完成其未被设计用途的功能(但仍然做得很好)。如果您单击它时自动隐藏,那么您使用的“模拟”菜单的行为将破坏其他内容。 - Erik Funkenbusch
如果您使用 JavaScript 停留在页面上,那么 JavaScript 修复其“引起”的问题是不会有问题的吧? - mowgli
使用JavaScript改进CSS菜单而不是进行完全替换,这是一个很好的选择。如果编码不当,JavaScript菜单可能会有一些缺点,例如降低可访问性和无法使用于未运行JavaScript的用户。 - sscirrus

5

我觉得你有点困惑。你似乎认为只存在一种二进制:全部使用CSS或全部使用JS。这种想法很愚蠢。在合适的时候应该使用CSS,在CSS不适用的情况下使用JS。在大多数情况下,使用CSS来处理一些繁重的工作(如菜单的隐藏/显示等),然后通过添加CSS不能提供的功能来增强这些菜单,是大多数专业前端开发人员构建菜单的方式。


3
对此点赞,只是因为你想轻微改变CSS菜单的行为,并不意味着你必须删除所有CSS并使用JS重新绑定悬停事件(即传统的JS菜单)。 - Christian

3
你的问题说明你已经做了一些研究并且解释得很清楚。然而,我发现有些混淆:最后你想使用javascript是因为你想触发某个东西(一个事件、一个函数等)。
我的回答如下:
css非常适合下拉菜单,如果你想在用户点击菜单时使用javascript,只需像这样做
<a href="javascript:my_function()" >Item 1</a>
my_function()函数可以执行您想要的代码,并可能隐藏所选元素。
我在这个jfiddle中使用了一个传统的window.alert函数的示例,您可以用您喜欢的javascript替换它。
最后关于您担心菜单消失的问题:您确定您需要它消失吗?当函数被执行时,用户的注意力可能会集中在其他地方,他将从下拉列表中移动......但是我不知道确切的原因,因为您没有解释为什么希望它消失。

3
我认为在像这样的下拉菜单中不使用JS的目标是误导的。如果您正在使用下拉菜单进行导航(无论是外部导航还是使用#引用的页面内导航),手动隐藏菜单就变得不必要了。如果您将其用于其他任何功能,合理的期望是它必须与JS一起使用,这意味着在“手动”操作渲染元素时没有任何问题。
当然,这里还有另一种可能的用途。您的jsfiddle示例看起来非常像一个时尚的<select>元素 - 如果这实际上是您的意图,则可以使用类似以下内容替换各个链接:
<label><input type="radio" name="test-select" value="1" />Item 1</label>

这可以通过本地提交来实现——没有使用JavaScript,这可能是仅靠表单最小功能所能实现的。


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接