纯 CSS 实现文字智能适配背景效果
动态的文字有长有短,但是需要智能适配背景的颜色变成其对比色。
还记得 2017 年,我们响应朋友的邀约从高德离职出来创业的时候,遇到了一个相对来说有点特殊的需求,动态的文字有长有短,但是需要智能适配背景的颜色变成其对比色。大概效果如下:
仔细看会发现,哪怕半个文字存在于两个不同的背景色之间,这个文字也会被分割成两个颜色。
看到这样的需求,大多数人第一时间想到的是,文字元素有两个,是完全重叠的两层,一层是黑色,一层是白色,然后通过遮罩实现。没错,这样的确可以实现这样的效果,但是也会让 DOM 结构过于复杂。
于是,今天我就带领大家只用一个文字元素,使用混合模式实现这样的效果。那么我们就开始吧!
一、构建背景容器
我们就用一个 div 元素实现黑色边框,一半黑色一半白色,分割线还是倾斜的背景容器。
<div><div>
DOM 结构尽可能的简约,所以就直接这样放一个 div 即可。核心是需要使用 CSS 控制其显示样式。
先不想那么多,我们先给容器一个大小和黑色边框,并设置背景颜色为白色。
div {
height: 500px;
border: 5px solid #000;
background: #fff;
}
很明显,现在只有一个框。
这个时候,我们需要让背景有一半为黑色,并且黑色部分构成一个直角梯形。自然会想到使用该元素的 before 或者 after 两个伪元素来实现。
既然要使用伪元素,大概率涉及到了伪元素的定位,那么我们先给 div 元素一个相对定位。
div {
position: relative;
height: 500px;
border: 5px solid #000;
background: #fff;
}
小小知识点:
position 属性是控制元素定位的,默认值为 static。
若一个元素的 position 属性值为绝对定位(absolute),即可通过 top、bottom 两个属性控制该元素的竖直偏移,也可以通过 right、left 两个属性控制该元素的水平偏移。
若没有设置 top、bottom 两个属性,则竖直方向的偏移和 position 的值为 static 显示的一样;若没有设置 right、left 两个属性,则水平方向的偏移和 position 的值为 static 显示的一样。
无论水平方向还是竖直方向,只要设置了偏移属性,那么就需要看该元素的父元素的 position 是什么值。若父元素的 position 不是 static,那么就会以该父元素的容器范围为基准开始偏移;若父元素的 position 是 static,那么就会无视该父元素的管理范围,继续向上寻找“爷爷”元素,直到找到 position 不是 static 的元素,或者直接以 body 元素为基准。
我曾经在《【欧洲杯】用纯前端写一个滚动的足球(上)》这篇文章中讲解过如何使用伪元素写正五边形。现在我们需要使用 before 和 after 两个伪元素组成一个直角梯形,最简单的方式就是使用 before 写成一个矩形,然后使用 after 写成一个直角三角形,然后拼接在一起。
按照这样的思路,我们直接用 CSS 把这个直角梯形写出来:
div::before,
div::after {
position: absolute;
top: 0;
bottom: 0;
display: block;
content: "";
}
div::before {
left: 0;
width: 40%;
background: #000;
}
div::after {
left: 40%;
width: 0;
height: 0;
border-top: 250px solid transparent;
border-right: 100px solid transparent;
border-bottom: 250px solid #000;
border-left: 100px solid #000;
}
按照这样的结构设计:
我们得到如下结果:
这就是我们想要的背景容器。
二、放入文字
一般来说,直接在 div 中写入文字即可。考虑到对鼠标悬停存在动画效果,我们就在 div 中放一个 h1 标签。
<div>
<h1>实现文字智能适配背景</h1>
</div>
通过 CSS 控制文字的位置和大小:
h1 {
position: absolute;
left: 40%;
z-index: 1;
font-size: 9rem;
}
设置了 z-index 属性,让其显示在 div 元素的伪元素的上方。
默认情况下,文字的颜色是黑色的:
设置文字颜色为白色:
h1 {
position: absolute;
left: 40%;
z-index: 1;
font-size: 9rem;
color: #fff;
}
显示效果如下:
为了看的更加清楚,我们给文字增加一个动画,让鼠标进入的时候,文字向左滑动,反之回到原位。
h1 {
position: absolute;
left: 40%;
z-index: 1;
font-size: 9rem;
color: #fff;
transition: 0.5s;
}
div:hover > h1 {
transform: translateX(-60%);
}
可以看到这样的效果:
这样,我们已经把文字插入到元素中了。但是,文字在白色部分是看不出来的,怎么办呢?掌声有请我们今天的主角的——混合模式!
三、混合模式
需要让文字智能适配背景的颜色,在黑色部分显示白色,在白色部分显示黑色,我们需要用到混合模式。
想要把混合模式完全搞懂,需要对颜色及其三要素有一定的了解。这里完全可以单独开一门课程进行讲解,今天涉及到了,就只能给大家做一个简单的介绍。
- 色调,是色彩的首要特征,是区别各种不同色彩的最准确的标准,即各类色彩的相貌称谓。
饱和度,又叫纯度,是指色彩的鲜艳程度。
明度,也叫亮度,是眼睛对光源和物体表面的明暗程度的感觉,主要是由光线强弱决定的一种视觉经验。
相信大多数人第一次接触混合模式,是在 Photoshop 中。
在 CSS 中,混合模式是用于控制 HTML 的元素间的颜色混合模式。它允许某个 HTML 元素的内容与其背后的背景或其他 HTML 元素内容以特定的方式相互作用,从而实现相对复杂的叠加效果,从而提升页面的视觉层次与艺术感。
在 CSS 中,主要是 background-blend-mode 属性和 mix-blend-mode 两个属性来实现元素的混合模式。
-
background-blend-mode - 指定 HTML 元素的背景层(包括背景颜色、背景图片等)之间的混合模式。
-
mix-blend-mode - 指定一个 HTML 元素的内容(包括文字、内嵌图像等)与其下方 HTML 元素的混合模式。
标准混合模式有如下 16 个:
-
Normal(默认):
不进行特殊混合,上层的 HTML 元素直接盖住下层的 HTML 元素;
这是默认的混合模式,相当于没有混合。
-
Multiply(正片叠底):
将上层 HTML 元素中的颜色与下层 HTML 元素的颜色的每一个分量进行相乘,一般情况下,计算后的结果颜色比原本的颜色更暗;
对于上层 HTML 元素中的颜色是纯黑色或纯白色的,混合后的结果将分别保持下层 HTML 元素的颜色不变或变为纯黑色。
-
Screen(滤色):
类似于两层幻灯片重叠的效果,上层 HTML 元素的颜色与下层 HTML 元素的颜色的互补色相乘,然后取反;
一般情况下,计算后的结果颜色比原本的颜色更亮;
对于上层 HTML 元素中的颜色是纯黑色或纯白色的,混合后会使下层 HTML 元素的颜色不变或变为纯白色。
-
Overlay(叠加):
结合了 Multiply 和 Screen 模式的特点;
对于下层 HTML 元素的颜色较暗的区域,使用 Multiply 模式;
对于下层 HTML 元素的颜色较亮的区域,使用 Screen 模式;
这种模式可以增强对比度。
-
Darken(变暗):
对于每个像素位置,取上层 HTML 元素的颜色与下层 HTML 元素的颜色中较暗的那个颜色作为结果颜色;
该模式倾向于保留两个层叠的 HTML 元素中最深的色彩。
-
Lighten(变亮):
类似于 Darken,只不过取的是两层 HTML 元素的颜色中较亮的那个颜色作为结果颜色;
该模式倾向于保留两个层叠的 HTML 元素中最浅的色彩。
-
Color-Dodge(颜色减淡):
上层 HTML 元素的颜色根据下层 HTML 元素的颜色信息中的亮度调整自身亮度,使得结果颜色变亮;
当下层 HTML 元素的颜色较暗时,影响较小;
当下层 HTML 元素的颜色接近白色时,上层 HTML 元素的颜色会明显变亮甚至完全变为白色。
-
Color-Burn(颜色加深):
与 Color-Dodge 反过来,上层 HTML 元素的颜色根据下层 HTML 元素的颜色信息中的亮度调整自身亮度,使得结果颜色变暗;
当下层 HTML 元素的颜色较亮时,影响较小;
当下层 HTML 元素的颜色接近黑色时,上层 HTML 元素的颜色会明显变暗甚至完全变为黑色。
-
Hard-Light(强光):
类似于 Overlay,但作用于下层 HTML 元素的颜色;
上层 HTML 元素的颜色类似于一个光源,对下层 HTML 元素的颜色施加明暗影响;
若上层 HTML 元素的颜色为纯黑色或纯白色,则会使下层 HTML 元素的颜色变暗或变亮。
-
Soft-Light(柔光):
与 Hard-Light 相似,但效果更为柔和;
上层 HTML 元素的颜色对下层 HTML 元素的颜色的明暗影响较小,产生类似半透明材料覆盖的效果。
-
Difference(差值):
计算上层 HTML 元素的颜色与下层 HTML 元素的颜色之间的色差,结果为两者之间的对比色;
当两层颜色相同时,结果为黑色;
当两层颜色互补时,结果为白色。
-
Exclusion(排除):
与 Difference 类似,但产生的对比度较低;
结果颜色比 Difference 模式更柔和,且不会出现纯黑色或纯白色。
-
Hue(色相):
取上层 HTML 元素的颜色信息中的色相与下层 HTML 元素的颜色信息中的饱和度和亮度,生成新的颜色;
下层 HTML 元素的颜色信息中的色调被上层 HTML 元素的颜色信息中的色调替换,但饱和度和亮度保持不变。
-
Saturation(饱和度):
取下层 HTML 元素的颜色信息中的色相与亮度,以及上层 HTML 元素的颜色信息中的饱和度,生成新的颜色;
下层 HTML 元素的颜色信息中的饱和度被上层 HTML 元素的颜色信息中的饱和度替换,其他属性保持不变。
-
Color(颜色):
取上层 HTML 元素的颜色信息中的色相与饱和度,以及下层 HTML 元素的颜色信息中的亮度,生成新的颜色;
下层 HTML 元素的颜色信息中的色调和饱和度被上层 HTML 元素的颜色信息中的色调和饱和度替换,亮度保持不变。
-
Luminosity(亮度/明度):
取上层 HTML 元素的颜色信息中的亮度,与下层 HTML 元素的颜色信息中的色相和饱和度结合,生成新的颜色;
下层 HTML 元素的颜色信息中的亮度被上层 HTML 元素的颜色信息中的亮度替换,色调和饱和度保持不变。
除了标准混合模式,还有分离混合模式和 CSS Paint API 混合模式,这里也做一个简单的介绍:
- 分离混合模式 - 在 normal、multiply、screen、darken、lighten、color-dodge、color-burn、hard-light、soft-light、difference、exclusion 这 11 种标准混合模式中还可以加上前缀 difference,形成如 difference-normal 等分离混合模式,用于独立控制 RGB 通道和 alpha 通道的混合。
分离混合模式由于其计算的简单性和效率,在某些情况下可能更适合性能敏感的应用场景。
-
CSS Paint API混合模式 - 一种允许开发者使用 JavaScript 编写自定义绘制逻辑来生成 CSS 背景、边框、内容等图像的现代 Web 技术。
CSS Paint API 混合模式需要在支持 CSS Paint API 的浏览器中才能使用,是一种特殊的混合模式,如 plus-darker、plus-lighter 等;
配合 mix-blend-mode 属性,CSS Paint API 可以实现更加动态、灵活且复杂的颜色混合效果。
混合模式及其色彩方面的知识还有很多,这里就不做过多的展开了。
咱们根据目前的知识,结合咱们的案例,感觉最适合的是 Difference 模式。于是我们在控制文字的 CSS 中添加这个混合模式:
h1 {
position: absolute;
left: 40%;
z-index: 1;
font-size: 9rem;
color: #fff;
transition: 0.5s;
mix-blend-mode: difference;
}
这样,我们就得到了需要的效果:
完整源码
最后,我们还是把完整的源代码贡献给大家吧!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
border: none;
font-size: 62.5%;
}
div {
position: relative;
height: 500px;
border: 5px solid #000;
background: #fff;
line-height: 500px;
cursor: pointer;
}
div::before,
div::after {
position: absolute;
top: 0;
bottom: 0;
display: block;
content: "";
}
div::before {
left: 0;
width: 40%;
background: #000;
}
div::after {
left: 40%;
width: 0;
height: 0;
border-top: 250px solid transparent;
border-right: 100px solid transparent;
border-bottom: 250px solid #000;
border-left: 100px solid #000;
}
h1 {
position: absolute;
left: 40%;
z-index: 1;
font-size: 9rem;
color: #fff;
transition: 0.5s;
mix-blend-mode: difference;
}
div:hover > h1 {
transform: translateX(-60%);
}
</style>
</head>
<body>
<div>
<h1>实现文字智能适配背景</h1>
</div>
</body>
</html>
↓
↓
↓
若大家对混合模式或者色彩方面的知识感兴趣的,欢迎大家留言,我会在将来做成视频或者更加详细的文章进行讲解。让我们拭目以待吧!
关注我,为您送上更多精彩内容!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)