前端图标解决方案

news2024/10/7 6:39:32

1. 前言

随着 Web 技术的发展与日益丰富的界面需求,图标逐渐成为前端开发中不可或缺的一部分,为此也诞生了各种各样的解决方案。文章总结及分析了目前常见的一些图标解决方案。

2. CSS 背景图片

2.1 background-image

图标本质上也是图片,所以一种最简单的方式就是利用background-image将图片作为图标容器的背景,例如:

css
复制代码
.icon {
  background-image: url("demo.jpg");
}

但是一个页面里往往会有很多图标,如果每个图标都去请求一次图片,会导致 HTTP 请求数量较多,我们知道 HTTP 并发请求数量是有上限的(例如 Chrome 最大是 6,HTTP/2 没有并发限制,此处暂且不论),请求太多图片会导致后面加载的图片被前面的图片阻塞,进而降低整体响应时间。为了解决这个问题,我们可以使用图像合并技术(Image Sprites)。

2.2 CSS Sprites

图像合并技术的原理是将多个图片合并成一个图片,使用时获取该图片的部分内容。这种做法有效减少了图片的请求数量,刚好适合图标的应用。

CSS Sprites(精灵图,雪碧图) 就是利用 CSS 背景图片实现图像合并的技术,图像合并可以使用其他方式,图像的部分获取主要是使用background-position配合background-image实现。例如,假设有一张 100px * 50px 的合并图片cat.png

sprites.png

展示左边的笑脸猫可以使用:

css
复制代码
/* 笑脸猫 */
.icon1 {
  width: 50px;
  height: 50px;
  background-image: url("cat.png");
  background-position: 0 0; /* 不偏移 */
}

展示右边的傲娇猫可以使用:

css
复制代码
/* 傲娇猫 */
.icon2 {
  width: 50px;
  height: 50px;
  background-image: url("cat.png");
  background-position: -50px 0; /* 向左偏移 50px */
}

实际使用时可以将公共的部分提取出来,不同的图标只需改变background-position

css
复制代码
.icon {
  width: 50px;
  height: 50px;
  background-image: url("cat.png");
}
.icon1 {
  background-position: 0 0; /* 不偏移 */
}
.icon2 {
  background-position: -50px 0; /* 向左偏移 50px */
}

根据 CSS Sprites 的原理,容易得出与其相关的一些结论:

  • 适用于固定容器尺寸:对于一个合并图像,每个图标的尺寸是固定的,如果一个图标要适应较多的容器,就会产生一些问题:

    • 图标尺寸 = 容器尺寸:最佳状态;
    • 图标尺寸 < 容器尺寸:图标可能失真;
    • 图标尺寸 > 容器尺寸:配合background-size可以兼容所有情况,但是整个合并图像尺寸会比较大,导致请求速度较慢。

    实际使用中可以设计多套不同尺寸的图标使用,但是维护成本也会相应增加。

  • 适用于不需要频繁更改的场景:图片文件的维护成本相对较高,频繁新增,更改,甚至删除都会极大增加维护成本,如果是多套不同图标,维护会更困难。

  • 图标颜色是固定的,不能随意更改。

  • CSS 计算图标位置时很容易出错,最好借助三方工具去设计,比如 CSS Sprites Generator。

3. 字体图标

3.1 字体图标介绍

字体图标是另一种常见的图标解决方案,其基本原理是将一组图标(例如 SVG 文件)打包成一种字体,将该字体加载到网页后,使用与某个图标对应的 Unicode 字符编码去显示该图标。例如在图标库Material Design Icons(mdi) 中,如果要显示一个 account 图标:

account.svg(2).png

需要以下两步:

  1. 使用@font-face加载字体:
css
复制代码
@font-face {
  font-family: "Material Design Icons";
  src: url("materialdesignicons-webfont.woff2"); // 路径应替换成字体文件路径
}
  1. 引用字体:

根据 mdi 文档,account 图标对应的字符编码是U+F004,在 HTML 中可以这样引用:

html
复制代码
<!-- &#xF004 是 U+F004 在 HTML 中的表示方法 -->
<span style="font-family: 'Material Design Icons'">&#xF004</span>

实际中因为字符编码使用不便,一般会在 CSS 中定义一些类:

