用Sass创建一个可维护的图标系统

用Sass创建一个可维护的图标系统
我最喜欢的向网站添加图标的方法之一是将它们作为数据URL背景图像包含::after在我的CSS中的伪元素(例如)中。该技术具有以下几个优点:

  • 除CSS文件外,它们不需要任何其他HTTP请求。
  • 使用该background-size属性,你可以将伪元素设置为您需要的任何大小,而不必担心它们会溢出边界(或被切断)。
  • 屏幕阅读器会忽略它们(至少在我使用Mac上的VoiceOver测试中),这对于仅装饰图标是有益的。

但是这种技术也存在一些缺点:

  • 当用作background-image数据URL时,你将无法使用“fill”或“stroke”CSS属性更改SVG的颜色(例如,如果您使用文件名引用url( ‘some-icon-file.svg’ ))。我们可以使用它filter()作为替代方案,但这可能并不总是一个可行的解决方案。
  • 当用作数据URL时,SVG标记可能看起来大而丑陋,当你需要在多个位置使用图标和/或必须更改它们时,它们很难维护。

我们将在本文中解决这两个缺点。

这种情况

让我们构建一个使用强大图标系统的站点,假设它有几个不同的按钮图标,它们都表示不同的操作:

  • 可下载内容的“下载”图标
  • 一个“外部链接”图标,用于指向另一个网站的按钮
  • 一个“右插入符号”图标,用于将我们带到流程的下一步

马上,我们就得到了三个图标。虽然这看起来并不多,但当我们将其扩展到更多的图标,如社交媒体网络等时,我已经开始担心它的可维护性了。就本文而言,我们将止步于这三个方面,但是你可以想象,在一个复杂的图标系统中,这会变得多么笨拙、多么迅速。

是时候编写代码了。首先,我们将设置一个基本按钮,然后通过使用BEM命名约定,我们将为其对应的按钮分配适当的图标。(在这一点上,有必要提醒你,我们将在Sass或更具体地说,SCSS中编写所有内容。为了便于讨论,假设我正在运行Autoprefixer来处理外观属性之类的东西。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.button {
  appearance: none;
  background: #d95a2b;
 border: 0;
  border-radius: 100em;
  color: #fff;
 cursor: pointer;
  display: inline-block;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  padding: 1em calc( 1.5em + 32px ) 0.9em 1.5em;
  position: relative;
  text-align: center;
  text-transform: uppercase;
  transition: background-color 200ms ease-in-out;

  &:hover,
  &:focus,
  &:active {
    background: #8c3c2a;
 }
}

这为我们提供了一个简单的、有吸引力的橙色按钮,该按钮在悬停、聚焦和活动状态时变为较暗的橙色。它甚至为我们想添加的图标提供了一点空间,所以现在让我们使用伪元素添加它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.button {

  /* everything from before, plus... */

  &::after {
    background: center / 24px 24px no-repeat; // Shorthand for: background-position, background-size, background-repeat
    border-radius: 100em;
    bottom: 0;
    content: '';
    position: absolute;
    right: 0;
    top: 0;
    width: 48px;
  }

  &--download {

    &::after {
      background-image: url( 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23fff" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>' );
      }
    }

  &--external {

    &::after {
      background-image: url( 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="31.408" height="33.919" viewBox="0 0 31.408 33.919"><g transform="translate(-1008.919 -965.628)"><g transform="translate(1046.174 2398.574) rotate(-135)"><path d="M0,0,7.879,7.879,0,15.759" transform="translate(1025.259 990.17) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><line y2="16.032" transform="translate(1017.516 980.5)" fill="none" stroke="%23fff" stroke-width="3"/></g><path d="M10683.643,5322.808v10.24h-20.386v-21.215h7.446" transform="translate(-9652.838 -4335)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>' );
    }
  }

  &--caret-right {

    &::after {
      background-image: url( 'data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.129 34.016"><path d="M1454.5,1298.922l15.947,15.947-15.947,15.947" transform="translate(-1453.439 -1297.861)" fill="none" stroke="%23fff" stroke-width="3"/></svg>' );
    }
  }
}

让我们先在这里停留下,虽然我们通过声明所有按钮的公共属性,然后只在每个类的基础上指定后台SVGs来保持SCSS尽可能整洁,但是它已经开始看起来有点笨拙了。这就是我之前提到的SVGs的第二个缺点:必须在CSS代码中使用大而丑陋的标记。

另外,请注意我们如何在SVG中定义填充和描边颜色。在某些时候,浏览器认为我们都知道并喜欢我们的十六进制颜色的octothorpe(“#”)存在安全风险,并宣称它们将不再支持包含它们的数据URL。这给我们留下了三个选择:

  • 将我们的数据url从标记(就像我们这里所做的)转换为以base-64编码的字符串,但是这使得它们比以前更难以维护,因为完全混淆了它们;或
  • 使用rgba()或hsla()表示法,并不总是像许多开发人员多年来一直使用十六进制那样直观;或
  • 将我们的10 – thorpe转换为其url编码的等效值“%23”。

我们将选择第三个选项,并解决浏览器的限制。(但是,我在这里要提到的是,这种技术将适用于rgb()、hsla()或任何其他有效的颜色格式,甚至是名为colors的CSS。但是请不要在生产代码中使用CSS命名的颜色。)

移动的地图

此时,我们只声明了三个按钮。但我不喜欢把它们像这样扔进代码里。如果我们需要在其他地方使用这些相同的图标,我们必须复制和粘贴SVG标记,否则我们可以将它们分配给变量(Sass或CSS自定义属性),并以这种方式重用它们。但我还是要试试三号门背后的东西,转而使用Sass最强大的功能之一:地图。

如果你不熟悉Sass映射,那么它们实际上是关联数组的Sass版本。我们可以指定一个名称(如果您愿意,也可以指定一个键),这样我们就可以通过一些逻辑的、容易记住的东西来检索它们,而不是用数字索引的项数组。所以让我们建立一个Sass地图,我们的三个图标:

1
2
3
4
5
$icons: (
  'download':    '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23fff" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>',
  'external':    '<svg xmlns="http://www.w3.org/2000/svg" width="31.408" height="33.919" viewBox="0 0 31.408 33.919"><g transform="translate(-1008.919 -965.628)"><g transform="translate(1046.174 2398.574) rotate(-135)"><path d="M0,0,7.879,7.879,0,15.759" transform="translate(1025.259 990.17) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><line y2="16.032" transform="translate(1017.516 980.5)" fill="none" stroke="%23fff" stroke-width="3"/></g><path d="M10683.643,5322.808v10.24h-20.386v-21.215h7.446" transform="translate(-9652.838 -4335)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>',
  'caret-right': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.129 34.016"><path d="M1454.5,1298.922l15.947,15.947-15.947,15.947" transform="translate(-1453.439 -1297.861)" fill="none" stroke="%23fff" stroke-width="3"/></svg>',
);

这里需要注意两件事:我们没有包含数据:image/svg+xml;utf-8,这些图标中的字符串,只有svg标记本身。每次我们需要使用这些图标时,这个字符串都是相同的,所以为什么要重复我们自己并冒着出错的风险呢?让我们将其定义为自己的字符串,并在需要时将其添加到图标标记中:

1
$data-svg-prefix: 'data:image/svg+xml;utf-8,';

另一件需要注意的事情是,我们实际上并没有使SVG更漂亮;那是不可能的。我们所做的就是把那些丑陋的代码从我们每天工作的代码中去掉,这样我们就不用那么多地去看那些乱七八糟的东西了。见鬼,我们甚至可以把它放在它自己的部分,我们只需要触摸当我们需要添加更多的图标。眼不见,心不烦!

现在,让我们用我们的地图。回到我们的按钮代码,我们现在可以用从图标地图中拉出这些图标来替换这些图标文字:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
&--download {

  &::after {
    background-image: url( $data-svg-prefix + map-get( $icons, 'download' ) );
  }
}

&--external {

  &::after {
    background-image: url( $data-svg-prefix + map-get( $icons, 'external' ) );
  }
}

&--next {

  &::after {
    background-image: url( $data-svg-prefix + map-get( $icons, 'caret-right' ) );
  }
}

现在看起来好多了。我们已经开始以一种保持代码可读性和可维护性的方式抽象出我们的图标。如果这是唯一的挑战,我们就完成了。但在激发本文灵感的实际项目中,我们还有另一个问题:不同的颜色。

我们的按钮是纯色的,在悬停状态下会变成深一点的颜色。但是如果我们想要“ghost”按钮,而不是在悬停时变成纯色呢?在这种情况下,对于出现在白色背景上的按钮,白色图标将是不可见的(而且可能在非白色背景上看起来是错误的)。我们需要的是每个图标的两种变体:用于悬停状态的白色图标,以及用于非悬停状态的匹配按钮边框和文本颜色的图标。

让我们更新按钮的基本CSS,将它从一个固态按钮转换为一个悬停时变为固态的ghost按钮。我们还需要调整图标的伪元素,这样我们也可以在悬停时将它们替换掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.button {
  appearance: none;
  background: none;
  border: 3px solid #d95a2b;
 border-radius: 100em;
  color: #d95a2b;
 cursor: pointer;
  display: inline-block;
  font-size: 18px;
  font-weight: bold;
  line-height: 1;
  padding: 1em calc( 1.5em + 32px ) 0.9em 1.5em;
  position: relative;
  text-align: center;
  text-transform: uppercase;
  transition: 200ms ease-in-out;
  transition-property: background-color, color;

  &:hover,
  &:focus,
  &:active {
    background: #d95a2b;
   color: #fff;
 }
}

现在我们需要创建不同颜色的图标。一个可能的解决方案是直接将颜色变化添加到我们的地图…在某种程度上。我们既可以在一维地图中添加不同颜色的新图标作为附加项,也可以使地图成为二维地图。

一维映射:

1
2
3
4
$icons: (
  'download-white':  '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23fff" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>',
  'download-orange': '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23d95a2b" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23d95a2b" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23d95a2b" stroke-width="3"/></g></svg>',
);

二维映射:

1
2
3
4
5
6
$icons: (
  'download': (
    'white':  '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23fff" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>',
    'orange': '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23d95a2b" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23d95a2b" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23d95a2b" stroke-width="3"/></g></svg>',
  ),
);

无论如何,这都是有问题的。只要再增加一种颜色,我们就能使维护工作加倍。需要更改现有的下载图标与一个不同的?我们需要手动创建每个颜色变化,将其添加到地图。需要第三种颜色吗?现在,您只需将维护成本增加两倍。我甚至不打算在代码中从多维Sass映射中检索值,因为这不能满足我们的最终目标。相反,我们要继续改进。

输入字符串替换

除了映射之外,本文中Sass的实用功能还来自于如何使用它使CSS的行为更像一种编程语言。Sass有内置函数(如map-get(),我们已经看到了),它允许我们编写自己的函数。

Sass还内置了一组字符串函数,但令人费解的是,字符串替换函数不在其中。这太糟糕了,因为它的实用性是显而易见的。但并不是所有的都失去了。

Hugo Giradel在2014年的CSS-Tricks上为我们提供了一个sr -replace()的Sass版本。我们可以使用它在这里创建一个版本的图标在我们的Sass地图,使用占位符为我们的颜色值。让我们把这个函数添加到我们自己的代码中:

1
2
3
4
5
6
7
8
9
10
@function str-replace( $string, $search, $replace: '' ) {

  $index: str-index( $string, $search );

  @if $index {
    @return str-slice( $string, 1, $index - 1 ) + $replace + str-replace( str-slice( $string, $index + str-length( $search ) ), $search, $replace);
  }

  @return $string;
}

接下来,我们将更新原始的Sass图标映射(只有图标的白色版本),将白色替换为占位符(%%COLOR%%),我们可以根据需要将其替换为所需的任何颜色。

1
2
3
4
5
$icons: (
  'download':    '<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%%COLOR%%" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%%COLOR%%" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%%COLOR%%" stroke-width="3"/></g></svg>',
  'external':    '<svg xmlns="http://www.w3.org/2000/svg" width="31.408" height="33.919" viewBox="0 0 31.408 33.919"><g transform="translate(-1008.919 -965.628)"><g transform="translate(1046.174 2398.574) rotate(-135)"><path d="M0,0,7.879,7.879,0,15.759" transform="translate(1025.259 990.17) rotate(90)" fill="none" stroke="%%COLOR%%" stroke-width="3"/><line y2="16.032" transform="translate(1017.516 980.5)" fill="none" stroke="%%COLOR%%" stroke-width="3"/></g><path d="M10683.643,5322.808v10.24h-20.386v-21.215h7.446" transform="translate(-9652.838 -4335)" fill="none" stroke="%%COLOR%%" stroke-width="3"/></g></svg>',
  'caret-right': '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.129 34.016"><path d="M1454.5,1298.922l15.947,15.947-15.947,15.947" transform="translate(-1453.439 -1297.861)" fill="none" stroke="%%COLOR%%" stroke-width="3"/></svg>',
);

但是,如果我们试图仅使用新的str-replace()函数和Sass的内置map-get()函数来获取这些图标,我们将得到一个又大又丑的结果。我宁愿把这两个一起一个函数,调用我们想要的图标在我们想要的颜色,那么简单一个函数有两个参数(因为我特别懒,我们甚至会默认为白色,我们可以省略参数,如果这是我们想要的彩色图标)。

因为我们得到了一个图标,它是一个getter函数,我们把它叫做get-icon():

1
2
3
4
5
6
7
8
9
@function get-icon( $icon, $color: #fff ) {

  $icon:        map-get( $icons, $icon );
  $placeholder: '%%COLOR%%';

  $data-uri: str-replace( url( $data-svg-prefix + $icon ), $placeholder, $color );

  @return str-replace( $data-uri, '#', '%23' );
}

还记得我们在哪里说过浏览器不会呈现包含10 / thorpe的数据url吗?是的,我们还使用了str-replace()ing,所以我们不必记住在颜色十六进制代码中传递“%23”。

附注:我也有一个用于抽象颜色的Sass函数,但是由于这超出了本文的范围,所以我将在你空闲时参考我的get-color()要点。

结果

现在我们有了get-icon()函数,让我们使用它。回到按钮代码,我们可以用新的图标getter替换map-get()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
&--download {

  &::before {
    background-image: get-icon( 'download', #d95a2b );
 }

  &::after {
    background-image: get-icon( 'download', #fff ); // The ", #fff" isn't strictly necessary, because white is already our default
 }
}

&--external {

  &::before {
    background-image: get-icon( 'external', #d95a2b );
 }

  &::after {
    background-image: get-icon( 'external' );
  }
}

&--next {

  &::before {
    background-image: get-icon( 'arrow-right', #d95a2b );
 }

  &::after {
    background-image: get-icon( 'arrow-right' );
  }
}

简单多了,不是吗?现在我们可以调用我们定义的任何图标,以及我们需要的任何颜色。所有这些都使用简单、干净、逻辑的代码。

  • 我们只需要在一个地方声明SVG。
  • 我们有一个函数,它能得到我们给它的任何颜色的图标。
  • 所有内容都抽象为一个逻辑函数,该函数的功能与它的功能完全相同:获取Y颜色的X图标。

让它变得万无一失

我们缺少的一件事是错误检查。我非常相信无声的失败……或者至少,失败以一种用户看不到的方式清楚地告诉开发人员哪里出了问题,以及如何修复它。(出于这个原因,我应该比现在更多地使用单元测试,但这是另一个话题。)

降低函数出错倾向的一种方法是设置默认颜色(在本例中是白色)。因此,如果使用get-icon()的开发人员忘记添加颜色,不用担心;图标将是白色的,如果这不是开发人员想要的,它是显而易见的,很容易修复。

但是等等,如果第二个参数不是颜色呢?好像开发人员输入了一个错误的颜色,使它不再被Sass处理器识别为一个颜色?

幸运的是,我们可以检查$color变量是什么类型的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@function get-icon( $icon, $color: #fff ) {

  @if 'color' != type-of( $color ) {

    @warn 'The requested color - "' + $color + '" - was not recognized as a Sass color value.';
    @return null;
  }

  $icon:        map-get( $icons, $icon );
  $placeholder: '%%COLOR%%';
  $data-uri:    str-replace( url( $data-svg-prefix + $icon ), $placeholder, $color );

  @return str-replace( $data-uri, '#', '%23' );
}

如果我们想输入一个无意义的颜色值:

1
2
3
4
5
6
&--download {

  &::before {
    background-image: get-icon( 'download', ce-nest-pas-un-couleur );
  }
}

我们得到的输出解释了我们的错误:

1
Line 25 CSS: The requested color - "ce-nest-pas-un-couleur" - was not recognized as a Sass color value.

处理就停止了。

但是如果开发人员没有声明图标呢?或者,更有可能声明一个在Sass映射中不存在的图标?在这种情况下,提供默认图标实际上没有意义,这就是为什么图标首先是一个强制参数。但为了确保我们调用的是一个图标,它是有效的,我们要添加另一个检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@function get-icon( $icon, $color: #fff ) {

  @if 'color' != type-of( $color ) {

    @warn 'The requested color - "' + $color + '" - was not recognized as a Sass color value.';
    @return null;
  }

  @if map-has-key( $icons, $icon ) {

    $icon:        map-get( $icons, $icon );
    $placeholder: '%%COLOR%%';
    $data-uri:    str-replace( url( $data-svg-prefix + $icon ), $placeholder, $color );

    @return str-replace( $data-uri, '#', '%23' );
  }

  @warn 'The requested icon - "' + $icon + '" - is not defined in the $icons map.';
  @return null;
}

我们将函数的主体封装在一个@if语句中,该语句检查映射是否提供了键。如果是这样(这是我们希望的情况),则返回处理后的数据URL。函数在@return处停止,这就是我们不需要@else语句的原因。

但是,如果没有找到图标,则返回null,并在控制台输出中返回一个@warning来标识问题请求,加上部分文件名和行号。现在我们确切地知道哪里出了问题,什么时候需要修复,什么需要修复。

所以如果我们不小心进入:

1
2
3
4
5
6
&--download {

  &::before {
    background-image: get-icon( 'ce-nest-pas-une-icône', #d95a2b );
 }
}

我们会看到输出在我们的控制台,我们的Sass进程正在观看和运行:

1
Line 32 CSS: The requested icon - "ce-nest-pas-une-icône" - is not defined in the $icons map.

至于按钮本身,图标所在的区域将为空白。虽然没有我们想要的图标那么好,但是比破碎的图像或类似的要好得多。

最终代码

在所有这些之后,让我们来看看我们最终的,经过处理的CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
.button {
  -webkit-appearance: none;
      -moz-appearance: none;
          appearance: none;
  background: none;
  border: 3px solid #d95a2b;
 border-radius: 100em;
  color: #d95a2b;
 cursor: pointer;
  display: inline-block;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  padding: 1em calc( 1.5em + 32px ) 0.9em 1.5em;
  position: relative;
  text-align: center;
  text-transform: uppercase;
  transition: 200ms ease-in-out;
  transition-property: background-color, color;
}
.button:hover, .button:active, .button:focus {
  background: #d95a2b;
 color: #fff;
}
.button::before, .button::after {
  background: center / 24px 24px no-repeat;
  border-radius: 100em;
  bottom: 0;
  content: '';
  position: absolute;
  right: 0;
  top: 0;
  width: 48px;
}
.button::after {
  opacity: 0;
  transition: opacity 200ms ease-in-out;
}
.button:hover::after, .button:focus::after, .button:active::after {
  opacity: 1;
}
.button--download::before {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23d95a2b" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23d95a2b" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23d95a2b" stroke-width="3"/></g></svg>');
}
.button--download::after {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="30.544" height="25.294" viewBox="0 0 30.544 25.294"><g transform="translate(-991.366 -1287.5)"><path d="M1454.5,1298.922l6.881,6.881-6.881,6.881" transform="translate(2312.404 -157.556) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><path d="M8853.866,5633.57v9.724h27.544v-9.724" transform="translate(-7861 -4332)" fill="none" stroke="%23fff" stroke-linejoin="round" stroke-width="3"/><line y2="14" transform="translate(1006.5 1287.5)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>');
}
.button--external::before {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="31.408" height="33.919" viewBox="0 0 31.408 33.919"><g transform="translate(-1008.919 -965.628)"><g transform="translate(1046.174 2398.574) rotate(-135)"><path d="M0,0,7.879,7.879,0,15.759" transform="translate(1025.259 990.17) rotate(90)" fill="none" stroke="%23d95a2b" stroke-width="3"/><line y2="16.032" transform="translate(1017.516 980.5)" fill="none" stroke="%23d95a2b" stroke-width="3"/></g><path d="M10683.643,5322.808v10.24h-20.386v-21.215h7.446" transform="translate(-9652.838 -4335)" fill="none" stroke="%23d95a2b" stroke-width="3"/></g></svg>');
}
.button--external::after {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="31.408" height="33.919" viewBox="0 0 31.408 33.919"><g transform="translate(-1008.919 -965.628)"><g transform="translate(1046.174 2398.574) rotate(-135)"><path d="M0,0,7.879,7.879,0,15.759" transform="translate(1025.259 990.17) rotate(90)" fill="none" stroke="%23fff" stroke-width="3"/><line y2="16.032" transform="translate(1017.516 980.5)" fill="none" stroke="%23fff" stroke-width="3"/></g><path d="M10683.643,5322.808v10.24h-20.386v-21.215h7.446" transform="translate(-9652.838 -4335)" fill="none" stroke="%23fff" stroke-width="3"/></g></svg>');
}
.button--next::before {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.129 34.016"><path d="M1454.5,1298.922l15.947,15.947-15.947,15.947" transform="translate(-1453.439 -1297.861)" fill="none" stroke="%23d95a2b" stroke-width="3"/></svg>');
}
.button--next::after {
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.129 34.016"><path d="M1454.5,1298.922l15.947,15.947-15.947,15.947" transform="translate(-1453.439 -1297.861)" fill="none" stroke="%23fff" stroke-width="3"/></svg>');
}

哎呀,还是挺丑的,但丑成了浏览器的问题,而不是我们的问题。

我已经将所有这些放在CodePen中,供大家进行分支和实验。这个小项目的长期目标是创建一个PostCSS插件来完成所有这些。这将增加该技术对每个人的可用性,无论他们是否使用CSS预处理器,或他们使用的是哪个预处理器。

“如果我看得更远,那是因为我站在巨人的肩膀上。”

——艾萨克·牛顿 1675年

结束语

以上就是今天码云笔记为大家带来的关于用Sass创建一个可维护的图标系统的全部内容,希望对大家有帮助,也欢迎大家留言讨论。

未经允许不得转载:码云笔记 » 用Sass创建一个可维护的图标系统
喜欢(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

在线客服

在线客服

  • 扫描二维码,微信联系 扫描二维码,微信联系