在图形编辑软件中,可以按特定地方式处理不同图层的合成,最新的CSS规范也引入了该功能,并提供了mix-blend-mode和background-blend-mode两个属性。混合模式(blending mode)是一种数学算法,可计算元素重叠部分的颜色值,目前已定义了十多种不同的混合模式。
## 一、元素混合
  元素混合是指将元素和其背后内容(backdrop,也叫背着物)混合,由mix-blend-mode属性设置混合模式。元素背后既可以是另一个元素,也可以是父元素的背景,并且声明了mix-blend-mode属性的元素被称为前景。注意,不同层叠上下文中的元素不能混合。接下来会对已有的混合模式逐个讲解,并给出相应的计算公式,下面列出的是会用到的符号含义。
  (1)Cr:计算后的颜色值。
  (2)B:进行混合的公式。
  (3)Cs:前景中的颜色。
  (4)Cb:元素背后的颜色(backdrop color)。
**1)darken**
  比较Cb和Cs的颜色分量(即R、G和B),选择较暗的颜色,即保留较小值。
~~~
B(Cb, Cs) = min(Cb, Cs)
~~~
  下面将img元素的mix-blend-mode属性定义为darken,父元素div声明了渐变背景。在下图中,左侧是img和div默认的混合效果,右侧是使用了darken混合后的效果。
~~~html
<style>
div {
background: linear-gradient(to right, rgb(48,129,242) 10%, rgb(255,204,0) 66%, rgb(255,102,0));
}
img {
mix-blend-mode: darken;
}
</style>
<div>
<img src="./avatar.png" />
</div>
~~~
:-: ![](https://img.kancloud.cn/03/be/03bea73de9ad80246dc7b9ceb5a553b8_855x412.png =450x)
**2)lighten**
  与darken类似,但选择较亮的颜色,即保留较大值,效果如下图所示。
~~~
B(Cb, Cs) = max(Cb, Cs)
~~~
:-: ![](https://img.kancloud.cn/02/2d/022d1e7a50ef8fc746b279c83d9507b9_855x412.png =450x)
**3)difference**
  取Cb和Cs颜色分量之差的绝对值,用较浅的颜色减去较深的颜色,效果如下图所示。
~~~
B(Cb, Cs) = | Cb - Cs |
~~~
:-: ![](https://img.kancloud.cn/a2/1c/a21cb3994b75940b302dea4b88ee58e2_855x414.png =450x)
**4)exclusion**
  与difference类似,但对比度更低,颜色更柔和,效果如下图所示。
~~~
B(Cb, Cs) = Cb + Cs - 2 x Cb x Cs
~~~
:-: ![](https://img.kancloud.cn/d2/21/d22149ea7f47ebf30669f2e6eadd4835_855x414.png =450x)
**5)multiply**
 &emsp将Cb和Cs中的颜色分量相乘,得到较暗的颜色,效果如下图所示。
~~~
B(Cb, Cs) = Cb x Cs
~~~
:-: ![](https://img.kancloud.cn/85/47/854766bafb447c1efb39ce944321bc61_855x414.png =450x)
**6)screen**
  将Cb和Cs的颜色反转,然后相乘,最后再反转,效果如下图所示。
~~~
B(Cb, Cs) = 1 - [(1 - Cb) x (1 - Cs)]
~~~
:-: ![](https://img.kancloud.cn/05/cb/05cb89c22839357484ead57a563f1315_855x414.png =450x)
**7)overlay**
  当Cb的颜色比Cs的颜色深时,执行multiply渲染;当Cb的颜色比Cs的颜色浅时,执行screen渲染,效果如下图所示。
~~~
B(Cb, Cs) = HardLight(Cs, Cb)
~~~
:-: ![](https://img.kancloud.cn/f1/21/f1214cc492416959008504761584c6c6_855x414.png =450x)
**8)hard-light**
  也是对multiply和screen的综合应用,但判断条件与overlay相反,效果如下图所示。