css
复制代码
/* 公共类,所有图标都依赖该类 */
.mdi {
  font-family: 'Material Design Icons';
}
/* account 定制类,\F004 为 U+F004 在 CSS 中的表示方法 */
.mdi-account::before {
  content: '\F004';
}

在 HTML 中,只需要使用<span class="mdi mdi-account"></span>即可显示 account 图标。

3.2 字体图标分析

相比 CSS Sprites 来说,字体图标有不少优势,如:

  • 可以适应不同容器尺寸。
  • 可以自由更改图标颜色。
  • 使用与维护要比 CSS Sprites 方便很多。

当然了,也会有一些劣势:

  • 只能使用纯色图标,对彩色图标无能为力。

字体图标还有一个很大的问题,公共的图标库(如 mdi)为了满足各种各样的需求都会有很多图标,我们的项目并不会全部使用,这样在前端打包的时候就会浪费很多空间,导致页面首屏加载速度减慢。

为了解决这个问题,我们可以尝试在字体打包阶段介入(毕竟即使可以处理字体中的 CSS,也无法解决字体文件过大的问题)。字体打包实际上就是将一系列图标文件转化为了字体文件与字体样式,如果我们能够控制转换的过程以及转换的目标,这个问题就可以解决。仍以 mdi 图标为例:所有的 mdi 图标存放在@mdi/svg包,mdi 打包过程可以使用@mdi/font-build包实现,这个包可以指定需要转换的图标以及最终的字体格式。如果我们能够搜集到应用中所有使用到的图标(很不舒服的一点是这一步只能手动检索),那么我们就可以控制最终的字体文件大小。

另外,我们也可以控制最终生成的字体格式,实际上,现代浏览器很多已经支持了woff2格式,因此如果不需要兼容很早的浏览器,完全可以只引用woff2字体(woff2字体具有更小的尺寸)。当然了,我们可以根据需求进行调整,浏览器对字体格式的支持程度如下:

  • woff2:caniuse.com/?search=wof… 推荐,需要考虑兼容性。
  • woff:caniuse.com/?search=wof… 推荐,已经被绝大部分浏览器支持了。
  • ttf/otf:caniuse.com/?search=ttf 不推荐。
  • eot:caniuse.com/?search=eot 不推荐,只有 IE 支持。

4. SVG 图标

4.1 内嵌 SVG

SVG 能够绘制矢量图,在不同的容器尺寸下不会有失真的情况,将 SVG 直接嵌入在 HTML 中即可使用,例如:

html
复制代码
<div style="width: 50px; height: 50px;">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z"/>
  </svg>
</div>

即可画出:

account.svg(2).png

相比字体图标来说,内嵌 SVG 可以渲染彩色图标,这是一个较大的优势,但是这种方案也有一个问题,就是如果同一个图标使用了很多次,需要重复很多相同的 SVG,从代码层面上我们可以使用变量去存储,但是 HTML 解析的时候还是会重复解析。为了解决这个问题,我们可以使用 SVG Sprites。

4.2 SVG Sprites

类似于 CSS Sprites,SVG Sprites 就是将多个 SVG 合并到一个 SVG 文件中,在引用的时候将需要的 SVG 内容取出,从而达到复用 SVG 的目的。其基本做法是利用 SVG <symbol> 元素定义图标,然后使用<use>元素引用图标。例如,有一个 account 的 SVG 图像如下:

svg
复制代码
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
  <path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
</svg>

我们可以使用<symbol>元素将其定义在一个sprites.svg的文件中:

svg
复制代码
<!-- sprites.svg -->
<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="account" viewBox="0 0 24 24"> <!-- 使用 account id 标识该图标 -->
    <path d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z"/>
  </symbol>
</svg>

在 HTML 中可以这样使用:

