使用CSS一步一将照片变成旧照片。
本文将回顾如何仅使用 CSS3 在任何图片上创建旧照片效果。无需 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 编码并替换为 %23。然后我们将该属性应用于 ::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(%23noise)' /></svg>"), #f003; filter: grayscale(100%) contrast(150%); mix-blend-mode: darken; }
noise 本身有不同的颜色,但现在它是单色的,因为我们对父元素应用了一些滤镜,这也会影响伪元素。尽管如此,我们仍然可以应用额外的滤镜(不是必需的)和混合模式以更好地与原始图片混合。我强烈建议使用不同的 mix-blend-mode 值:darken 和 multiply 产生我们想要的效果的很好的结果。
结果与之前的图像相同,但我们有一个颗粒/噪点,为旧照片图像增加了更多的真实感:
总结
在本文中,我们了解了如何在不借助外部文件的情况下仅使用 CSS(和一个小型内联 SVG)逐步创建旧照片效果。
更改过滤镜和遮罩中的值将生成完全不同的图像。请随意下载代码并在本地运行或在 CodePen 上查看本示例。
https://codepen.io/alvaromontoro/pen/QWxXaKb
最终的代码:
HTML部分:
<div></div> <div class="old-style"></div>
CSS部分:
div { display: inline-block; width: 45vw; aspect-ratio: 3/4; background: url(https://assets.codepen.io/1506195/portrait-woman-unsplash.jpg); background-position: top center; background-size: cover; } .old-style { position: relative; filter: grayscale(1) blur(1px) contrast(1.2) sepia(1) blur(0.25px); -webkit-mask: radial-gradient(#000, #000a); } .old-style::before { content: ""; position: absolute; width: 100%; height: 100%; -webkit-mask: radial-gradient(farthest-side, #0000 30%, #000); backdrop-filter: blur(5px) sepia(90%); } .old-style::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(%23noise)' /></svg>"), #f003; filter: grayscale(100%) contrast(150%); mix-blend-mode: darken; }
更多例子
为了表明这种效果在一般情况下确实有效,而不仅仅是演示图像所特有的东西,我将它应用到更多图片:
我们可以改变径向渐变的中心来关注我们认为更重要的区域。例如,渐变的中心更靠近这张照片中的脸部:
我喜欢用人的照片来达到效果,但没有人也行。如果照片的主题是旧物件,则效果尤其好:
原文: https://medium.com/gitconnected/old-photo-effect-with-css-54f5be9912b,作者:Alvaro Montoro,翻译:CSDN博主「前端达人」