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

翻译 2016年06月02日 09:59:53

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

本文摘自guestAleks HudochenkovAleks 在这里给我们展示了PostCSS在前端开发中,所擅长的领域。
也就是,越少的去写无用的CSS。你即将看到各种与处理图像相关的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。这是处理任何像素密度图像的一种格式。更妙的是,它的语法是文本,这意味着我们可以对其进行编辑,而不再需要用沉重的工具,如图形编辑程序。

这里有内联SVG插件: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会自动更新大小。需要更改颜色?如果您使用另一个插件或预处理器,你甚至可以定义成变量。

<iframe id="cp_embed_NNvGJP" src="//codepen.io/hudochenkov/embed/NNvGJP?height=300&amp;theme-id=1&amp;slug-hash=NNvGJP&amp;default-tab=css%2Cresult&amp;user=hudochenkov&amp;embed-version=2" scrolling="no" frameborder="0" height="300" allowtransparency="true" allowfullscreen="true" name="CodePen Embed" title="CodePen Embed" class="cp_embed_iframe " style="width: 100%; overflow: hidden;"></iframe>

精灵

目前你可能想用那种图片精灵,所有的图片组合在一起成一个较大的图像。首先,众所周知,手机解码内嵌图像比普通图像稍微慢一些。

有很多的工具,可以生成图片精灵。例如: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插件,使我们的电脑为我们做这些事情。它加快了我们的工作,使我们成为更快乐的人。

PostCss简介

官网地址:http://postcss.org/ 源代码地址:https://github.com/postcss 来自官方的文档上写着的是PostCSS是一个JS插件转换样式表的工具。这些插件能...

JavaScript变量的作用域&是否有var 的区别

javascript 块级作用域

原生JS实现最简单的图片懒加载

试一下自己撸一个图片懒加载… Demo地址:http://axuebin.com/lazyload 照片都是自己拍的哦~ 懒加载 什么是懒加载 懒加载其实就是延迟加载,是...

Qt中设置widget背景颜色/图片的注意事项(使用样式表 setStyleSheet())

在Qt中设置widget背景颜色或者图片方法很多种:重写paintEvent() , 调色板QPalette , 样式表setStyleSheet等等。        但是各种方法都有其注意事项...
  • ly7969
  • ly7969
  • 2012年07月05日 18:03
  • 852

Qt中设置widget背景颜色/图片的注意事项(使用样式表 setStyleSheet())

在Qt中设置widget背景颜色或者图片方法很多种:重写paintEvent() , 调色板QPalette , 样式表setStyleSheet等等。        但是各种方法都有其注意事项...

Qt中设置widget背景颜色/图片的注意事项(使用样式表 setStyleSheet())

在Qt中设置widget背景颜色或者图片方法很多种:重写paintEvent() , 调色板QPalette , 样式表setStyleSheet等等。        但是各种方法都有其注意事项...

在css样式表里面引用background-image没有出现图片原因与解决方法

今天写网页的时候遇到一个问题,在样式表里面引用background-image,没有出现效果。然后查了一下是因为相对路径和绝对路径的问题,还有一个是对css样式表的引入的误解,这类文章别的博客已经有的...

不用css样式表和背景图片实现圆角矩形,超简洁!

当网站页面的整体布局设计好后,接下来有很多细节的实现是很让人头疼的。其中之一就是圆角矩形的实现。 在网上看了很多圆角矩形的实现方法,基本有两种,一种是用纯css实现,不需要背景图片;另一种是用背...
  • aerchi
  • aerchi
  • 2012年03月31日 13:13
  • 2569

php 下载其他站点样式表的图片

  • 2015年10月25日 11:05
  • 622KB
  • 下载

样式表CSS的使用

下面给出一个例子是直接编辑内嵌式CSS文本。内嵌一个样式表很直接,只要在标记之间插入一个标记对到文档中即可,这个样式块控制了它所嵌入的整个Web页的外观。IE 3.0及后续版本自动为样式表注册MIME...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何使用 PostCSS 在样式表中处理图片
举报原因:
原因补充:

(最多只允许输入30个字)