html
复制代码
<div style="width: 50px; height: 50px;">
  <svg viewBox="0 0 24 24">
    <!-- 引用该图标(文件名#ID) -->
    <use xlink:href="sprites.svg#account"></use>
  </svg>
</div>

这样就可以正确绘制出 account 图标了。

结合以上的图标方案可以看出 SVG Sprites 几乎可以支持各种类型的图标,在其他方案解决不了的情况下可以考虑这种,如果图标不是很多,也可以直接嵌入 SVG。当然了,使用 SVG Sprites 的时候也需要关注下浏览器兼容性:

  • <symbol>:caniuse.com/?search=svg…
  • <use>:caniuse.com/?search=svg…

5. CSS 绘制

图标的另一个解决方案是直接使用 CSS 绘制,这种方案利用 CSS borderbox-shadowtransform等属性结合伪元素beforeafter拼出图标,使用的时候直接引用相应的类名即可,具体做法可以参考 css.gg/ 。

这种做法的优势是使用方便,还能够使用animation支持动态图标,劣势是图标库的设计较为复杂,只能使用一些简单的图标,如果过于复杂,实现起来会比较困难,即便可以实现也会有大量的 CSS 代码,使用的时候需要综合考虑。

6. 小结

本文总结了前端开发中常见的一些图标解决方案,并分析了不同解决方案的优劣势。目前比较主流的方案是字体图标和 SVG 图标,CSS Sprites 和 CSS 绘制可以在特定场景下使用。

学习更多前端知识请关注CRMEB

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/791296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

子网划分和计网解题方法

子网的基本概念 子网是计算机网络中的一个逻辑单元&#xff0c;是由多个IP地址组成的网络。在计算机网络中&#xff0c;IP地址是一个32位的二进制数&#xff0c;用于标识网络上的设备。子网划分是将一个大型的IP地址网络划分为多个小的IP地址网络&#xff0c;每个小的IP地址网…

软件外包开发的项目管理工具

在开发大型项目时涉及到多人管理&#xff0c;细节比较多&#xff0c;需要借助科学的项目管理方法和软件工具来提高软件项目效率。现在有比较多的项目管理方法和配套工具&#xff0c;每个项目和团队的情况不同&#xff0c;选择适合自己的是最重要的。今天和大家分享软件项目管理…

小程序新渲染引擎 Skyline 发布正式版

为了进一步提升小程序的渲染性能和体验&#xff0c;我们推出了一套新渲染引擎 Skyline&#xff0c;现在&#xff0c;跟随着基础库 3.0.0 发布 Skyline 正式版。 我们知道&#xff0c;小程序一直用 WebView 来渲染界面&#xff0c;因其有不错的兼容性和丰富的特性&#xff0c;且…

【通世智库】陈敏华:永存我心的爱——忆我的丈夫陶一凡

​ 2022年12月25日&#xff0c;我敬爱的丈夫&#xff0c;平静安然的告别了眷恋着他的亲友们&#xff0c;走了。 72年前&#xff0c;在上海致远中学上学不满16岁的陶一凡&#xff0c;毅然弃笔从戎&#xff0c;随志愿军跨过鸭绿江&#xff0c;奔赴朝鲜战场。他说过&#xff0c;12…

企业通过CRM分析销售数据有什么用处?

企业为什么要分析CRM销售数据&#xff1f;分析CRM销售数据的目的&#xff0c;是为企业提供对其销售业绩、客户行为和市场趋势的宝贵见解。通过分析这些数据&#xff0c;企业可以确定他们表现良好的领域和需要改进的领域。 1、销售业绩 通过分析CRM销售数据&#xff0c;企业可…

云计算——ACA学习 数据中心概述

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 写在前面 课程目标 学前了解 一.数据中心定义 二.数据中心涉及的主要标准与规范 …

adas知识

车辆坐标系 右手坐标系&#xff0c;红色箭头方向角度为正。 传感器坐标系&#xff08;如相机&#xff09;

关于项目,会问我什么?

作者&#xff1a;阿秀 校招八股文学习网站&#xff1a;https://interviewguide.cn 这是阿秀的第「288」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 在校招求职这块&#xff0c;简历上比较重要的点就是教育背景、实习经历、项目经验三块&#xff0c;其中教育背景都到了秋招这…

TencentOS Server镜像操作系统介绍_常见问题解答FAQ

腾讯云TencentOS Server镜像是腾讯云推出的Linux操作系统&#xff0c;完全兼容CentOS生态和操作方式&#xff0c;TencentOS Server操作系统为云上运行的应用程序提供稳定、安全和高性能的执行环境&#xff0c;TencentOS可以运行在腾讯云CVM全规格实例上&#xff0c;包括黑石物理…

naive-ui的dialog.warning 关闭和阻止关闭

序&#xff1a; 1、如果你卡到 了&#xff0c;博主没写博客&#xff0c;可以在博主的公众号&#xff1a;“程序员野区” 留言。博主看到有时间再帮你去试 2、博主主要讲的怎么 主动关闭dialog和阻止dialog 自动关闭。 注意&#xff01;&#xff01;&#xff01;&#xff01;来&…

蛋白组学富集分析 uniport id蛋白ID如何进行KEGG和GO富集分析 代谢组学

使用蛋白ID如何进行KEGG和GO富集分析 - 知乎 (zhihu.com) 昨天&#xff0c;有个童鞋咨询如何使用蛋白ID进行功能富集分析&#xff0c;功能富集分析主要是KEGG和GO。 思路 蛋白ID转UniProt数据库IDUniProt数据库ID转KEGG和GO号使用KEGG和GO号进行富集分析 教程&#xff08;实操…

5.CSS(二)

目录 一、Emmet语法 &#xff08;一&#xff09;快速生成HTML结构语法 &#xff08;二&#xff09;快速生成CSS样式语法 二、CSS的复合选择器 &#xff08;一&#xff09;后代选择器&#xff08;重要&#xff09; &#xff08;二&#xff09;子选择器&#xff08;重要&…

这些文档翻译软件助力你成功翻译外语文档

明华&#xff1a;嘿&#xff0c;你知道吗&#xff1f;我刚刚发现了三款超级好用的文档翻译软件&#xff01;简直就是我的救星啊&#xff01; 彦琪&#xff1a;真的吗&#xff1f;我在翻译文档的问题一直觉得很头痛。我想找一款网站来翻译文档&#xff0c;又不知道文档翻译在线…

Nginx教程(相关概念)

Nginx 简介 1、什么是Nginx Nginx(engine x") 是一个高性能的HTTP和反向代理服务器,特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力确实在同类型的网页服务器中表现较好Nginx专为性能优化而开发&#xff0c;性能是其最重要的考量…

vue中在使用keep-alive时,会出现在页面跳转后el-tooltip或el-dropdown不消失的问题以及解决方法

一、 问题复现 跳转前&#xff1a; 跳转后&#xff1a; 二、分析 由于在vue中使用了keep-alive&#xff0c;页面在切换时&#xff0c;上一个页面的实例被缓存了&#xff0c;跳转后并没有销毁&#xff0c;所以才会残留 tooltip或dropdown&#xff0c;所以有以下解决思路&am…

[C++] C++入门第一篇 -- 命名空间,输入输出,缺省函数,函数重载底层原理

目录 1、关键字 2、命名空间 2.1 命名空间的定义 2.2 命名空间的使用方式 2.2.1 加命名空间名称及作用域限定符 2.2.2 使用using将命名空间中某个成员引入 2.2.3 使用using namespace 命名空间名称引入 3、C输入与输出 4、缺省参数 4.1 缺省参数的概念 4.2 缺省参数…

Blazor前后端框架Known-V1.2.7

V1.2.7 Known是基于C#和Blazor开发的前后端分离快速开发框架&#xff0c;开箱即用&#xff0c;跨平台&#xff0c;一处代码&#xff0c;多处运行。 Gitee&#xff1a; https://gitee.com/known/KnownGithub&#xff1a;https://github.com/known/Known 概述 基于C#和Blazor…

预科C语言

1.day10 1、perror() 原型&#xff1a;void perror(const char *s); 根据errno呈现错误信息 perror("malloc error"); malloc error: Cannot allocate memory 2、多文件编译 .c ---预处理&#xff08;.i -E&#xff09;---汇编&#xff08;.s -S&#xf…

threeJs着色器ShaderMaterial以及统一着色语言GLSL语法基本介绍

一、着色器材质ShaderMaterial的基本使用 废话不多讲先来看案例 console.log(着色器入门)// 引入three.js import * as THREE from three // 引入OrbitControls控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls// 初始化场景 const scene n…

git 提交换行符问题:LF would be replaced by CRLF

提交git 记录时&#xff0c;遇到问题 fatal: LF would be replaced by CRLF 原因: 是因为git换行符的导致Unix/Linux使用的是LF&#xff0c;Mac后期也采用了LF&#xff0c;但Windows一直使用CRLF 解决方案&#xff1a;禁止转换文件格式&#xff0c;其次允许提交换行符的文件 …