整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

初识CSS-字体图标

初识CSS-字体图标

大有学问# #头条创作挑战赛#

什么是字体图标?

在html代码中是以文字元素的形式出现,但在网页渲染时却以图片的形式显示的小图标就叫做字体图标

常见形式:地址、电话、登录窗口的头像等。

字体图标与精灵图对比

字体图标比精灵图更为轻量化,在网页中加载速度更快;

精灵图在实际使用中,图片放大或缩小时图片会失真。

精灵图是一张多个图标整合的一个大图片,后续添加或修改图标不方便。

注:

虽然字体图标好处多多,但是它并不能替代精灵图。

当小图标形式简单且个数较少时适合使用字体图标;

当小图标形式复杂且个数较多时适合使用精灵图。

字体图标哪里来?

icomoon网站:https://icomoon.io/。

阿里iconfont字库:https://www.iconfont.cn/。

字体图标使用方法

以icomoon网站为例。

从网站中下载图标压缩包:点击右上角“IcoMoon App”按钮,进入字体图标选择页面。

icomoon网站首页

选中需要的图标(选中状态的图标,背景颜色会变白且出现黄色边框)后,个数可以选择1个,也可以选择多个。选好图标后,点击右下角“Generate Font ”按钮进入下载页面。

字体图标选择页面

点击右下角“download”按钮进行下载。

icomoon网站图标下载页面

解压下载好的压缩包。


字体图标下载文件解压后的文件夹

将解压好的文件夹整体添加到项目文件夹中,我没有单独设置字体文件夹,直接放在素材图片文件夹了。

项目文件夹目录

打开字体图标文件夹中style.css,

复制字体声明到html文件的style样式中,改变url的图标文件存放位置。

span标签中字体样式需要与字体声明中样式保持一致。

字体图标调用

在html文件中,span标签的内容是需要从网站中直接粘贴复制过来使用。在网站下载页面,鼠标点击就是选中状态,直接ctrl+c复制即可。

字体图标的代码样式调用

如此就是完整的字体图标使用过程。另外有阿里iconfont也可以使用,也是免费的。有兴趣可自行了解。

字体图标代码示例

<style>
  /* 字体声明 :从下载字体图标的文件夹中style.css文件上复制过来的*/
  @font-face {
    font-family: 'icomoon';
    src:  url('../images/icomoon/fonts/icomoon.eot?49yzcu');
    src:  url('../images/icomoon/fonts/icomoon.eot?49yzcu#iefix') format('embedded-opentype'),
          url('../images/icomoon/fonts/icomoon.ttf?49yzcu') format('truetype'),
          url('../images/icomoon/fonts/icomoon.woff?49yzcu') format('woff'),
          url('../images/icomoon/fonts/icomoon.svg?49yzcu#icomoon') format('svg');
    font-weight: normal;
    font-style: normal;
    font-display: block;
  }
  span {
    font-family: 'icomoon';
    font-size: 100px;
    color: antiquewhite;
  }
</style>

span标签的内容就是从字体图标上粘贴下来的

代码运行效果图

好了,今天的学习就到这里了,下回学习CSS三角~

前言

全是干货的技术殿堂

文章收录在我的 GitHub 仓库,欢迎Star/fork: Java-Interview-Tutorial

https://github.com/Wasabi1234/Java-Interview-Tutorial

this 是函数运行时,在函数体内部自动生成的一个对象,只能在函数体内部使用。

教科书般的解释,字都认识,怎么连在一起还是不知道啥意思呢?

1 this的值究竟是什么呢?

函数的不同场合,this有不同值。

总的来说,this就是函数运行时所在的环境对象。

1.1 简单函数调用

函数的最通常用法,属全局性调用,因此this就代表全局对象。

  • 看下面案例

1.2 作为对象方法的调用

函数还可以作为某个对象的方法调用,这时this就指这个上级对象。

记住一条:当function被作为method调用时,this指向调用对象。另外,JavaScript并不是OO的,而是object based的一种语言。

1.3 构造函数

所谓构造函数,就是通过这个函数,可以生成一个新对象。这时,this就指这个新对象。

  • 上面两套代码等效 可以写class test,但本质上new test()的时候,还是test构造函数,差不多,class主要是向java之类的语言抄的,可以直接当java的类用,但本质上test还是个构造函数,因为js一开始就没有class 只能用构造函数,函数test运行时,内部会自动有一个this对象可以使用。

运行结果为1。为了表明这时this不是全局对象,我们对代码做一些改变:

运行结果为2,表明全局变量x的值根本没变。

1.4 apply 调用

apply()是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this指的就是这第一个参数。

apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。

如果把最后一行代码修改为

运行结果就变成了1,证明了这时this代表的是对象obj。

2 深入内存分析

学懂 JavaScript 语言,一个标志就是理解下面两种写法,可能有不一样的结果。

上面代码中,虽然obj.foo和foo指向同一个函数,但是执行结果可能不一样。请看下面的例子。

  • 对于obj.foo()来说,foo运行在obj环境,所以this指向obj
  • 对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。

为什么会这样?函数的运行环境到底是谁决定的?为什么obj.foo()就是在obj环境执行,而一旦var foo=obj.foo,foo()就变成全局环境执行了?

带着灵魂的思考,我们深入解析下

2.1 内存布局

上面的代码将一个对象赋值给变量obj.

  • JS 引擎会先在内存里面,生成一个对象{ foo: 5 },然后把这个对象的内存地址赋值给变量obj。

变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。举例来说,上面例子的foo属性,实际上是以下面的形式保存的。

{
  foo: {
    [[value]]: 5
    [[writable]]: true
    [[enumerable]]: true
    [[configurable]]: true
  }
}

注意,foo属性的值保存在属性描述对象的value属性里面。

3 函数

这样的结构是很清晰的,问题在于属性的值可能是一个函数。

  • 引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性
{
  foo: {
    [[value]]: 函数的地址
    ...
  }
}

由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。

4 环境变量

JavaScript 允许在函数体内部,引用当前环境的其他变量。

上面代码中,函数体里面使用了变量x。该变量由运行环境提供。

现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

上面代码中,函数体里面的this.x就是指当前运行环境的x。

var f=function () {
  console.log(this.x);
}

var x=1;
var obj={
  f: f,
  x: 2,
};

// 单独执行
f() // 1

// obj 环境执行
obj.f() // 2

上面代码中,函数f在全局环境执行,this.x指向全局环境的x。

在obj环境执行,this.x指向obj.x。

回到本文开头提出的问题,obj.foo()是通过obj找到foo,所以就是在obj环境执行。一旦var foo=obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行。

参考

  • Javascript 的 this 用法
  • JavaScript 的 this 原理

用 SVG 符号和 CSS 变量实现多彩图标

使用图片和 CSS 精灵制作 web 图标的日子一去不复返了。随着 web 字体的爆发,图标字体已经成为在你的 web 项目中显示图标的第一解决方案。

字体是矢量,所以你无须担心分辨率的问题。他们和文本一样因为拥有 CSS 属性,那就意味着,你完全可以应用 sizecolorstyle 。你可以添加转换、特效和装饰,比如旋转、下划线或者阴影。

怪不得类似 Font Awesome 这类项目仅仅在 npm 至今已经被下载了超过 1500 万次。

可是图标字体并不完美, 这就是为什么越来越多的人使用行内 SVG 。CSS Tricks 写了图标字体劣于原生 SVG 元素的地方:锐利度、定位或者是因为跨域加载、特定浏览器错误和广告屏蔽器等原因导致的失败。现在你可以规避绝大多数这些问题了,总体上使用图标字体是一个安全的选择。

然而,还是有一件事情对于图标字体来说是绝对不可能的:多色支持。只有 SVG 可以做到。

摘要 :这篇博文深入阐述怎么做和为什么。如果你想理解整个思维过程,推荐阅读。否则你可以直接在 CodePen 看最终代码。

设置 SVG 标志图标

行内 SVG 的问题是,它会非常冗长。你肯定不想每次使用同一个图标的时候,还需要复制/粘贴所有坐标。这将会非常重复,很难阅读,更难维护。

通过 SVG 符号图标,你只需拥有一个 SVG 元素,然后在每个需要的地方引用就好了。

先添加行内 SVG ,隐藏它之后,再用 <symbol> 包裹它,用 id 对其进行识别。

<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path d="..." /> </symbol> </svg>

整个 SVG 标记被一次性包裹并且在 HTML 中被隐藏。

然后,所有你要做的是用一个 <use> 标签将图标实例化。

<svg> <use xlink:href="#my-first-icon" /> </svg>

这将会显示一个初始 SVG 图标的副本。

**就是这样了!**看起来很棒,是吧?

你可能注意到了这个有趣的 xlink:href 属性:这是你的实例与初始 SVG 之间的链接。

需要提到的是 xlink:href 是一个弃用的 SVG 属性。尽管大多数浏览器仍然支持,你应该用 **href** 替代。现在的问题是,一些浏览器比如 Safari 不支持使用 href 进行 SVG 资源引用,因此你仍然需要提供 xlink:href 选项。

安全起见,两个都用吧。

添加一些颜色

不像是字体, color 对于 SVG 图标没有任何作用:你必须使用 fill 属性来定义一个颜色。这意味着他们将不会像图标字体一样继承父文本颜色,但是你仍然可以在 CSS 中定义它们的样式。

