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

推荐订阅源

K
Kaspersky official blog
罗磊的独立博客
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
量子位
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
B
Blog RSS Feed
腾讯CDC
博客园_首页
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
博客园 - Franky
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
D
Docker
P
Privacy & Cybersecurity Law Blog
S
Securelist
V
V2EX
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
The Hacker News
The Hacker News
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Recent Announcements
Recent Announcements
Cloudbric
Cloudbric
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
V2EX - 技术
V2EX - 技术

Aaron Gustafson: Latest Posts

Can Your AI Pass the Accessibility Test? :: Aaron Gustafson Fixing Accessibility After the Fact Is Too Late :: Aaron Gustafson Easy Data-entry Verification with a Web Component :: Aaron Gustafson Visual Validation Feedback for Form Fields :: Aaron Gustafson Never Lose Form Progress Again :: Aaron Gustafson Accessibility Assistant for Figma v52 :: Aaron Gustafson Repeatable Form Fields Made Simple :: Aaron Gustafson A Production-Ready Web Component Starter Template :: Aaron Gustafson Fullscreen Video and Iframes Made Easy :: Aaron Gustafson Dynamic Datalist: Autocomplete from an API :: Aaron Gustafson Lazy Loading Images Based on Screen Size :: Aaron Gustafson A Web Component for Obfuscating Form Fields :: Aaron Gustafson Optimizing Your Codebase for AI Coding Agents :: Aaron Gustafson A Web Component for Conditionally Displaying Fields :: Aaron Gustafson Identifying Accessibility Data Gaps in CodeGen Models :: Aaron Gustafson Learning Web Design, 6th Edition is out! :: Aaron Gustafson Exploring AI’s Role in Accessibility :: Aaron Gustafson Complaining About Designers Fiddling with Figma Solves Nothing :: Aaron Gustafson On Diversity :: Aaron Gustafson A Web Component for Conditional Dependent Fields :: Aaron Gustafson On CrowdStrike, dependencies, and building robust products on the web :: Aaron Gustafson Requirement Rules for Checkboxes :: Aaron Gustafson Don’t Outsource Your Perspective to a LLM :: Aaron Gustafson One World, One Web, One Love :: Aaron Gustafson
Passing Your CSS Theme to `canvas` :: Aaron Gustafson
Aaron Gustafson · 2025-05-02 · via Aaron Gustafson: Latest Posts

While working on a recent project I noticed an issue with a canvas-based audio visualization when I toggled between light and dark modes. When I’d originally set it up I was browsing in dark mode and the light visualization stroke showed up perfectly on the dark background, but it was invisible when viewed using the light theme (which I’d neglected to test). I searched around, but didn’t find any articles on easy ways to make canvas respond nicely to user preferences, so I thought I’d share (in brief) how I solved it.

The CSS Setup

The theming of this particular project uses CSS custom properties. For simplicty I’m going to set up two named colors and then use two theme-specific custom properties to apply them in the default light theme and the dark theme:

:root {
  --color-dark: #222;
  --color-light: rgba(255, 255, 255, 0.5);

  --color-background: var(--color-light);
  --color-foreground: var(--color-dark);
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--color-dark);
    --color-foreground: var(--color-light);
  }
}

Applying the Theme to Canvas

To get the theme into my canvas-related code, I set up a theme object to hold the values:

const theme = {};

Next, I wrote a function to pull in the theme colors using window.getComputedStyle(). After defining the function, I call it immediately to populate the theme object:

function importTheme() {
  theme.foreground =
    window
      .getComputedStyle(document.documentElement)
      .getPropertyValue("--color-foreground")
      .trim() || "black";
  theme.background =
    window
      .getComputedStyle(document.documentElement)
      .getPropertyValue("--color-background")
      .trim() || "white";
}
importTheme();

I set this up with just two theme colors, but you can import as many (or few) as you like. Be sure to set a sensible default or fallback for each color though, just in case your theme’s custom property names change.

With this in place, I can set my canvas animation’s colors by referencing them from the theme object. For example:

context.fillStyle = theme.foreground;

Keeping Things in Sync

The final bit of magic comes when you add an event listener to a MediaQueryList:

const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
mediaQuery.addEventListener("change", importTheme);

Here I’ve used matchMedia() to get a MediaQueryList object. Typically we use the matches property of this object to establish whether the media query currently matches or not. A lesser-known option, however, is that you can attach an event listener to it that will be triggered whenever the query’s status changes. So cool! With this in place, the canvas contents will update whenever the user’s theme changes. Here’s an example of that:

This video demonstrates how a canvas element rendering a dark sine wave against a light background can miraculously transform into a light sine wave against a dark background using CSS custom properties and a bit of JavaScript.

Demo

I put together a quick demo of this in a fork of Alvin Shaw’s Canvas Sine Wave Experiment:


Hopefully this is helpful to someone out there. Happy theming!