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

news2024/11/15 8:38: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一样变换颜色毫无规律。

举个交互反馈的例子:

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.coloradmin.cn/o/2157925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C/C++指针的前世今生

前言 老早之前就想写这个内容了&#xff0c;打了草稿后闲置了两个月&#xff0c;因为其他事就没再动过这个东西了&#xff0c;今天翻草稿箱的时候发现了它&#xff0c;就把它完善出来&#xff0c;顺便我也学习学习。 正文 指针的前世今生 前面先说一下&#xff0c;故事是随…

【第十七章:Sentosa_DSML社区版-机器学习之异常检测】

【第十七章&#xff1a;Sentosa_DSML社区版-机器学习之异常检测】 机器学习异常检测是检测数据集中的异常数据的算子&#xff0c;一种高效的异常检测算法。它和随机森林类似&#xff0c;但每次选择划分属性和划分点&#xff08;值&#xff09;时都是随机的&#xff0c;而不是根…

前端——实现时钟 附带小例子

创建日期对象 toLocaleDateString() 获取日期 console.log(date.toLocaleDateString()) toLocaleTimeString() 获取时间 console.log(date.toLocaleTimeString()) toLocaleString() 获取日期和时间 console.log(date.toLocaleString()) date.getDay() 获取星期几 周日为…

VisualStudio的“应用代码更改“按钮功能

无意发现这个按钮&#xff0c;因为开发这么多年也没专门尝试这个按钮&#xff0c;于是好奇它的功能。 光标放在按钮上面提示了“应用代码更改”&#xff0c;于是猜想应该是在调试不断开的情况下支持热应用更改。 经过验证&#xff0c;功能确实如同猜想的一样&#xff0c;具体验…

Leetcode 1039. 多边形三角形剖分的最低得分 枚举型区间dp C++实现

问题&#xff1a;Leetcode 1039. 多边形三角形剖分的最低得分 你有一个凸的 n 边形&#xff0c;其每个顶点都有一个整数值。给定一个整数数组 values &#xff0c;其中 values[i] 是第 i 个顶点的值&#xff08;即 顺时针顺序 &#xff09;。 假设将多边形 剖分 为 n - 2 个三…

力扣(leetcode)每日一题 1014 最佳观光组合

题干 1014. 最佳观光组合 给你一个正整数数组 values&#xff0c;其中 values[i] 表示第 i 个观光景点的评分&#xff0c;并且两个景点 i 和 j 之间的 距离 为 j - i。 一对景点&#xff08;i < j&#xff09;组成的观光组合的得分为 values[i] values[j] i - j &#…

windows 出现身份验证错误,要求的函数不受支持

现象环境&#xff1a; win10 mstsc内网远程server2016&#xff0c;出现错误代码&#xff1a; 远程桌面连接出现身份验证错误。要求的函数不受支持。这可能是由于CredSSP加密数据库修正 出现身份验证错误 原因&#xff1a; 系统更新&#xff0c;微软系统补丁的更新将 Cred…

<刷题笔记> 力扣236题——二叉树的公共祖先

236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 题目解释&#xff1a; 我们以这棵树为例&#xff0c;来观察找不同的最近公共祖先有何特点&#xff1a; 思路一&#xff1a; 除了第二种情况&#xff0c;最近公共祖先满足&#xff1a;一个节点在他的左边&am…

现代LLM基本技术整理

0 开始之前 本文从Llama 3报告出发&#xff0c;基本整理一些现代LLM的技术。基本&#xff0c;是说对一些具体细节不会过于详尽&#xff0c;而是希望得到一篇相对全面&#xff0c;包括预训练&#xff0c;后训练&#xff0c;推理&#xff0c;又能介绍清楚一些具体技术&#xff0…

Hierarchical Video-Moment Retrieval and Step-Captioning

背景 为了激发人们对使用机器学习系统从这些基于文本查询的大型视频语料库中提取和总结重要信息的兴趣&#xff0c;在视频检索、时刻检索、视频摘要和视频字幕方面取得了进展。以前的工作通常侧重于独立解决这些任务&#xff1b;然而&#xff0c;所有这些任务都有一个共同的目标…