~~~
if(Cs <= 0.5)
B(Cb, Cs) = Multiply(Cb, 2 x Cs)
else
B(Cb, Cs) = Screen(Cb, 2 x Cs -1)
~~~
:-: ![](https://img.kancloud.cn/28/1f/281f10134fe874887a99ac74547b9a0c_855x414.png =450x)
**9)soft-light**
  与hard-light类似,但颜色更加柔和,效果如下图所示。
~~~
if(Cs <= 0.5)
B(Cb, Cs) = Cb - (1 - 2 x Cs) x Cb x (1 - Cb)
else
B(Cb, Cs) = Cb + (2 x Cs - 1) x (D(Cb) - Cb)
with
if(Cb <= 0.25)
D(Cb) = ((16 * Cb - 12) x Cb + 4) x Cb
else
D(Cb) = sqrt(Cb)
~~~
:-: ![](https://img.kancloud.cn/26/0b/260b44f37bcae31446ac4a0382d0f72c_855x414.png =450x)
**10)color-dodge**
  不改变颜色,但会将其调亮,效果如下图所示。
~~~
if(Cb == 0)
B(Cb, Cs) = 0
else if(Cs == 1)
B(Cb, Cs) = 1
else
B(Cb, Cs) = min(1, Cb / (1 - Cs))
~~~
:-: ![](https://img.kancloud.cn/e2/c3/e2c3c38348355914702c8cfd734f2a9c_855x414.png =450x)
**11)color-burn**
  与color-dodge的作用相反,将颜色调暗,效果如下图所示。
~~~
if(Cb == 1)
B(Cb, Cs) = 1
else if(Cs == 0)
B(Cb, Cs) = 0
else
B(Cb, Cs) = 1 - min(1, (1 - Cb) / Cs)
~~~
:-: ![](https://img.kancloud.cn/42/21/42214b782458d5fe734a62dfb6bdd1eb_855x414.png =450x)
  接下来的四个混合模式不操作颜色分量,而是以不同的方式合并Cs和Cb的色相、饱和度、亮度和颜色,会用到几个辅助函数,如下所示。
~~~
Lum(C) = 0.3 x Cred + 0.59 x Cgreen + 0.11 x Cblue
ClipColor(C)
L = Lum(C)
n = min(Cred, Cgreen, Cblue)
x = max(Cred, Cgreen, Cblue)
if(n < 0)
C = L + (((C - L) * L) / (L - n))
if(x > 1)
C = L + (((C - L) * (1 - L)) / (x - L))
return C
SetLum(C, l)
d = l - Lum(C)
Cred = Cred + d
Cgreen = Cgreen + d
Cblue = Cblue + d
return ClipColor(C)
Sat(C) = max(Cred, Cgreen, Cblue) - min(Cred, Cgreen, Cblue)
SetSat(C, s)
if(Cmax > Cmin)
Cmid = (((Cmid - Cmin) x s) / (Cmax - Cmin))
Cmax = s
else
Cmid = Cmax = 0
Cmin = 0
return C;
~~~
**12)hue**
  将Cb的颜色的饱和度与亮度跟Cs中对应位置的色相合并,效果如下图所示。
~~~
B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
~~~
:-: ![](https://img.kancloud.cn/20/2a/202a008539b587114865203cb8e811e5_855x414.png =450x)
**13)saturation**
  将Cb的颜色的色相与亮度跟Cs中对应位置的饱和度合并,效果如下图所示。
~~~
B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
~~~
:-: ![](https://img.kancloud.cn/95/96/9596765b615cb2d3766c52439cf3023a_855x414.png =450x)
**14)color**
  将Cb的颜色的亮度跟Cs中对应位置的色相与饱和度合并,效果如下图所示。
~~~
B(Cb, Cs) = SetLum(Cs, Lum(Cb))
~~~
:-: ![](https://img.kancloud.cn/bc/b1/bcb18ce1225fb090d45f49b70bf6fd28_855x414.png =450x)
**15)luminosity**
  将Cb的颜色的色相与饱和度跟Cs中对应位置的亮度合并,效果如下图所示。
