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

推荐订阅源

宝玉的分享
宝玉的分享
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks
V2EX - 技术
V2EX - 技术
Hacker News: Ask HN
Hacker News: Ask HN
T
Tailwind CSS Blog
V
Visual Studio Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
月光博客
月光博客
H
Hacker News: Front Page
D
DataBreaches.Net
GbyAI
GbyAI
Recorded Future
Recorded Future
IT之家
IT之家
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Schneier on Security
Schneier on Security
P
Privacy International News Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Security Affairs
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
L
LangChain Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
腾讯CDC
The Last Watchdog
The Last Watchdog
I
Intezer
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News - Newest:
Hacker News - Newest: "LLM"
Stack Overflow Blog
Stack Overflow Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
U
Unit 42
H
Help Net Security
Simon Willison's Weblog
Simon Willison's Weblog
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Schneier on Security
T
Tenable Blog
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
B
Blog
S
Security @ Cisco Blogs
A
About on SuperTechFans
V
V2EX
T
The Exploit Database - CXSecurity.com

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.