我如何使用 CSS 自定义属性 PlatoBlockchain 数据智能制作图标系统。 垂直搜索。 哎。

我如何使用 CSS 自定义属性制作图标系统

SVG 是网站上图标的最佳格式,有 毫无疑问. 无论屏幕像素密度如何,它都可以让您拥有清晰的图标,您可以在悬停时更改 SVG 的样式,甚至可以使用 CSS 或 JavaScript 为图标设置动画。

有很多方法可以在页面上包含 SVG,每种技术都有自己的优点和缺点。 在过去的几年里,我一直在使用 Sass 函数在我的 CSS 中直接导入我的图标,避免弄乱我的 HTML 标记。

我有一个 Sass 列表,其中包含我的图标的所有源代码。 然后将每个图标编码为具有 Sass 函数的数据 URI 并存储在 自定义属性 在页面的根部。

TL博士

我在这里给你的是一个 Sass 函数,它直接在你的 CSS 中创建一个 SVG 图标库。

SVG 源代码使用 Sass 函数编译,该函数将它们编码为数据 URI,然后将图标存储在 CSS 自定义属性中。 然后,您可以在 CSS 中的任何位置使用任何图标,就像它是外部图像一样。

这是一个直接从我的个人网站代码中提取的示例:

.c-filters__summary h2:after {
  content: var(--svg-down-arrow);
  position: relative;
  top: 2px;
  margin-left: auto;
  animation: closeSummary .25s ease-out;
}

演示

萨斯结构

/* All the icons source codes */
$svg-icons: (
  burger: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0...'
);

/* Sass function to encode the icons */
@function svg($name) {
  @return url('data:image/svg+xml, #{$encodedSVG} ');
}

/* Store each icon into a custom property */
:root {
  @each $name, $code in $svg-icons {
    --svg-#{$name}: #{svg($name)};
  }
}

/* Append a burger icon in my button */
.menu::after {
  content: var(--svg-burger);
}		

这种技术既有优点也有缺点,因此在您的项目中实施此解决方案之前,请考虑到它们:

优点

  • SVG 文件没有 HTTP 请求。
  • 所有图标都存储在一个地方。
  • 如果您需要更新图标,则不必检查每个 HTML 模板文件。
  • 图标与您的 CSS 一起缓存。
  • 您可以手动编辑图标的源代码。
  • 它不会通过添加额外的标记来污染您的 HTML。
  • 您仍然可以使用 CSS 更改图标的颜色或某些方面。

缺点

  • 您不能使用 CSS 为 SVG 的特定部分设置动画或更新。
  • 你拥有的图标越多,你的 CSS 编译文件就越重。

我主要将这种技术用于图标而不是徽标或插图。 编码的 SVG 总是比它的原始文件重,所以我仍然使用外部文件加载复杂的 SVG,或者使用 标记或在我的 CSS 中 url(path/to/file.svg).

将 SVG 编码为数据 URI

将 SVG 编码为数据 URI 并不新鲜。 实际上 Chris Coyier 写了一篇文章 关于它 10 多年前解释如何使用这种技术以及为什么你应该(或不应该)使用它。

有两种方法可以在 CSS 中使用带有数据 URI 的 SVG:

  • 作为外部图像(使用 background-image,边框图像,列表样式图像,...)
  • 作为伪元素的内容(例如 ::before or ::after)

这是一个基本示例,展示了如何使用这两种方法:

这种特定实现的主要问题是,每次需要新图标时都必须手动转换 SVG,而且在 CSS 中包含这么长的不可读代码字符串并不令人愉快。

这就是 Sass 来拯救的地方!

使用 Sass 函数

通过使用 Sass,我们可以通过将 SVG 的源代码直接复制到我们的代码库中来简化我们的工作,让 Sass 正确编码它们以避免任何浏览器错误。

该解决方案主要受 Threespot Media 开发的现有功能的启发,可在 他们的存储库.

以下是这项技术的四个步骤:

  • 创建一个列出所有 SVG 图标的变量。
  • 列出数据 URI 需要跳过的所有字符。
  • 实现将 SVG 编码为数据 URI 格式的函数。
  • 在代码中使用您的函数。

1.图标列表

/**
* Add all the icons of your project in this Sass list
*/
$svg-icons: (
  burger: ''
);

2.转义字符列表

/**
* Characters to escape from SVGs
* This list allows you to have inline CSS in your SVG code as well
*/
$fs-escape-chars: (
  ' ': '%20',
  ''': '%22',
  '"': '%27',
  '#': '%23',
  '/': '%2F',
  ':': '%3A',
  '(': '%28',
  ')': '%29',
  '%': '%25',
  '': '%3E',
  '': '%5C',
  '^': '%5E',
  '{': '%7B',
  '|': '%7C',
  '}': '%7D',
);

3.编码功能

/**
* You can call this function by using `svg(nameOfTheSVG)`
*/
@function svg($name) {
  // Check if icon exists
  @if not map-has-key($svg-icons, $name) {
    @error 'icon “#{$name}” does not exists in $svg-icons map';
    @return false;
  }

  // Get icon data
  $icon-map: map-get($svg-icons, $name);

  $escaped-string: '';
  $unquote-icon: unquote($icon-map);
  // Loop through each character in string
  @for $i from 1 through str-length($unquote-icon) {
    $char: str-slice($unquote-icon, $i, $i);

    // Check if character is in symbol map
    $char-lookup: map-get($fs-escape-chars, $char);

    // If it is, use escaped version
    @if $char-lookup != null {
        $char: $char-lookup;
    }

    // Append character to escaped string
    $escaped-string: $escaped-string + $char;
  }

  // Return inline SVG data
  @return url('data:image/svg+xml, #{$escaped-string} ');
}		

4. 在页面中添加 SVG

button {
  &::after {
    /* Import inline SVG */
    content: svg(burger);
  }
}

如果您已经按照这些步骤操作,Sass 应该正确编译您的代码并输出以下内容:

button::after {
  content: url("data:image/svg+xml, %3Csvg%20xmlns=%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox=%270%200%2024.8%2018.92%27%20width=%2724.8%27%20height=%2718.92%27%3E%3Cpath%20d=%27M23.8,9.46H1m22.8,8.46H1M23.8,1H1%27%20fill=%27none%27%20stroke=%27%23000%27%20stroke-linecap=%27round%27%20stroke-width=%272%27%2F%3E%3C%2Fsvg%3E ");
}		

自定义属性

现在实现的 Sass svg() 功能很好用。 但它最大的缺陷是代码中多个地方都需要的图标会被复制,并且可能会大大增加编译后的 CSS 文件的重量!

为了避免这种情况,我们可以将所有图标存储到 CSS 变量 并使用对变量的引用,而不是每次都输出编码的 URI。

我们将保留之前的代码,但这次我们首先将 Sass 列表中的所有图标输出到我们网页的根目录中:

/**
  * Convert all icons into custom properties
  * They will be available to any HTML tag since they are attached to the :root
  */

:root {
  @each $name, $code in $svg-icons {
    --svg-#{$name}: #{svg($name)};
  }
}

现在,而不是调用 svg() 每次我们需要一个图标时,我们都必须使用创建的变量 --svg 字首。

button::after {
  /* Import inline SVG */
  content: var(--svg-burger);
}

优化 SVG

此技术不会对您正在使用的 SVG 的源代码进行任何优化。 确保不要留下不必要的代码; 否则它们也会被编码,并会增加你的 CSS 文件大小。

您可以检查 这个很棒的清单 有关如何正确优化 SVG 的工具和信息。 我最喜欢的工具是 Jake Archibald 的 SVGOMG — 只需将您的文件拖到那里并复制输出的代码。

奖励:在悬停时更新图标

使用这种技术,我们无法使用 CSS 选择 SVG 的特定部分。 例如,没有办法改变 fill 用户悬停按钮时图标的颜色。 但是我们可以使用一些技巧和 CSS 来修改图标的外观。

例如,如果您有一个黑色图标,并且希望在悬停时将其设为白色,则可以使用 invert() CSS 过滤器。 我们也可以玩 hue-rotate() 过滤。

而已!

我希望您在自己的项目中发现这个小助手功能很方便。 让我知道你对这种方法的看法——我很想知道你如何使它变得更好或以不同的方式解决它!

时间戳记:

更多来自 CSS技巧