【CSS Tricks】在css中尝试一种新的颜色模型HSL

server/2024/9/23 18:26:08/

目录

  • 引言
  • 浏览器支持性
  • HSL介绍
  • HSL相较于RGB的优势在哪?
  • HSL在网页设计的应用场景
  • 如何用代码转换hsl
    • RGB转HSL
    • HSL转RGB
    • HEX格式的互转
  • 总结

引言

本篇不会对rgb颜色模型或是hsl颜色模型的显色原理进行深入的探究,仅从前端开发角度去论述在工作中选择哪种比较合适。

  • 大多数电视机、显示器、投影仪通过将不同强度的红、绿、蓝色光混合来生成不同的颜色,这就是RGB三原色的加色法。通过这种方法可以在RGB色彩空间生成大量不同的颜色,然而,这三种颜色分量的取值与所生成的颜色之间的联系并不直观。
  • 艺术家有时偏好使用HSL或HSV而不选择三原色光模式(即RGB模型)或 印刷四分色模式(即CMYK模型),因为它类似于人类感觉颜色的方式,具有较强的感知度。HSL以人类更熟悉的方式封装了关于颜色的信息:“这是什么颜色?深浅如何?明暗如何?”。

浏览器支持性

  • 在Can i use?网站上查询到hsl的支持性结果为:
    caniuse
    目前为止主流的浏览器均支持hsl颜色,所以可以放心使用。

HSL介绍

HLS 有三个分量,hue(色相)、saturation(饱和度)、lightness(亮度)。
在这里插入图片描述

  • hue代表色相(色相环角度),色相的定义中,许多的颜色分布在一个圆环上,取值范围则是 0-360度,每个角度代表着一种颜色。以六大主色为基础,他们分别按 60 度的间隔排列在圆环上。这六大主色分别是:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红。
    在这里插入图片描述

  • saturation代表饱和度。饱和度是指颜色的强度或纯度,使用 0 ~ 100% 的百分比来度量。表示色相中颜色成分所占的比例,数值越大,颜色中的灰色越少,颜色越鲜艳,呈现的是一种从灰色到色相颜色的变化。
    在这里插入图片描述

  • lightness代表亮度,表现颜色的明暗程度,使用 0 ~ 100% 的百分比来度量。反映色彩中混入的黑白两色,50% 处只有纯色,小于 50% 时,数值越小混入的黑色越多,越接近于黑色;大于 50% 时,数值越大混入的白色越多,越接近于白色。
    在这里插入图片描述

  • 一般在css中写法为:hsl( 255, 90%, 50% ) 或是带透明度 hsal( 255, 90%, 50%, 0.5 )。

HSL相较于RGB的优势在哪?

  • 感知相关性:RGB模型中的颜色分量并不直接对应人类对颜色的感知。在RGB中改变一个颜色的单个分量(红、绿或蓝),通常不会产生直观的颜色变化。相比之下,HSL模型的设计更接近人类对颜色的认知,其中色相(Hue)代表颜色的基本色调,饱和度(Saturation)代表颜色的纯度,亮度(Lightness)代表颜色的明暗程度。因此,在需要根据感知调整颜色时,HSL往往更为直观。
  • 颜色混合:当需要混合颜色以获得新的颜色时,使用RGB模型可能不容易预测结果。而在HSL模型中,可以通过较为简单的方式调整颜色的各个方面,如改变色相来得到类似的颜色变化,调整饱和度来控制颜色的鲜艳度等。
  • 计算复杂性:虽然RGB模型直接对应于硬件上的颜色生成,但在需要进行复杂的颜色运算时,如颜色渐变、颜色过滤或者颜色对比度调整等,HSL模型可能提供更加简便的方法。
  • 易于编程和算法实现:对于某些图形处理算法来说,使用HSL模型可以使某些任务变得更简单,比如色彩校正、图像分割和颜色过滤等。

HSL在网页设计的应用场景

  1. 颜色主题生成:使用HSL可以方便地生成一系列颜色,这些颜色共享相同的色相或亮度,但有不同的饱和度,从而创建出和谐的颜色主题。
  2. 生成互补色:使用HSL可以快速的为网站logo或标题icon设置强烈对比的互补色,只需要将hue值+180即可,根据实际需求动态调整。
  3. 交互反馈:在设计交互元素时,可以使用HSL来创建动态的颜色变化,例如当用户悬停或点击按钮时,通过调整饱和度或亮度来提供视觉反馈。
  4. 其实只要是小幅度调整参数即可获得颜色变化的场景都适合使用hsl,hsl带来的好处就是可以更符合直觉的去生成颜色,而不用像rgb一样变换颜色毫无规律。

