CSS 实现图标详解 image sprite、Icon Font、svg 和 CSS 绘制

蛮荒时期 CSS Sprites

在很久很久以前,使用图标一般是直接使用图片,或者使用雪碧图。缺点是颜色单一,难以维护。

//CSS
[class^="icon-"],[class*=" icon-"] {
	display: inline-block;
	width: 14px;
	height: 14px;
	margin-top: 1px;
	*margin-right: .3em;
	line-height: 14px;
	vertical-align: text-top;
	background-image: url(bootstrap/img/glyphicons-halflings-white.png);
	background-position: 14px 14px;
	background-repeat: no-repeat;
}
.icon-glass {
  background-position: 0 0;
}
.icon-music {
  background-position: -72px -48px;
}

// HTML
<span class="icon-music"></span>


CSS3 时代

CSS3 引入了 @font-face,允许使用自定义字体的一个模块。

@font-face {
  font-family: <YourWebFontName>;
  src: <source> [<format>][,<source> [<format>]]*;
  [font-weight: <weight>];
  [font-style: <style>];
}

@font-face CSS at-rule 指定一个用于显示文本的自定义字体;字体能从远程服务器或者用户本地安装的字体加载. 如果提供了local()函数,从用户本地查找指定的字体名称,并且找到了一个匹配项, 本地字体就会被使用. 否则, 字体就会使用url()函数下载的资源。

通过允许作者提供他们自己的字体,@font-face 让设计内容成为了一种可能,同时并不会被所谓的"网络-安全"字体所限制(字体如此普遍以至于它们能被广泛的使用). 指定查找和使用本地安装的字体名称可以让字体的自定义化程度超过基本字体,同时在不依赖网络情况下实现此功能。

在同时使用url()和local()功能时,为了用户已经安装的字体副本在需要使用时被使用,如果在用户本地没有找到字体副本就会去使用户下载的副本查找字体。

@font-face 规则不仅仅使用在CSS的顶层,还可以用在任何CSS条件组规则中.

// 举例
@font-face {
  font-family: "Bitstream Vera Serif Bold";
  src: url("https://developer.mozilla.org/@api/deki/files/2934/=VeraSeBd.ttf");
}

body { font-family: "Bitstream Vera Serif Bold", serif }


字体图标原理

有了font-face的支持,我们可以在HTML页面上添加一个 unicode 码,让该元素使用我们自定义字体里的样式。


字体格式简介

ttf / otf:TTF(TrueTypeFont)是Apple公司和Microsoft公司共同推出的字体文件格式,最常用的一种字体文件表示方式。因为这种格式容易被非法复制,后来产生了WOFF字体格式。

eot: EOT(Embedded Open Type),是微软创造的字体格式。这种格式只在IE6-IE8里使用。

woff:WOFF(Web Open Font Format)是一种网页所采用的字体格式标准。此字体格式发展于2009年,现在正由万维网联盟的Web字体工作小组标准化,以求成为推荐标准。此字体格式不但能够有效利用压缩来减少档案大小,并且不包含加密也不受DRM(数位著作权管理)限制。WOFF字体通常比其它字体加载要快,因为使用了OTF和TTF字体里的存储结构和压缩算法。这种字体格式还可以加入元信息和授权信息。

woff2(*):WOFF2(Web Open Font Format 2.0),相比woff最大的优化应该是加强了字体的压缩比。

SVG: Scalable Vector Graphics 是由W3C制定的开放标准的图形格式。SVG字体就是使用SVG技术来呈现字体,还有一种gzip压缩格式的SVG字体。


CSS3 字体图标的实现

方案一,使用 iconfont.cn

最简单的方法,设计师可以制作一些svg图标,上传到 iconfont.cn,然后 iconfont.cn 可以生成CSS代码。还有兼容各种浏览器的字体格式。

