如果内联 SVG 图标,如何处理唯一的标题和 ID?

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。从 200 美元的免费积分 开始!

仅仅 内联 SVG 似乎是最简单、最灵活的图标系统。但这段 <svg> 代码可能包含 <title>,并且您可能出于各种原因在这两个元素上都应用了 ID。

其中一个原因可能是您只是希望图标上有一个 ID 以便于 JavaScript 或样式目的进行唯一标识。

另一个原因是为了可访问性,建议您使用 aria-labelledby 连接 id 和 title,例如

<!-- aria-labelledby pointing to ID's of title and desc because some browsers incorrectly don't use them unless we do -->
<svg role="img" viewBox="0 0 100 100" aria-labelledby="unique-title-id unique-desc-id">

  <!-- title becomes the tooltip as well as what is read to assistive technology -->
  <!-- must be the first child! -->
  <title id="unique-title-id">Short Title (e.g. Add to Cart)</title>

  <!-- longer description if needed -->
  <desc id="unique-desc-id">A friendly looking cartoon cart icon with blinking eyes.</desc>

  <!-- all the SVG drawing stuff -->
  <path d="..." />
</svg>

但是现在您在某个地方包含了两次该 SVG。假设您在使用 Rails…

<%= render "/icons/icon.svg.erb" %>

<p>yadda yadda yadda</p>

<%= render "/icons/icon.svg.erb" %>

现在页面上将有两个具有完全相同 ID 的元素,这…不好吗?

如果您依赖该 ID 用于任何与 JavaScript 相关的操作,那肯定是不好的,因为 JavaScript 只会找到第一个,这可能会造成混淆和奇怪的结果。

我不确定这是否对可访问性有害。也许其他人可以对此发表意见。假设标题相同,我的猜测是它不会有太大影响。

我认为这对 HTML 语义是不利的,但如果没有任何不良后果,我通常对此并不太在意。

如果您真的有兴趣解决此问题,我的首选方法是手动传入要使用的 ID。

同样,如果您在使用 Rails,您可以传递局部变量

<%=
  render(
    partial: "parts/modules/search",
    locals: {
      svg_id: "my-icon",
      title_id: "my-icon-title",
      desc_id: "my-icon-desc"
    }
  )
%>

然后设计图标以使用这些局部变量,例如

<svg title="<%= svg_id %> aria-labelledby="<%= title_id %>" ... >
 
   <title id="<%= title_id %>>
  
   ...

</svg>

您可以将此概念移植到任何语言。React 应用程序可以有

<SVGIcon svg_id="..." title_id="..." />

PHP 应用程序可以在 include 之前设置变量

$svg_id = "...";
$title_id = "...";
include("/icons/icon.svg.php");

现在,您只需管理 ID 以使其唯一,就像我们一直以来对 ID 所做的那样。

这篇文章的灵感来自 Austin Wolf,他遇到了这个问题,并 思考了一些解决方案。这还包括自动生成唯一的 ID

<svg aria-labelledby="star-6c84fb90-12c4-11e1-840d-7b25c5ee775a">
  <title id="star-6c84fb90-12c4-11e1-840d-7b25c5ee775a">star icon</title>
  // ...
</svg> 

对我来说,这似乎也是一个不错的解决方案。

我很想听听更多想法!