举个交互反馈的例子:

css">button{background: hsl(200, 50%, 50%); /* 蓝色调背景 */transition: background-color 2s;
}
// 仅提高亮度即可提供选中的视觉反馈效果
button:hover {background: hsl(200, 50%, 70%); /* 亮一点的蓝色 */
}

如何用代码转换hsl

RGB转HSL

设(r,g,b)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设 max等价于(r,g,b)中的最大者。设 min等于这些值中的最小者。要找到在HSL空间中的(r,g,b)值,这里的h∈[0,360)度是角度的色相角,而s,l∈[0,1] 是饱和度和亮度,计算为:
在这里插入图片描述
h的值通常规范化到位于0到360°之间。

以下是js代码实现,返回值为数组,分别对应hue(色相)、saturation(饱和度)、lightness(亮度)。

/*** rgb2hsl** @param {number} r 红色颜色值 0~255* @param {number} g 绿色颜色值 0~255* @param {number} b 蓝色颜色值 0~255*/
function rgb2hsl(r, g, b) {r /= 255;g /= 255;b /= 255;const max = Math.max(r, g, b);const min = Math.min(r, g, b);const diff = max - min;let h = 0;let l = (max + min) / 2;let s = 0;if (max === min) {h = 0;} else if (max === r && g >= b) {h = 60 * ((g - b) / diff);} else if (max === r && g < b) {h = 60 * ((g - b) / diff) + 360;} else if (max === g) {h = 60 * ((b - r) / diff) + 120;} else if (max === b) {h = 60 * ((r - g) / diff) + 240;};if (l === 0 || max === min) {s = 0;} else if (0 < l && l <= 0.5) {s = diff / (2 * l);} else if (l > 0.5) {s = diff / (2 - 2 * l);};return [Math.round(h), Math.round(s * 100), Math.round(l * 100)];
}

HSL转RGB

给定HSL空间中的(h,s,l)值定义的一个颜色,h在指示色相角度的值域 [0,360] 中,s和l在饱和度和亮度的值域 [0,1] 中。相应在RGB空间中的(r,g,b)三原色,r,g和b也分别对应于红色、绿色和蓝色的值域[0,1]中,它们可计算为:
首先,如果s=0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r,g和b都等于l。注意h的值在这种情况下是未定义的。
当s≠0的时候,可以使用下列过程:
在这里插入图片描述
以下是js代码实现,返回值为数组,分别对应R(红)、g(绿)、b(蓝)。

/*** hsl2rgb** @param {number} h Hue 色调 0 ~ 360* @param {number} s Saturation 饱和度 0 ~ 100* @param {number} l Lightness 亮度 0 ~ 100*/
function hsl2rgb(h, s, l) {h /= 360;s /= 100;l /= 100;let r = 0;let g = 0;let b = 0;let p = 0;let q = 0;function rgb(t, p, q) {if (t < 1.0 / 6.0) {return p + (q - p) * 6.0 * t;} else if (t >= 1.0 / 6.0 && t < 1.0 / 2.0) {return q;} else if (t >= 1.0 / 2.0 && t < 2.0 / 3.0) {return p + (q - p) * ((2.0 / 3.0) - t) * 6.0;} else {return p;}}function _rgb(t) {if (t < 0) {return t + 1.0;} else if (t > 1) {return t - 1.0;} else {return t;}}if (s === 0) {r = g = b = l;} else {q = l < 0.5 ? l * (1.0 + s) : l + s - l * s;p = 2.0 * l - q;r = rgb(_rgb(h + 1.0 / 3.0), p, q);g = rgb(_rgb(h), p, q);b = rgb(_rgb(h - 1.0 / 3.0), p, q);}return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}

HEX格式的互转

HEX只是由16进制数字代表了0-255,都可以通过rgb作为桥梁去转换hsl格式。
以下是hex和rgb的互转的js实现:

/*** rgb2hex** @param {number} r 红色颜色值 0~255* @param {number} g 绿色颜色值 0~255* @param {number} b 蓝色颜色值 0~255* @param {number} a 透明度 0~100,默认100*/
function rgb2hex(r, g, b, a) {if (typeof a === 'undefined') {a = '';}else {a = Math.round(255 * a / 100);a = (a | 1 << 8).toString(16).slice(1);}const val = ((b | g << 8 | r << 16) | 1 << 24).toString(16).slice(1);return val.toUpperCase() + a.toUpperCase();
}/*** hex2rgb** @param {string} hex hex颜色值 eg: #000、#325312、#b2c343*/
function hex2rgb(hex) {hex = hex.replace(/^#/, '');let a = null;if (hex.length === 8) {a = parseInt(hex.slice(6, 8), 16) / 255;hex = hex.slice(0, 6);}if (hex.length === 4) {a = parseInt(hex.slice(3, 4).repeat(2), 16) / 255;hex = hex.slice(0, 3);}if (hex.length === 3) {hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];}const num = parseInt(hex, 16);const r = num >> 16;const g = (num >> 8) & 255;const b = num & 255;const rgb = [r, g, b];if (a !== null) {rgb.push(Math.round(a * 100));}return rgb;
}

总结

在日常开发过程中,大多数情况下UI提供的颜色值为rgb或者hex格式,有些设计网站会直接提供hsl格式的色值。通过这篇文章主要想阐述一个事实,那就是hsl相对于rgb在前端开发领域是有很大优势的,尤其是编码层面上。使用hsl会使css的编码更加清晰,得到的颜色大概率不会偏离预期。可能现阶段大家用的不是很多,所以会有所抵触,在使用一段时间后,相信你会爱上这种颜色模式。


http://www.ppmy.cn/server/120913.html

相关文章

U盘显示未被格式化的全面解析与数据救援策略

一、现象直击&#xff1a;U盘显示未被格式化的困境 在日常的数字生活中&#xff0c;U盘作为便携的存储工具&#xff0c;承载着大量重要数据。然而&#xff0c;当您满怀期待地将U盘插入电脑&#xff0c;却迎面碰上“未被格式化”的警告时&#xff0c;无疑是一场突如其来的数据危…

基于机器学习的注意力缺陷/多动障碍 (ADHD)(python论文+代码)HYPERAKTIV

简述 医疗保健领域的机器学习研究往往缺乏完全可重复性和可比性所需的公共数据。由于患者相关数据附带的隐私问题和法律要求&#xff0c;数据集往往受到限制。因此&#xff0c;许多算法和模型发表在同一主题上&#xff0c;没有一个标准的基准。因此&#xff0c;本文提出了一个公…

红外图像绝缘子识别数据集

红外图像绝缘子识别数据集&#xff0c;数据集一共919张图片&#xff0c;标注为voc格式&#xff0c;可以转yolo格式 数据集名称 红外图像绝缘子识别数据集 (Infrared Insulator Recognition Dataset, IIRD) 数据集描述 IIRD是一个专为电气工程领域设计的小规模红外图像数据集…

【贪心算法】贪心算法二

贪心算法二 1.最长递增子序列2.递增的三元子序列3.最长连续递增序列 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 1.最长递增子序列 题目链…

word批量裁剪图片,并调整图片大小,不锁定纵横比

在word中有若干图片待处理&#xff0c;裁剪出指定内容&#xff0c;调整成指定大小。如下是待处理的图片&#xff1a; 这时&#xff0c;选择视图&#xff0c;选择宏&#xff0c;查看宏 选择创建宏 添加cut_picture代码如下&#xff0c;其中上、下、左、右裁剪的橡塑尺寸根据自己…

解决Echarts:宽度100%,渲染的宽度却是100px

为什么我们宽度设置了100%&#xff0c;结果变为了100px&#xff1f; 源码这里没有获取到clientWidth&#xff0c;会将设置的width:100%转换称100px 解决办法&#xff1a; <div ref"numberPieRef"></div>let numberPieRef ref(null); let myChart nu…

电脑串口和手机蓝牙BLE串口数据包通信调试工具

1&#xff0c;支持HEX收发 2&#xff0c;支持文本收发 3&#xff0c;支持自定义按钮发送自定义命令和数据包 4&#xff0c;支持自定义解析包内任意位置1~4字节转int并显示 5&#xff0c;自定义json举例说明 [ {"name":"1234命令","type":"b…

基于微信小程序的健身房管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的健…