~~~
B(Cb, Cs) = SetLum(Cb, Lum(Cs))
~~~
:-: ![](https://img.kancloud.cn/d4/c3/d4c306ebf5846ec7775332a5b9b73684_855x414.png =450x)
## 二、背景混合
  背景混合适合一个元素包含多个背景的情况,由background-blend-mode属性设置混合模式。当混合多个背景时,会从后往前进行混合。如果包含背景色,那么首先由背景色与最下层的背景图混合,其结果再与次下层的背景图混合,以此类推。
  在下面的示例中,包含两个div元素,都使用lighten混合,其中第二个div元素包含背景色。两个元素的混合效果如下图所示,左侧无背景色,右侧有背景色。
~~~html
<style>
div {
background: url(./avatar.png) no-repeat center,
url(./lake.png);
background-size: 40% 40%, cover;
background-blend-mode: lighten;
}
.color {
background-color: #F60;
}
</style>
<div></div>
<div class="color"></div>
~~~
:-: ![](https://img.kancloud.cn/e3/a5/e3a5a89ecae7ff096ca3467736eac000_1050x510.png =600x)
  注意,background-blend-mode属性可接收多种混合模式,用逗号分隔,样式如下,效果如下图所示。
~~~css
div {
background-blend-mode: lighten, hard-light;
}
~~~
:-: ![](https://img.kancloud.cn/8c/40/8c4015e46fb149027800ab4120ddedaf_510x510.png =300x)
## 三、隔离
  在合成的过程中,还可通过isolation属性隔离混合,即让那些元素自成一组。注意,isolation属性需要声明到某个容器元素中,并且不能和混合模式存在于同一个元素上。
  接下来用一个简单的例子来演示isolation属性的用法,首先创建HTML结构,section是img的祖先元素,div是img的父元素。
~~~html
<section>
<div>
<img src="./avatar.png" class="blend" />
</div>
</section>
<section>
<div class="isolation">
<img src="./avatar.png" class="blend" />
</div>
</section>
~~~
  然后添加CSS样式,将混合模式声明在img元素上,第二个div元素定义了isolation属性。得到的效果如下图所示,左侧的祖先元素的背景会与图像混合,而右侧因为发生了隔离,所以就不会与背景混合。
~~~css
section {
background: linear-gradient(to right, #3081F2 10%, #FC0 66%, #F60);
}
.blend {
mix-blend-mode: lighten;
}
.isolation {
isolation: isolate;
}
~~~
:-: ![](https://img.kancloud.cn/2a/a1/2aa1f6689d232891c6db0523c2b4c40c_855x414.png =450x)
  注意,建立层叠上下文的元素可自动独立,而不受isolation属性的影响,能发生层叠上下文的情形包括:
  (1)文档根元素,例如html元素。
  (2)相对或绝对定位且z-index属性值不为auto的元素。
  (3)固定或粘滞定位的元素。
  (4)弹性盒的子元素,且z-index属性值不为auto。
  (5)网格容器的子元素,且z-index属性值不为auto。
  (6)opacity属性值小于1的元素。
  (7)mix-blend-mode属性值不为normal的元素。
  (8)transform、filter、perspective、clip-path、mask、mask-image和mask-border属性值不为none的元素。
  (9)isolation属性值为isolate的元素。
  (10)-webkit-overflow-scrolling属性值为touch的元素。
  (11)contain属性值为layout、paint或包含它们其中之一的合成值(例如strict、content)的元素。
  (12)为will-change定义任一属性。
*****
> 原文出处:
[博客园-CSS躬行记](https://www.cnblogs.com/strick/category/1667864.html)
[知乎专栏-CSS躬行记](https://zhuanlan.zhihu.com/pwcss)
已建立一个微信前端交流群,如要进群,请先加微信号freedom20180706或扫描下面的二维码,请求中需注明“看云加群”,在通过请求后就会把你拉进来。还搜集整理了一套[面试资料](https://github.com/pwstrick/daily),欢迎浏览。
![](https://box.kancloud.cn/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200)
推荐一款前端监控脚本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不仅能监控前端的错误、通信、打印等行为,还能计算各类性能参数,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、扩展运算符和剩余参数
- 3、解构
- 4、模板字面量
- 5、对象字面量的扩展
- 6、Symbol
- 7、代码模块化
- 8、数字
- 9、字符串
- 10、正则表达式
- 11、对象
- 12、数组
- 13、类型化数组
- 14、函数
- 15、箭头函数和尾调用优化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、类
- 21、类的继承
- 22、Promise
- 23、Promise的静态方法和应用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基础实践
- 3、WebRTC视频通话
- 4、Web音视频基础
- CSS进阶
- 1、CSS基础拾遗
- 2、伪类和伪元素
- 3、CSS属性拾遗
- 4、浮动形状
- 5、渐变
- 6、滤镜
- 7、合成
- 8、裁剪和遮罩
- 9、网格布局
- 10、CSS方法论
- 11、管理后台响应式改造
- React
- 1、函数式编程
- 2、JSX
- 3、组件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表单
- 8、样式
- 9、组件通信
- 10、高阶组件
- 11、Redux基础
- 12、Redux中间件
- 13、React Router
- 14、测试框架
- 15、React Hooks
- 16、React源码分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基础
- 4、webpack进阶
- 5、Git
- 6、Fiddler
- 7、自制脚手架
- 8、VSCode插件研发
- 9、WebView中的页面调试方法
- Vue.js
- 1、数据绑定
- 2、指令
- 3、样式和表单
- 4、组件
- 5、组件通信
- 6、内容分发
- 7、渲染函数和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、数据类型
- 2、接口
- 3、类
- 4、泛型
- 5、类型兼容性
- 6、高级类型
- 7、命名空间
- 8、装饰器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系统和网络
- 3、命令行工具
- 4、自建前端监控系统
- 5、定时任务的调试
- 6、自制短链系统
- 7、定时任务的进化史
- 8、通用接口
- 9、微前端实践
- 10、接口日志查询
- 11、E2E测试
- 12、BFF
- 13、MySQL归档
- 14、压力测试
- 15、活动规则引擎
- 16、活动配置化
- 17、UmiJS版本升级
- 18、半吊子的可视化搭建系统
- 19、KOA源码分析(上)
- 20、KOA源码分析(下)
- 21、花10分钟入门Node.js
- 22、Node环境升级日志
- 23、Worker threads
- 24、低代码
- 25、Web自动化测试
- 26、接口拦截和页面回放实验
- 27、接口管理
- 28、Cypress自动化测试实践
- 29、基于Electron的开播助手
- Node.js精进
- 1、模块化
- 2、异步编程
- 3、流
- 4、事件触发器
- 5、HTTP
- 6、文件
- 7、日志
- 8、错误处理
- 9、性能监控(上)
- 10、性能监控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 监控系统
- 1、SDK
- 2、存储和分析
- 3、性能监控
- 4、内存泄漏
- 5、小程序
- 6、较长的白屏时间
- 7、页面奔溃
- 8、shin-monitor源码分析
- 前端性能精进
- 1、优化方法论之测量
- 2、优化方法论之分析
- 3、浏览器之图像
- 4、浏览器之呈现
- 5、浏览器之JavaScript
- 6、网络
- 7、构建
- 前端体验优化
- 1、概述
- 2、基建
- 3、后端
- 4、数据
- 5、后台
- Web优化
- 1、CSS优化
- 2、JavaScript优化
- 3、图像和网络
- 4、用户体验和工具
- 5、网站优化
- 6、优化闭环实践
- 数据结构与算法
- 1、链表
- 2、栈、队列、散列表和位运算
- 3、二叉树
- 4、二分查找
- 5、回溯算法
- 6、贪心算法
- 7、分治算法
- 8、动态规划
- 程序员之路
- 大学
- 2011年
- 2012年
- 2013年
- 2014年
- 项目反思
- 前端基础学习分享
- 2015年
- 再一次项目反思
- 然并卵
- PC网站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端学习之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 日志
- 2020