// HTML <svg class="icon"> <use xlink:href="#my-first-icon" /> </svg> // CSS .icon { width: 100px; height: 100px; fill: red; }

在这里,你可以使用不同的填充颜色创建同一个图标的不同实例。

// HTML <svg class="icon icon-red"> <use xlink:href="#my-first-icon" /> </svg> <svg class="icon icon-blue"> <use xlink:href="#my-first-icon" /> </svg> // CSS .icon { width: 100px; height: 100px; } .icon-red { fill: red; } .icon-blue { fill: blue; }

这样就可以生效了,但是不完全符合我们的预期。目前为止,我们所有做的事情可以使用一个普通的图标字体来实现。我们想要的是在图标的位置可以有不同的颜色。我们想要向每个路径上填充不同颜色,而不需要改变其他实例,我们想要能够在必要的时候重写它。

首先,你可能会受到依赖于特性的诱惑。

// HTML <svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path class="path1" d="..." /> <path class="path2" d="..." /> <path class="path3" d="..." /> </symbol> </svg> <svg class="icon icon-colors"> <use xlink:href="#my-first-icon" /> </svg> // CSS .icon-colors .path1 { fill: red; } .icon-colors .path2 { fill: green; } .icon-colors .path3 { fill: blue; }

不起作用。

我们尝试设置 .path1.path2.path3 的样式,仿佛他们被嵌套在 .icon-colors 里,但是严格来说,并非如此<use> 标签不是一个会被你的 SVG 定义替代的占位符。这是一个引用将它所指向内容复制为 shadow DOM

**那接下来我们该怎么办?**当子项不在 DOM 中时,我们如何才能用一个区域性的方式影响子项?

CSS 变量拯救世界

在 CSS 中,一些属性从父元素继承给子元素。如果你将一个文本颜色分配给 body ,这一页中所有文本将会继承那个颜色直到被重写。父元素没有意识到子元素,但是可继承的样式仍然继续传播。

在我们之前的例子里,我们继承了填充属性。回头看,你会看到我们声明填充颜色的类被附加在了实例上,而不是定义上。这就是我们能够为同一定义的每个不同实体赋予不同颜色的原因。

现在有个问题:我们想传递不同颜色给原始 SVG 的不同路径,但是只能从一个 fill 属性里继承。

这就需要 CSS 变量了。

就像任何其它属性一样, CSS 变量在规则集里被声明。你可以用任意命名,分配任何有效的 CSS 值。然后,你为它自己或者其它子属性,像一个值一样声明它,并且这将被继承

.parent { --custom-property: red; color: var(--custom-property); }

所有 .parent 的子项都有红色文本。

.parent { --custom-property: red; } .child { color: var(--custom-property); }

所有嵌套在 .parent 标签里的 .child 都有红色文本。

现在,让我们把这个概念应用到 SVG 符号里去。我们将在 SVG 定义的每个部分使用 fill 属性,并且设置成不同的 CSS 变量。然后,我们将给它们分配不同的颜色。

// HTML <svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path fill="var(--color-1)" d="..." /> <path fill="var(--color-2)" d="..." /> <path fill="var(--color-3)" d="..." /> </symbol> </svg> <svg class="icon icon-colors"> <use xlink:href="#my-first-icon" /> </svg> // CSS .icon-colors { --color-1: #c13127; --color-2: #ef5b49; --color-3: #cacaea; }

然后… 生效了 !

现在开始,为了用不同的颜色方案创建实例,我们所需要做的是创建一个新类。

// HTML <svg class="icon icon-colors-alt"> <use xlink:href="#my-first-icon" /> </svg> // CSS .icon-colors-alt { --color-1: brown; --color-2: yellow; --color-3: pink; }

如果你仍然想有单色图标,你不必在每个 CSS 变量中重复同样的颜色。相反,你可以声明一个单一 fill 规则:因为如果 CSS 变量没有被定义,它将会回到你的 fill 声明。

.icon-monochrome { fill: grey; }

你的 fill 声明将会生效,因为初始 SVG 的 fill 属性被未设置的 CSS 变量值定义。

怎样命名我的 CSS 变量?

当提到在 CSS 中命名,通常有两条途径:描述的或者语义的。描述的意思是告诉一个颜色是什么:如果你存储了 #ff0000 你可以叫它 --red 。语义的意思是告诉颜色它将会被如何应用:如果你使用 #ff0000 来给一个咖啡杯把手赋予颜色,你可以叫它 --cup-handle-color

描述的命名也许是你的本能。看起来更干脆,因为#ff0000 除了咖啡杯把手还有更多地方可以被使用。一个 --red CSS 变量可被复用于其他需要变成红色的图标路径。毕竟,这是实用主义在 CSS 中的工作方式。并且是一个良好的系统。