科研绘图系列:R语言连线点图(linechart dotplot)

文章目录 介绍加载R包导入数据数据预处理画图组合图形导出数据系统信息介绍 不同物种的强度和微生物的组成情况 加载R包 library("here") library("tidyverse") library("reshape2") library("vegan")

照片写真记录摄影作品记录网站源码

完美适应iPad&#xff0c;平板&#xff0c;手机竖屏不支持lazy&#xff0c;横屏可以&#xff0c;但建议使用平板查看效果&#xff0c; 有服务器直接上传解压使用&#xff0c;环境nginxphp&#xff0c; 没有服务器也没关系&#xff0c;可以直接使用html

Cherry Studio:开启AI智能工作的新篇章

引言 在当今快速发展的科技时代&#xff0c;如何高效利用人工智能技术提升工作效率&#xff0c;成为了各行各业专业人士的共同追求。&#x1f352; Cherry Studio 正是为此而生&#xff0c;它是一款支持多模型服务的桌面客户端&#xff0c;内置了超过 30 个行业的智能助手&…

Could not load library libcudnn_cnn_train.so.8 问题及(非常简单)解决方案

问题描述 Could not load library libcudnn_cnn_train.so.8. Error: /usr/local/cuda-11.8/lib64/libcudnn_cnn_train.so.8: undefined symbol: _ZN5cudnn3cnn34layerNormFwd_execute_internal_implERKNS_7backend11VariantPackEP11CUstream_stRNS0_18LayerNormFwdParamsERKNS…

对抗攻击的详细解析:原理、方法与挑战

对抗攻击的详细解析&#xff1a;原理、方法与挑战 对抗攻击&#xff08;Adversarial Attack&#xff09;是现代机器学习模型&#xff0c;尤其是深度学习模型中的一个关键安全问题。其本质在于&#xff0c;通过对输入数据添加精微的扰动&#xff0c;人类难以察觉这些扰动&#…

教你一招:在微信小程序中为用户上传的图片添加时间水印

在微信小程序开发过程中&#xff0c;我们常常需要在图片上添加水印&#xff0c;以保护版权或增加个性化元素。本文将为大家介绍如何在微信小程序中为图片添加时间水印&#xff0c;让你的小程序更具特色。 实现步骤&#xff1a; 1. 创建页面结构 在pages目录下创建一个名为upl…

使用思科搭建企业网规划训练,让网络全部互通,使用规则提高工作效率。

1. 企业背景&#xff1a; 某企业分为销售部、行政部、人力资源部、财务部、业务部、接待中心等主要六个部门&#xff1b;配置网管中心&#xff0c;允许网络管理员登录企业交换机和路由器对企业网络进行管理&#xff1b;配置服务器集群&#xff0c;设置FTP、DNS、WEB服务器&am…

一个基于 Tauri、Vite 5、Vue 3 和 TypeScript 构建的即时通讯系统,牛啊牛啊!(附源码)

这段时间正在学习桌面端开发&#xff0c;目前了解了Electron和Tauri,在搜索教程的时候发现了一位大佬用Tauri开发了个即时通讯的软件&#xff0c;并且技术栈用的也是VUE3和TypeScript&#xff0c;所以今天就给大家分享一下这个项目——HuLa HuLa HuLa 是一个基于 Tauri、Vite …

Skyeye 云智能制造 v3.14.6 发布,ERP 商城

Skyeye 云智能制造&#xff0c;采用 Springboot winUI 的低代码平台、移动端采用 UNI-APP。包含 30 多个应用模块、50 多种电子流程&#xff0c;CRM、PM、ERP、MES、ADM、EHR、笔记、知识库、项目、门店、商城、财务、多班次考勤、薪资、招聘、云售后、论坛、公告、问卷、报表…

【Elasticsearch系列廿一】ES7 SQL 新特性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…