惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Spread Privacy
Spread Privacy
S
Schneier on Security
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Application and Cybersecurity Blog
Application and Cybersecurity Blog
MongoDB | Blog
MongoDB | Blog
NISL@THU
NISL@THU
N
Netflix TechBlog - Medium
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Webroot Blog
Webroot Blog
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
Forbes - Security
Forbes - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗
Recent Announcements
Recent Announcements
IT之家
IT之家
B
Blog
C
CERT Recently Published Vulnerability Notes
S
SegmentFault 最新的问题
Recent Commits to openclaw:main
Recent Commits to openclaw:main
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
Know Your Adversary
Know Your Adversary
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Troy Hunt's Blog
O
OpenAI News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
V2EX - 技术
V2EX - 技术
L
Lohrmann on Cybersecurity
C
Cyber Attacks, Cyber Crime and Cyber Security
H
Help Net Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Last Week in AI
Last Week in AI
Help Net Security
Help Net Security
Hacker News: Ask HN
Hacker News: Ask HN
A
About on SuperTechFans
Y
Y Combinator Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
Vercel News
Vercel News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Recorded Future
Recorded Future
C
Cisco Blogs
Project Zero
Project Zero

daverupert.com

Finding curated public domain images A workaround for hiding empty slots in Chromium Spoons by Sam Vibe Check №42 The duality of language models in the browser 10,000-watt GPU meet 40-watt lump of meat I don’t want a screenshot of your Claude conversation When moving fast, talking is the first thing to break Inverted themes with light-dark() Ozempic dreams Before I go: People like it when other people make things People are not friction Smaller and dumber Priority of idle hands Magic Words Write about the future you want I’m swearing off APIs entirely Waiting for the power to go out The best version of my site so far… Focus rings with nested contrast-color()? Using your design system colors with contrast-color() Algorithmic hover states with contrast-color() Twenty Twenty-Five Vibe Check №41 One thing churches do well Grid Paper Inkwell Games
Interpolate contrast-color() to manipulate lightness
Dave Rupert · 2026-01-09 · via daverupert.com

In my first post on contrast-color() I demo’d using color-mix() to change a background-color on hover, but I will be honest… mixing black and white isn’t always what you want. It would be cool and helpful to coerce contrast-color() to return either 1 or -1 so that we could adjust lightness in a color function on hover instead of only mixing white and black.

Building on the inline CSS if() statements in my last post, we can use the same trick to interpolate the result of contrast-color() into a number.

Disclaimer: All caveats from the previous post about browser support, caching quirks, and expected syntax changes still apply.

See the Pen contrast-color() powered design system colors by Dave Rupert (@davatron5000) on CodePen.

Ahh… feel that? Now our states maintains its harmonious color palette where mixing in white or black gets us a bit muddier results. We’re picking another note on the scale of the color’s lightness ramp.

The relevant CSS to make this trick work goes like this:

/* Needed for if() statement */
@property --captured-color {
  syntax: "<color>";
  inherits: true;
  initial-value: white;
}

/* https://lea.verou.me/blog/2024/contrast-color/ */
@function --contrast-color(--bg-color) {
  --l: clamp(0, (l / var(--l-threshold, 0.623) - 1) * -infinity, 1);
  result: oklch(from var(--bg) var(--l) 0 0);
}

button {
  background-color: var(--ds-button-bg);
	--captured-color: --contrast-color(var(--ds-button-bg));
  --lighter-or-darker: if(
    style(--captured-color: oklch(1 0 0)): 2.5; /* go extra lighter */
    else: -1; /* go darker */
  );  
  ...
  
	&:hover, &:focus {
		background-color: oklch(
			from var(--ds-button-bg) 
			calc(l + (0.1 * var(--lighter-or-darker))) c h 
		);
  }
}

For comparison’s sake, I web-inspected up a little apples-to-apples, side-by-side of the adjusting lightness way and the color-mixing way of algorithmic hover states where it’s 10% lightened/darkened versus 10% mix of white/black.

a side by side look at adjusting lightness vs mixing in white and black. the rest for all the buttons is on top and the hover state for all the buttons is on the bottom. The hover states for the buttons on the adjusting lightness demo are a bit warmer, but probably hard to notice to the average person.

The difference is almost imperceptible, but the hover states from the “Adjust Lightness” method feel a tad bit warmer, particularly on the bottom row with the green, blue, and purple buttons. The difference becomes more obvious if the step is greater than 10%.

Unless your customers are a bunch of color dorks, they probably won’t see it the care you put into this. But I’m willing to wager that even if they don’t see the difference, they will be able to feel the difference.

We also get a lot more control with this if() statement route. For example, I can set the lighten amount to 2.5 (+25%) instead of 1 (+10%) because that’s what felt better. If you’re algorithmically generating your color palettes, it should be easy to find the ideal values; either a step-up or step-down, perhaps. And we’re also not just limited to lightness! You could mess with chroma or whatever the b in lab() is. Find what makes sense for your system.

A part of me wants to take this even further to get more control. For example, if the color is super dark (e.g. black) and the lightness value is below 0.1, lighten by 25%, otherwise lighten by 10%. That might be possible with an if() inside the oklch() or a sin() function… but that sounds like a lot of Math and probably hurts readability. More experiments to do though.

It’s fun to embark on this new world of algorithmic color schemes in vanilla CSS. While I’m excited to play, I’m more excited to see what your beautiful brains come up with.