// 生成的实际代码大概如下:
@font-face {font-family: "iconfont";
  src: url('//t.com/t/font_22266d.eot?'); /* IE9 */
  src: url('//t.com/t/font_22266d.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
  url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAEJ...OnwA=') format('woff2'),
  url('//t.com/t/font_22266d.woff?') format('woff'),
  url('//t.com/t/font_22266d.ttf?') format('truetype'), 
  /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
  url('//t.com/t/font_22266d.svg?#iconfont') format('svg'); /* iOS 4.1- */
}

.iconfont{
  font-family:"iconfont" !important;
  font-size:16px;font-style:normal;
  -webkit-font-smoothing: antialiased;
  -webkit-text-stroke-width: 0.2px;
  -moz-osx-font-smoothing: grayscale;
}

.icondanxuanfill:before {
  content: "\e71e";
}

.icondanxuan:before {
  content: "\e71f";
}

.iconfangxingweixuanzhong:before {
  content: "\e720";
}

.iconfangxingxuanzhongfill:before {
  content: "\e721";
}
...

使用方法:

// 通过字体编码引用
<i class="iconfont">&#x33;</i>
// 通过类引用
<i class="iconfont icon-xxx"></i>


方案二 直接引入SVG做图标,然后再来个 SVG-Sprite,未来的趋势

首先定义这些图标:

<svg>
    <symbol>
        <!-- 第1个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第2个图标路径形状之类代码 -->
    </symbol>
    <symbol>
        <!-- 第3个图标路径形状之类代码 -->
    </symbol>
</svg>

symbol元素用来定义一个图形模板对象,它可以用一个<use>元素实例化。symbol元素对图形的作用是在同一文档中多次使用,添加结构和语义。结构丰富的文档可以更生动地呈现出来,类似讲演稿或盲文,从而提升了可访问性。注意,一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的 <use>元素)才能呈现。

定义以后引用

<svg class="icon" aria-hidden="true">
    <!-- aria-hidden 属性禁止计算机辅助技术朗读图标 -->
    <use xlink:href="#icon-ai-weixin"></use>
</svg>


方案三:使用 CSS 伪元素实现图标

伪元素

伪元素是一个附加至选择器末的关键词,允许你对被选择元素的特定部分修改样式。伪元素主要有: ::first-letter 第一个字母的样式 ::first-line 首行文字的样式 ::before 元素头部添加的修饰 ::after 元素尾部添加的修饰 ::placeholder input的占位符样式 ::selection 被选中元素的样式

我个人觉得伪元素可以解释为元素的修饰,可以为元素带来额外的附加样式,属于额外的文档结构。

伪类

用来表示无法在CSS中轻松或者可靠检测到的某个元素的状态或属性,比如a标签的hover表示鼠标经过的样式,visited表示访问过的链接的样式,更多的用来描述元素状态变化时的样式,伪类主要有: :link :visited :hover :active :focus :lang(fr) :not(s) :root :first-child :last-child :only-child :nth-child(n) :nth-last-child(n) :first-of-type :last-of-type :only-of-type :nth-of-type(n) :nth-last-of-type(n) :empty :checked :enabled :disabled * :target

思路其实就是利用元素的::before伪元素画一个三角形,用css设置span样式为一条线并进行布局定位:

// less
.arrow {
    position: relative;
    display: inline-block;
    line-height: 0;
    background-color: #ccc;
    &.arrow-hor {
        width: 16px;
        height: 1px;
    }
    &.arrow-hor.right::before {
        content: '';
        position: absolute;
        top: -4px;
        right: -8px;
        border: 4px solid transparent;
        border-left: 4px solid #ccc;
    }
}

// html
<span class="arrow arrow-hor right"></span>

这样就实现了一个指向右的箭头,我们用类似的方法也可以实现左箭头,上下箭头,实现双向箭头只需要加一个::after伪类并做适当定位就好了。


总结

现在最流行的是方案一,可生成多平台兼容的图标。

方案二是一种全新的使用方式,是未来的主流,也是平台目前推荐的用法。支持多色图标了,不再受单色限制。

通过一些技巧,支持像字体那样,通过font-size,color来调整样式。兼容性较差,支持 ie9+,及现代浏览器。浏览器渲染svg的性能一般,还不如png。

方案三像街头耍把戏一下,很好看。


参考:

https://www.jianshu.com/p/2acb66b2ed28

https://developer.mozilla.org/zh-CN/docs/Web/CSS/@font-face

https://www.cnblogs.com/jianghaijun4031/p/13231941.html

https://zhuanlan.zhihu.com/p/430423521

https://zhuanlan.zhihu.com/p/86479976

https://www.iconfont.cn/help/detail?helptype=code

修改时间 2021-12-24

声明:本站所有文章和图片,如无特殊说明,均为原创发布。商业转载请联系作者获得授权,非商业转载请注明出处。
随机推荐
JavaScript 和 CSS 检测横屏适配
Node.js MySQL 连接池和事务
JavaScript 数据类型和变量
Node.js url 模块
github Support for password authentication was removed
JavaScript DOM 查找元素
Node.js 实现 RBAC 权限模型
JavaScript Global 对象