使用CSS一步一步的将照片变成旧照片。
本文将回顾如何仅使用 CSS 在任何图片上创建旧照片效果。无需 Photoshop 或任何其他图像编辑器。只需几行代码!
我们将检查三种相互叠加的不同方法,每次迭代都会增加旧照片效果,使其看起来更逼真、更好看。
对于此页面上的示例,我们将使用 Filipp Romanovski 的照片。您可以在 Unsplash 上找到它,以及许多其他令人惊叹的图片(由 Filipp 和更多作者提供。)
一、使用图片标签创建旧照片效果的最基本方法是直接对 <img /> 标签中的图像应用滤镜。这种方法很快,效果会很好,但结果可能太基础了。
让我们从 HTML 中的图像开始:
<img src="link-to-your-image.jpg" alt="Description of the image" />
然后我们将在 CSS 中应用一些 filters 和一个简单的 mask:
img {
filter: grayscale(1) blur(1px) contrast(1.2) sepia(1);
-webkit-mask: radial-gradient(#000, #0009);
}
让我们一一看看每个过 filters 滤镜的作用:
grayscale(1):将图片变成灰度级。这会将一些区域混合成类似的灰色调,使图片失去一些细节。
blur(1px):对图像应用高斯模糊。足以组合颜色区域并使图片失去更多细节。
contrast(1.2):锐化图片。我们可以稍微调整一下值,将其调整为我们想要的,并为每张图片对其进行个性化设置。但要注意:太高或太低,看起来会很奇怪。
sepia(1):将颜色更改为旧照片的棕褐色。
此外,我们可以添加一个额外的 blur(0.5px)(它不必是整数或大于 1)来使照片稍微模糊一点并完成滤镜效果。但这不是必需的。
最后一行添加了-webkit-mask 。旧照片看起来更集中在中心,但随后它们会退化,失去颜色并且边缘变得有点模糊。我们可以通过在 CSS 中应用遮罩来实现。不幸的是,并非所有浏览器都支持遮罩……对我们来说幸运的是,供应商前缀是!所以我们可以使用 -webkit-mask 应用相同的效果。
使用 -webkit-mask: radial-gradient(#000, #0009),我们告诉浏览器使图像的边缘半透明(通过在中心使用一个完全可见的椭圆,向外渐变),所以图片会褪色并与背景融为一体。请注意,这可能会根据背景颜色产生不同的结果!
应用这四行CSS后,我们就实现了老照片的效果。这是原始图片与结果图片的比较:
不错,但我们可以更进一步。
二、使用伪元素使用单个 <img /> 标签的一个问题是图像没有像 ::before 或 ::after 这样的伪元素,这限制了我们可以应用到元素的效果。如果我们不使用 <img /> 而使用 <div> 并将图像添加为背景,我们可以将滤镜和遮罩应用于其伪元素并获得更准确的效果。
获得与 <img /> 标签类似的结果会很简单。 HTML 看起来像这样:
<div class="old-style-photo demo-image"></div>
然后,在 CSS 中,我们将使用该元素来显示旧式照片,就像之前的部分一样。唯一的区别是我们还需要设置大小和图像作为背景:
/* specific to the demo image */
.demo-image {
width: 45vw;
aspect-ratio: 3/4;
background: url(link-to-image.jpg);
background-size: cover;
}
/* needed for the pseudo-elements and old-photo effect */
.old-style-photo {
position: relative;
filter: grayscale(1) blur(1px) contrast(1.2) sepia(1) blur(0.25px);
-webkit-mask: radial-gradient(#000, #000a);
}
就这样,我们得到了与上一节相同的效果。我们将使用 ::before 伪元素来模糊图像的边缘。旧照片中常见的东西。为此,我们将再次使用遮罩。另一个从中心到边缘的径向渐变,但这次将是相反的方向:在中心隐藏,在末端可见。这样,我们就可以对图像本身应用背景滤镜效果。
使用 backdrop-filter,我们可以对元素后面的区域应用过滤器。因为中心是用蒙版裁剪的,所以滤镜不会应用于图像的中心,只会根据蒙版应用于可见区域和可见度。例如,如果我们应用 blur() 背景滤镜,则完全可见的边缘会比仅部分可见的中间部分更加模糊。
.old-style-photo::before {
content: "";
position: absolute;
width: 100%;
height: 100%;
-webkit-mask: radial-gradient(farthest-side, #0000 30%, #000);
backdrop-filter: blur(5px) sepia(90%);
}
生成的图像边缘更模糊,而且我们在混合中添加了更多棕褐色(因此颜色组合得更多):
三、进一步添加混合内联 SVG有些人会大声说到,说这“不是纯 CSS 解决方案”(我从来没有声称它是),并认为这部分是作弊。相反,我们将其称为“利用 CSS 必须提供的所有功能”。
是的,它是真实的。最后一步将包括一些 SVG。事实上,CSS 有过滤器,但它们不像 SVG 的那样多样化或先进。对我们来说幸运的是,我们可以以一种相对直接的方式结合这两种技术。
一种选择是在 HTML 中使用一些内联 SVG 并从我们的 CSS 中引用它。我们将使用的另一个选项是直接在 CSS 中内联 SVG(不在 HTML 端添加任何内容)。这可以通过使用 url() 函数和数据 URI 将 SVG 添加为背景来实现:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
在我们的例子中,我们甚至不需要进行 base64 编码。这是一个简单的 SVG,我们可以将它作为文本放在数据 URI 中:
<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
<filter id='noise' x='0%' y='0%' width='100%' height='100%'>
<feTurbulence baseFrequency='0.5' />
</filter>
<rect x='0' y='0' width='100%' height='100%' filter='url(#noise)' />
</svg>
我们唯一需要注意的是滤镜中的#。它需要进行 URL 编码并替换为 #。然后我们将该属性应用于 ::after 伪元素:
.old-style-photo::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
opacity: 0.6;
background:
url("data:image/svg xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'><filter id='noise' x='0%' y='0%' width='100%' height='100%'><feTurbulence baseFrequency='0.5' /></filter><rect x='0' y='0' width='100%' height='100%' filter='url(#noise)' /></svg>"), #f003;
filter: grayscale(100%) contrast(150%);
mix-blend-mode: darken;
}
noise 本身有不同的颜色,但现在它是单色的,因为我们对父元素应用了一些滤镜,这也会影响伪元素。尽管如此,我们仍然可以应用额外的滤镜(不是必需的)和混合模式以更好地与原始图片混合。我强烈建议使用不同的 mix-blend-mode 值:darken 和 multiply 产生我们想要的效果的很好的结果。
结果与之前的图像相同,但我们有一个颗粒/噪点,为旧照片图像增加了更多的真实感: