原文链接: https://css-tricks.com/images-in-postcss
本文摘自guest
网Aleks Hudochenkov
。Aleks
在这里给我们展示了POSTCSS
在前端开发中,所擅长的领域。
也就是,越少的去用CSS
。你即将看到各种与处理图像的PostCSS插件。最后,我敢肯定你能够想像POSTCSS
在CSS
中的重要性。
我们平时也一直在用CSS
处理图片。但我们甚至可能没有意识到这一点,如果我们能替代手工操作的话,那很多事情就会容易很多 。我将为你展示很多POSTCSS
的插件,尤其是在处理图片上。
本文所介绍的每个插件在任何可以解析PostCSS
语法- CSS
,SCSS
,Less
,以及使用POSTCSS
语法创建的插件中都可以使用。我不会介绍如何使用PostCSS本身,因为已经有一个很好的文章德鲁Minns。
让我们现在开始看案例吧。
图片助手
postcss-assets
插件几乎是用于处理图像的必备插件。它有很多功能。
内联图像
有时候,我们的样式表内将图像做成数据的URL
方式是很有用的。减少了一个HTTP请求!
/* input.css */
div {
background: inline("images/logos/postcss.png");
}
/* output.css */
div {
background: url("data:image/png;base64,iVBORw0KGgoAAAA...ggg==");
}
计算维度
有时你需要元素的大小或根据你所使用的图像的尺寸大小来决定背景尺寸。根据需要,这个插件可以使将尺寸测量并输出。
/* input.css */
body {
width: width("images/foobar.png");
height: height("images/foobar.png");
background-size: size("images/foobar.png");
}
/* output.css */
body {
width: 320px;
height: 240px;
background-size: 320px 240px;
}
如果我们处理的是二倍图,我们可以通过传递第二个参数输出:
/* input.css */
body {
width: width("images/foobar.png", 2);
height: height("images/foobar.png", 2);
background-size: size("images/foobar.png", 2);
}
/* output.css */
body {
width: 160px;
height: 120px;
background-size: 160px 120px;
}
URL解析
该插件可以自动补全文件路径。我们并不需要知道完整路径图像。只要知道文件名就可以了。
例如,我们有这样的文件夹结构:
images/
logos/
postcss.png
input.css
我们传这样的一个参数。**
表示当前路径下所有文件夹和文件进行搜索。
postcss([
require(‘postcss-assets‘)({
loadPaths: [‘**‘]
})
])
/* input.css */
div {
background: resolve("postcss.png");
background: resolve("logos/postcss.png");
}
/* output.css */
div {
background: url("/images/logos/postcss.png");
background: url("/images/logos/postcss.png");
}
缓存无效
这个插件可以使图片缓存失效。
postcss([
require(‘postcss-assets‘)({
cachebuster: true
})
])
/* input.css */
div {
background: url("images/logos/postcss.png");
}
/* output.css */
div {
background: url("images/logos/postcss.png?153bd5d59c8");
}
内联和修改SVGs
几乎每一个图形我最近处理的都是SVG。这是处理任何像素密度图像的一种格式。更妙的是,它的语法是文本,这意味着我们可以对其进行编辑,而不需要用沉重的工具,如图形编辑程序。
这里有内联SVGs插件:postcss-inline-svg.
。你可能会问,为什么我们需要它,postcss-assets
插件已经可以做到这一点了。原因是postcss-inline-svg
有一个杀手锏:它可以修改SVG。
比如说在一个网站里,我们在十个不同的地方使用了不同颜色的星形图标。有很多方法可以做到这一点。我们可以使用一个inline SVG system
<symbol></symbol>
或者 <use>
。又或者,我们可以使用CSS
背景属性!
在CSS中使用图像有两种方式。1)url(/path/to/image.jpg)
传文件路径 2)url(data:...)
数据URL。后者有时也被称为“内联”图像,完成的图像精灵的主要优势之一:结合HTTP请求。有了postcss-inline-svg
,我们可以这样做(让我们的CSS
精灵图像),单独调整颜色:
/* input.css */
.star--red {
background-image: svg-load("img/star.svg", fill=#f00);
}
.star--green {
background-image: svg-load("img/star.svg", fill=#0f0, stroke=#abc);
}
/* output.css */
.star--red {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg fill=‘%23f00‘%3E...%3C/svg%3E");
}
.star--green {
background: url("data:image/svg+xml;charset=utf-8,%3Csvg fill=‘%230f0‘ stroke=‘%23abc‘%3E...%3C/svg%3E");
}
你觉着,这样输出的CSS
文件是太大了?输出CSS将更大,是因为代码重复,但它并没有用Gzip
压缩的事!为了证明,我做了一个测试。我一个CSS文件写了100个不同的选择器,并在每规则集与随机颜色的添加图标内嵌填。像这样:
.wibcsidpuaeqgbxvcjqq {
background: svg-load("images/star.svg", fill: #8c0);
}
我创建了一个副本,删除了??所有内嵌图片的背景。以下是文件大小的对比结果:
– | Original size | Gzipped |
---|---|---|
With 100 images | 48500 bytes | 2560 bytes |
With 1 image | 3158 bytes | 1817 bytes |
区别:2560 – 1817 = 743 bytes
差别不是很大!
这种方法的唯一区别是:没有办法为图片添加动画。例如,如果悬停的时候,颜色有过渡动画,就实现不了。因为transition
不能被应用到background-image
属性上。
这些插件互相恭维
实际案例:我们需要一个按钮是一个图标。按钮内的图像需要一个特定的图像大小,也需要改变悬停颜色。只有一个源SVG文件。
标记:
<button type="button" class="delete">Delete</button>
在没有任何帮助的情况下,我们可能会这样做:
.delete {
box-sizing: content-box;
padding: 15px;
/* Values based on this particular image */
width: 26px;
height: 32px;
border: 1px solid #ef5350;
border-radius: 3px;
background: #fff url("images/trash.svg") 50% 50% no-repeat;
text-indent: -9999px;
}
.delete:hover {
border-color: #c62828;
/* Manually duplicate file and change things */
background-image: url("images/trash-hover.svg");
}
用postcss-assets
自动化后,我们可以这样做:
postcss([ require(‘postcss-inline-svg‘)(), require(‘postcss-assets‘)()]);
.delete {
box-sizing: content-box;
padding: 15px;
width: width("images/trash.svg");
height: height("images/trash.svg");
border: 1px solid #ef5350;
border-radius: 3px;
background: #fff svg-load("images/trash.svg", fill=#ef5350) 50% 50% no-repeat;
text-indent: -9999px;
}
.delete:hover {
border-color: #c62828;
background-image: svg-load("images/trash.svg", fill=#c62828);
}
输出:
.delete {
box-sizing: content-box;
padding: 15px;
width: 26px;
height: 32px;
border: 1px solid #ef5350;
border-radius: 3px;
background: #fff url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns=‘http://www.w3.org/2000/svg‘ width=‘26‘ height=‘32‘ viewBox=‘12 8 26 32‘ fill=‘%23ef5350‘%3E%3Cpath d=‘M20 18h2v16h-2z‘/%3E%3Cpath d=‘M24 18h2v16h-2z‘/%3E%3Cpath d=‘M28 18h2v16h-2z‘/%3E%3Cpath d=‘M12 12h26v2H12z‘/%3E%3Cpath d=‘M30 12h-2v-1c0-.6-.4-1-1-1h-4c-.6 0-1 .4-1 1v1h-2v-1c0-1.7 1.3-3 3-3h4c1.7 0 3 1.3 3 3v1z‘/%3E%3Cpath d=‘M31 40H19c-1.6 0-3-1.3-3.2-2.9l-1.8-24 2-.2 1.8 24c0 .6.6 1.1 1.2 1.1h12c.6 0 1.1-.5 1.2-1.1l1.8-24 2 .2-1.8 24C34 38.7 32.6 40 31 40z‘/%3E%3C/svg%3E") 50% 50% no-repeat;
text-indent: -9999px;
}
.delete:hover {
border-color: #c62828;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns=‘http://www.w3.org/2000/svg‘ width=‘26‘ height=‘32‘ viewBox=‘12 8 26 32‘ fill=‘%23c62828‘%3E%3Cpath d=‘M20 18h2v16h-2z‘/%3E%3Cpath d=‘M24 18h2v16h-2z‘/%3E%3Cpath d=‘M28 18h2v16h-2z‘/%3E%3Cpath d=‘M12 12h26v2H12z‘/%3E%3Cpath d=‘M30 12h-2v-1c0-.6-.4-1-1-1h-4c-.6 0-1 .4-1 1v1h-2v-1c0-1.7 1.3-3 3-3h4c1.7 0 3 1.3 3 3v1z‘/%3E%3Cpath d=‘M31 40H19c-1.6 0-3-1.3-3.2-2.9l-1.8-24 2-.2 1.8 24c0 .6.6 1.1 1.2 1.1h12c.6 0 1.1-.5 1.2-1.1l1.8-24 2 .2-1.8 24C34 38.7 32.6 40 31 40z‘/%3E%3C/svg%3E");
}
如果图像变化,你不需要做任何事情!postcss-assets
会自动更新大小。需要更改颜色?如果您使用另一个插件或预处理器,你甚至可以定义成变量。
精灵
目前你可能想用那种图片精灵,所有的图片组合在一起成一个较大的图像。首先,众所周知,手机解码内嵌图像比普通图像稍微慢一些。
有很多的工具,可以生成图片精灵。例如:grunt-spritesmith
。
这些工具都是很强大的,不是特别容易或方便安装。就像grunt-spritesmith
这个,你需要了解它的模板引擎是如何工作的。
但postcss-sprites就方便的多。这是它的工作原理:
/* input.css */
.comment {
background-image: url("images/sprite/ico-comment.png");
}
.bubble {
background-image: url("images/sprite/ico-bubble.png");
}
/* output.css */
.comment {
background-image: url("images/sprite.png");
background-position: 0 0;
}
.bubble {
background-image: url("images/sprite.png");
background-position: 0 -50px;
}
它查找在CSS中每个图像(可能是过滤),创建一个`Sprite,并输出正确的背景位置到那里。
为高清屏处理图像精灵
尽管postcss-sprites
支持高清屏图片,它并不完全给你处理过程。例如,它不给你媒体查询在高清屏实际使用的那些图像。这个问题可以用另一个PostCSS
插件来解决。这是PostCSS
生态之美 - 有许多插件,每个只做一项工作,你可以结合他们去解决更复杂的问题。
有一个postcss-at2x
插件,它增加了高清屏幕的媒体查询。让我们结合这些插件生成普通屏和高清屏精灵。
postcss([
require(‘postcss-at2x‘)(),
require(‘postcss-sprites‘).default({
retina: true
})
]);
/* input.css */
.circle {
background-image: url("images/circle.png") at-2x;
}
.square {
background-image: url("images/square.png") at-2x;
}
/* output.css */
.circle {
background-image: url("sprite.png");
background-position: 0px 0px;
}
.square {
background-image: url("sprite.png");
background-position: -25px 0px;
}
@media (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx) {
.circle {
background-image: url("[email protected]");
background-position: 0px 0px;
background-size: 50px 25px;
}
}
@media (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi), (min-resolution: 1.5dppx) {
.square {
background-image: url("[email protected]");
background-position: -25px 0px;
background-size: 50px 25px;
}
}
创建动态图片
有时候我们需要非常简单的图像(如几何形状),但仍然发现自己打开一个图形编辑器,创建图像,导入它,把它在正确的地方,对其进行优化,并在CSS
中使用它。那我们能不能在CSS
里创建简单的图片?我敢打赌,你一定会说:我们可以!
postcss-write-svg
可以让你在CSS
里创建简单的SVG
图像。刚刚描述SVG
元素,它会被内联作为background-image
。
/* input.css */
@svg square {
@rect {
fill: var(--color, black);
width: 100%;
height: 100%;
}
@polygon {
fill: green;
points: 50,100 0,0 0,100;
}
}
#example {
background: white svg(square param(--color #00b1ff));
}
/* output.css */
#example {
background: white url("data:image/svg+xml,%3Csvg xmlns=‘http://www.w3.org/2000/svg‘%3E%3Crect fill=‘%2300b1ff‘ width=‘100%25‘ height=‘100%25‘/%3E%3Cpolygon fill=‘green‘ points=‘50%2C100 0%2C0 0%2C100‘/%3E%3C/svg%3E");
}
还有其他的插件,只有CSS属性,实现圆和三角形。你可以用CSS
直接实现三角形
,但它的不全面,当你想要做不同类型的三角形变得更难了。postcss-triangle
允许您轻松地创建等腰三角形,等腰和等边三角形。
/* input.css */
.isosceles-triangle {
triangle: pointing-right;
width: 150px;
height: 115px;
background-color: red;
}
.right-isosceles-triangle {
triangle: right-iso pointing-down;
width: 250px;
background-color: red;
}
.equilateral-triangle {
triangle: equilateral pointing-up;
height: 100px;
background-color: red;
}
/* output.css */
.isosceles-triangle {
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
border-width: 57.5px 0 57.5px 150px;
border-left-color: red;
}
.right-isosceles-triangle {
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
border-width: 125px 125px 0;
border-top-color: red;
}
.equilateral-triangle {
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
border-width: 0 57.73503px 100px;
border-bottom-color: red;
}
圈更容易,postcss-circle
可以节省你的几行代码,并增强可读性。
/* input.css */
.circle {
circle: 100px red;
}
/* output.css */
.circle {
border-radius: 50%;
width: 100px;
height: 100px;
background-color: red;
}
缓存无效
假设你需要更新样式表里的图像链接。我们可能会遇到一个问题,如果我们使用的缓存日期还要很久才到期,用户的浏览器该图像是挂在缓存中的。解决办法是,强迫用户的浏览器去下载的新版本(缓存无效)。有两种方法可以做到这一点:改变文件名或更改URL
。更改文件名有很多要求,但改变URL
参数是容易的。
以下是postcss-urlrev
如何改变URL
/* input.css */
.foo {
background: url("images/test.png") 0 0 no-repeat;
}
/* output.css */
.foo {
background: url("images/test.png?v=e19ac7dee6") 0 0 no-repeat;
}
这个任务还可以用 postcss-cachebuster
and postcss-assets
公用组件
PostCSS
插件可以帮助优化样式表。例如postcss-svgo
可以用 SVGO
优化内联SVG
,最好的SVG
优化工具。
如果您仍然需要支持不支持SVG
的浏览器,postcss-svg-fallback
可以帮助你。这个插件在你的CSS
将SVG
回退PNG
(包括内联,和外联链接URL() ),为旧浏览器增加了额外的规则。
内联图像可能使CSS
臃肿,但有一个解决方案:postcss-data-packer
可以提取 Data URL
到一个单独的文件。然后,您就可以异步加载该文件,以减少网页加载时间。
结论
在没有PostCSS
之前,我们做了很多繁琐的手工工作:复制和粘贴的事情,或者手工计算。现在,我们可以使用一些PostCSS
插件,使我们的电脑为我们做这些事情。它加快了我们的工作,使我们成为更快乐的人。