线形菜单图标… 这就是个菜单

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

前几天晚上我突然有了一个很蠢的小想法,然后我就把它写成了代码(就是这样)。您知道那些用来表示导航的小图标吗?我们这里称它们为 三线菜单 图标,但它们也被称为 Navicon(很聪明)或汉堡包(很蠢)。这个图标的重点是它看起来像一个小菜单,所以希望很明显,您点击它可以显示一个真正的菜单。但是,如果这个图标根本不是一个图标,而是一个缩小的实际菜单呢?

概念

是的,它有点俗气。

不过这个技巧非常简单。它主要依赖于 CSS transformtransition,以及其他一些基本知识。

过程本质上是

  1. 首先设计全尺寸视图
  2. 使用 transform: scale(0.X); 将整个内容缩小到图标大小
  3. 使用 opacity: 0 移除不必要的部分
  4. 当处于图标大小的时候,只对整个内容的点击做出反应。
  5. 当点击时,切换到 transform: scale(1),将隐藏的部分设置为 opacity: 1,并恢复正常的点击功能。

这是设计部分

更改状态

您可以通过多种方式更改菜单的“状态”(展开或折叠)。也许可以使用 复选框技巧 或者使用 jQuery 很容易地实现。

$(".main-nav").on("click", function() {
  $(this).toggleClass("open");
  return false;
});

我们在这里做的只是更改一个类,这 绝对是最佳做法

CSS

在处理状态时,我特别喜欢 Sass,因为您可以在同一个块中嵌套状态。

.main-nav {
  /* Animate the state change */
  transition: 0.3s ease;
  transform: 
    /* Make mini */
    scale(0.1) 
    /* Hot performance 10x hack */
    translateZ(0);
  /* The open state */
  &.open {
    transform: scale(1.0);
  }
}

处理点击

点击的事情有点奇怪。我们需要确保

  • 点击图标版本只需打开菜单
  • 在打开状态下点击菜单项可以正常工作
  • 有一种方法可以关闭它

我们已经有了 jQuery,它可以在您点击整个元素的任何位置时切换类。可以保持原样。我们只需要确保,如果您碰巧点击了微型图标内部的那些细小的线条之一,您实际上不会跳转到该链接。

所有这些链接都在一个 <ul> 中,因此处理此问题的一种方法是使用 CSS 使整个内容默认情况下不可点击(最小化),但在打开状态下可点击。

.main-nav {
  ul {
    pointer-events: none;
  }
  &.open {
    ul {
      pointer-events: auto;
    }
  }
}

虽然 pointer-events 很棒,但 支持方面存在明显的差距,IE 10 就是如此(不过 IE 11 支持它)。您可能希望使用一个额外的 <div>,在默认(最小化)状态下使用它来覆盖整个内容,并在打开状态下将其移除。

关闭它

我们处理关闭的方式是添加一个关闭按钮

<button class="close-button">
  <b class="visually-hidden">Close</b>
  <span aria-hidden="true">
    ×
  </span>
</button>

我们希望在那里使用 × 字符作为图标。但如果读取(或者如果它有意义的话,那就是“乘法”),它没有任何意义。因此,我们隐藏了它不被读取,并包含一个更易读的单词,该单词是视觉上隐藏的(使用定位将其踢出页面)。使用图标的标准程序

在我们的简单示例中,我们甚至不需要将事件处理程序直接绑定到此按钮,因为我们已经有一个附加到整个父元素上的事件处理程序,它可以切换打开状态。如果您点击此按钮,该事件将冒泡并触发该事件并完成工作。这可能很奇怪,因此请随意调整并直接绑定到元素。

语义?

虽然这个 <button> 并没有让我感到厌恶,但我们可以就它进行无休止的辩论。(示例对话)。在没有启用 JS 的情况下,它毫无意义,那么我们应该使用 JS 插入它吗?我们是否应该将其设为带有返回页面顶部的 href 的锚链接?<button> 仍然是正确的元素吗?

渐进增强?

虽然我们只是在这里玩乐,但我们可能会考虑通过渐进增强来解决这个问题。也就是说,从一个仅作为标记完全可用的菜单开始。然后,随着支持的可用性,提升所有花哨的功能。

幸运的是,我们的标记已经大部分处于良好的状态。我认为 <button> 是我们关闭按钮的正确元素,因为没有“有意义的 href”,但它应该使用 JS 插入,因为它只有在使用 JS 时才有功能。非常简单,可能看起来像这样

$('<button class="close-button">\
    <b class="visually-hidden">Close</b>\
    <span aria-hidden="true">\
      ×\
    </span>\
  </button>').appendTo(".main-nav");

另一个问题是,我们以这样一种方式处理 CSS,即默认状态是菜单关闭。并且该“关闭”状态本质上依赖于 CSS 变换来缩小它。如果不支持 CSS 变换,菜单将显示为打开状态,覆盖内容并且无法关闭(糟糕)。如果我们的菜单没有覆盖内容,我们可能没问题,但由于它确实覆盖了内容,因此最好仅在浏览器支持我们的花哨 CSS 需求时才应用我们的花哨样式。

有无数种方法可以解决这个问题,但一种相当简单且标准的方法是通过 Modernizr 检测相关技术的支持情况。如果我们需要的功能存在,<html> 元素上将有一个类名告诉我们这一点,我们可以使用它来应用花哨的功能。

.main-nav {
  /* Default, visible, accessible styling */
}
.csstransforms .main-nav {
  /* Bring the fancy */
}

IE 8 不支持 CSS 变换,因此

一无所知。

我再次将一个愚蠢的小演示变成了一个课程。这是最终的解决方案

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 扩展为实际菜单的线形菜单图标

其他想法?

也许这个想法本身很俗气,但我确实喜欢您点击的内容成为显示内容的一部分的想法。这有点像动画如何用于使操作更清晰,在这些动画期间拥有一个焦点也可以提供帮助。例如

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 owgLF