频道栏目
首页 > 资讯 > HTML/CSS > 正文

如何使用 `PostCSS` 在样式表中处理图片

16-06-04        来源:[db:作者]  
收藏   我要投稿

原文链接: https://css-tricks.com/images-in-postcss

你即将看到各种与处理图像的PostCSS插件。最后,我敢肯定你能够想像POSTCSSCSS中的重要性。

我们平时也一直在用CSS处理图片。但我们甚至可能没有意识到这一点,如果我们能替代手工操作的话,那很多事情就会容易很多 。我将为你展示很多POSTCSS的插件,尤其是在处理图片上。

本文所介绍的每个插件在任何可以解析PostCSS语法- CSSSCSSLess ,以及使用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 或者 。又或者,我们可以使用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文件。

标记:

在没有任何帮助的情况下,我们可能会这样做:

.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("sprite.@2x.png");
    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("sprite.@2x.png");
    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可以帮助你。这个插件在你的CSSSVG回退PNG(包括内联,和外联链接URL() ),为旧浏览器增加了额外的规则。

内联图像可能使CSS臃肿,但有一个解决方案:postcss-data-packer可以提取 Data URL到一个单独的文件。然后,您就可以异步加载该文件,以减少网页加载时间。

结论

在没有PostCSS之前,我们做了很多繁琐的手工工作:复制和粘贴的事情,或者手工计算。现在,我们可以使用一些PostCSS插件,使我们的电脑为我们做这些事情。它加快了我们的工作,使我们成为更快乐的人。

相关TAG标签
上一篇:JavaScript学习--Item35 事件流与事件处理
下一篇:JAVA解析XML文件
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站