问题是,在我们的案例里,我们不能把零散的类应用于我们想设置样式的标签。实用主义原则不能应用,因为我们对于每个图标有单独的引用,我们不得不通过类的变化来设置样式。

使用语义类命名,例如 --cup-handle-color ,对于这个情况更有用。当你想改变图标一部分的颜色时,你立即知道这是什么以及需要重写什么。无论你分配什么颜色,类命名将会一直关联。

默认还是不要默认,这是个问题

将你的图标的多色版本设置成默认状态是很有诱惑力的选择。这样,你无需设置额外样式,只需要在必要的时候可以添加你自己的类。

有两个方法可以实现::rootvar() default

:root

:root 选择器中你可以定义所有你的 CSS 变量。这将会把它们统一放在一个位置,允许你『分享』相似的颜色。 :root 拥有最低的优先度,因此可以很容易地被重写。

:root { --color-1: red; --color-2: green; --color-3: blue; --color-4: var(--color-1); } .icon-colors-alt { --color-1: brown; --color-2: yellow; --color-3: pink; --color-4: orange; }

然而,这个方法有一个主要缺点。首先,将颜色定义与各自的图标分离可能会有些让人疑惑。当你决定重写他们,你必须在类与 :root 选择器之间来回操作。但是更重要的是,它不允许你去关联你的 CSS 变量,因此让你不能复用同一个名字。

大多数时候,当一个图标只用一种颜色,我用 --fill-color 名称。简单,易懂,对于所有仅需要一种颜色的图标非常有意义。如果我必须在 :root 声明中声明所有变量,我就不会有几个 --fill-color。我将会被迫定义 --fill-color-1--fill-color-2 或者使用类似 --star-fill-color--cup-fill-color 的命名空间。

var() 默认

你可以用 var() 功能来把一个 CSS 变量分配给一个属性,并且它的第二个参数可以设置为某个默认值。

<svg xmlns="http://www.w3.org/2000/svg" style="display: none"> <symbol id="my-first-icon" viewBox="0 0 20 20"> <title>my-first-icon</title> <path fill="var(--color-1, red)" d="..." /> <path fill="var(--color-2, blue)" d="..." /> <path fill="var(--color-3, green)" d="..." /> </symbol> </svg>

在你定义完成 --color-1--color-2--color-3 之前,图标将会使用你为每个 <path> 设置的默认值。这解决了当我们使用 :root 时的全局关联问题,但是请小心:你现在有一个默认值,并且它将会生效。结果是,你再也不能使用单一的 fill 声明来定义单色图标了。你将不得不一个接一个地给每个使用于这个图标的 CSS 变量分配颜色。

设置默认值会很有用,但是这是一个折中方案。我建议你不要形成习惯,只在对给定项目有帮助的时候做这件事情。

How browser-friendly is all that?

CSS 变量与大多数现代浏览器兼容,但是就像你想的那样, Internet Explorer 完全不兼容。因为微软要支持 Edge 终止了 IE11 开发, IE 以后也没有机会赶上时代了。

现在,仅仅是因为一个功能不被某个浏览器(而你必须适配)兼容,这不意味着你必须全盘放弃它。在这种情况下,考虑下优雅降级:给现代浏览器提供多彩图标,给落后浏览器提供备份的填充颜色。

你想要做的是设置一个仅在 CSS 变量不被支持时触发的声明。这可以通过设置备份颜色的 fill 属性实现:如果 CSS 变量不被支持,它甚至不会被纳入考虑。如果它们不能被支持,你的 fill 声明将会生效。

如果你使用 Sass 的话,这个可以被抽象为一个 @mixin

@mixin icon-colors($fallback: black) { fill: $fallback; @content; }

现在,你可以任意定义颜色方案而无需考虑浏览器兼容问题了。

.cup { @include icon-colors() { --cup-color: red; --smoke-color: grey; }; } .cup-alt { @include icon-colors(green) { --cup-color: green; --smoke-color: grey; }; }

在 mixin 中通过 @content 传递 CSS 变量也是一个可选项。如果你在外面做这件事,被编译的 CSS 将会变得一样。但是它有助于被打包在一起:你可以在你编辑器中折叠片段然后用眼睛分辨在一起的声明。

在不同的浏览器中查看这个 pen 。在最新版本的 Firefox , Chrome 和 Safari 中,最后两只杯子各自拥有红色杯身灰色烟气和蓝色杯身灰色烟气。在 IE 和 版本号小于 15 的 Edge 中,第三个杯子的杯身与烟气全部都是红色,第四个则全部是蓝色! ?