【总结】1549- CSS 如何根据背景色自动切换黑白文字?

2023-11-09 17:30

本文主要是介绍【总结】1549- CSS 如何根据背景色自动切换黑白文字?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在项目中,经常会碰到背景色不确定的场景,为了让内容文字足够清晰可见,文字和背景之间需要有足够的对比度。换句话说,当背景是深色时,文字为白色,当背景是浅色时,文字为黑色,就像这样:

9aee9db575bf0acab1339da26c87af76.jpeg
image-20221226102604970

通常这种情况,大家可能会通过 js 去计算背景色的深浅度(灰度),算法是公开的,如果已知颜色的RGB值,那么可以通过以下方式得到颜色灰度

luma = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255

这样可以得到一个0~1之间的范围值,可以根据需求,设定一个阈值,超过表示为浅色,否则为深色。

原理就是这样,这里就不多介绍了。

那么,纯 CSS 也能实现这样的效果吗?当然可以,而且实现更简单,一起看看吧

一、CSS 滤镜实现

实现这个效果需要用到 CSS 滤镜。

假设有 HTML 是这样的

<div class="box"><span class="txt">前端侦探</span>
</div>

因为要使用滤镜对文字单独处理,所以需要额外一层标签。

然后,容器和文字用同一种颜色表示,目的是让文字颜色和背景相关联,可以通过currentColor实现

.box{color: #ffeb3b;background-color: currentColor;
}

接下来可以想一下,如何让彩色文字变成黑白

提到黑白,可以想到灰度滤镜(grayscale),相信大家前几天都用到过,这样可以将彩色的文字转换成灰色

.text{filter: grayscale(1)
}

效果如下

99c5d0f5c234e0f6cb195b41550895b0.jpeg
image-20221224165239122

这样文字颜色由原来的黄绿色变成了浅灰色。

但是,这种灰色在现在这种背景下太难看清了,我们需要的是纯正的黑色或者白色,现在只是灰色,如何“加强”一下呢?

这时,我们可以用到对比度滤镜(contrast),在前面的基础上再叠加一层

.text{filter: grayscale(1) contrast(999)
}

这里的对比度给的比较大,这样就会极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色,效果如下

39233e71f71ec6331da3f11505f2622a.jpeg
image-20221224165207221

这样能还不太明显,我们把背景色换一下

d5762cb338c7ad6bdc7d953bbb1d82cb.jpeg
image-20221224155024179

最后,还差一步,由于前面的操作是将原有颜色经过滤镜转换成了和自身相对应的白色或者黑色,但是是相反的,所以需要用到反转滤镜(invert),颠倒黑白

.text{filter: grayscale(1) contrast(999) invert(1)
}

效果如下

330646509a40ea87e889f56cb71db534.jpeg
image-20221224155446675

下面用一张图来表示转换过程

060c6e71e40814a621b165ae1c9e5e95.jpeg
image-20221224165935410

下面是任意颜色的适配效果,还是挺完美的

760230dea5e7239667af05044d515375.gif

Kapture 2022-12-23 at 14.43.29

代码很简单,就这么一行

.text{filter: grayscale(1) contrast(999) invert(1)
}

完整代码可以查看以下任意链接

  • CSS auto-color (juejin.cn)[1]

  • CSS auto-color (codepen.io)[2]

  • CSS auto-color (runjs.work)[3]

二、CSS 其他思路

除了上面这种方式,还可以通过 CSS 变量来实现,要复杂一些。

这里简单介绍一下实现思路

  1. 将颜色RGB值拆分成 3 个独立的 CSS变量

  2. 通过灰度算法,用 CSS 计算函数算出灰度

  3. 用得到的灰度和阈值做差值,通过hsl模式转换成纯黑和纯白

有兴趣的可以参考张鑫旭老师的这篇文章:CSS前景背景自动配色技术简介[4],可以看到,整体实现和 js 逻辑几乎是一致的,下面是完整实现

另外可以参考之前这篇文章:CSS 变量自动变色技术

:root {/* 定义RGB变量 */--red: 44;--green: 135;--blue: 255;/* 文字颜色变色的临界值,建议0.5~0.6 */--threshold: 0.5;
}.btn {/* 按钮背景色就是基本背景色 */background: rgb(var(--red), var(--green), var(--blue));/** * 使用sRGB Luma方法计算灰度(可以看成亮度)* 算法为:* lightness = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255*/--r: calc(var(--red) * 0.2126);--g: calc(var(--green) * 0.7152);--b: calc(var(--blue) * 0.0722);--sum: calc(var(--r) + var(--g) + var(--b));--lightness: calc(var(--sum) / 255);/* 设置颜色 */color: hsl(0, 0%, calc((var(--lightness) - var(--threshold)) * -999999%));
}

效果如下

05860c277c45fed2fcd36a1c5cf62e5f.gif
auto-color-button.gif (228×225) (zhangxinxu.com)

相比前面的实现而言,实现更加灵活,可以少一层标签。

另外,CSS 正在起草一个颜色对比函数color-contrast,可以从几个颜色中自动选择对比度最高的那个,实现是这样的

.text-contrast-primary {color: color-contrast(var(--theme-primary) vs white, black);
}

不过,现在还没有任何浏览器支持。

413953a8f88365f0c9d5bdbeb35d7aab.jpeg
image-20221224174008923

如果将来支持了,这将是终极解决方案。

三、优缺点总结

总的来说,在color-contrast函数支持之前,我更推荐 CSS 滤镜方式,有以下几点好处

  1. 代码简洁,就一行代码,3 个滤镜

  2. 对颜色格式无任何要求,无需转换成 RGB模式

  3. 无需了解颜色算法,对设计更为友好

当然,也是存在一些缺点

  1. 需要单独一层标签,使用场景可能有限制

  2. 对颜色敏感度较高,不然无从下手

  3. 颜色转换有限制,最终只能是黑白,其他颜色就无能为力了

下面来回顾一下用到的3个滤镜,总结一下

  1. 灰度滤镜(grayscale),可以将彩色的文字转换成灰色

  2. 对比度滤镜(contrast),可以极大的增强对比度,黑的更黑,白的更白,如果是浅灰,那就变成白色,如果是深灰,那就变成黑色

  3. 反转滤镜(invert),可以翻转颜色,颠倒黑白

重新体会颜色转换过程

1a62661c1a6f63feafc8ef5fe5f1e536.jpeg
image-20221224165935410

你记住了吗?最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤

参考资料

[1]

CSS auto-color (juejin.cn): https://code.juejin.cn/pen/7180639403566448698

[2]

CSS auto-color (codepen.io): https://codepen.io/xboxyan/pen/bGjVbGj

[3]

CSS auto-color (runjs.work): https://runjs.work/projects/bb844abe80da401d

[4]

CSS前景背景自动配色技术简介: https://www.zhangxinxu.com/wordpress/2018/11/css-background-color-font-auto-match/

往期回顾

#

如何使用 TypeScript 开发 React 函数式组件?

#

11 个需要避免的 React 错误用法

#

6 个 Vue3 开发必备的 VSCode 插件

#

3 款非常实用的 Node.js 版本管理工具

#

6 个你必须明白 Vue3 的 ref 和 reactive 问题

#

6 个意想不到的 JavaScript 问题

#

试着换个角度理解低代码平台设计的本质

7071fb75e44cfaef2da7eaf38e6cd0f6.gif

这篇关于【总结】1549- CSS 如何根据背景色自动切换黑白文字?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/377555

相关文章

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp