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

推荐订阅源

Y
Y Combinator Blog
IT之家
IT之家
博客园_首页
人人都是产品经理
人人都是产品经理
博客园 - Franky
I
InfoQ
Recent Announcements
Recent Announcements
P
Proofpoint News Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
GbyAI
GbyAI
大猫的无限游戏
大猫的无限游戏
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
月光博客
月光博客
Microsoft Security Blog
Microsoft Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
雷峰网
雷峰网
博客园 - 聂微东
N
Netflix TechBlog - Medium
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
D
Docker

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) How do I add authentication to a Next.js app? Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage
Unicorn or Chameleon? Two strategies for exporting custom...
Colin Sidoti · 2022-04-15 · via Clerk Blog

Clerk's React library exports <SignUp/>, <SignIn/>, and <UserProfile/> components. They come styled and fully-featured so developers can focus on building their application:

Exporting Customizable React Components guide illustration

Unsurprisingly, this leads to the question: How can I customize the components to match my brand?

Whitelabeling software is a famously hard and unsolved problem - it's extremely common to find widgets or portions of websites that have completely different styling.

One example is this chat widget from Alaska Airlines, which shows different form field styling (rounded vs square), different buttons (huge text, not capitalized), and a different font (Arial vs Circular).

Exporting Customizable React Components guide illustration

This quarter at Clerk, we're revisiting our customization strategy. We want to truly solve this problem with perfect matching styles instead of just "close enough" styles. Internally, we say we're switching from a "unicorn" strategy to a "chameleon" strategy.

While we haven't finalized the chameleon strategy yet, we do have a proof of concept running and are excited about the developer experience it produces.

Unicorn strategy

Exporting Customizable React Components guide illustration

Our initial approach to theming is a "unicorn" strategy because we came up with the system ourselves – developers have to learn our specific way of applying styles.

We drew inspiration from others, so you've probably seen something like it before. Developers simply pass a theme prop to <ClerkProvider> to customize aspects of the design:

While this system is great for quickly getting close styles, it suffers in the last mile. There simply aren't enough options to provide developers with the complete customization capabilities they desire.

Chameleon strategy

Exporting Customizable React Components guide illustration

Our next iteration approaches customization with a new mindset. Instead of asking developers to learn our strategy, we will integrate with any strategy they already use.

If you've been around the frontend ecosystem for a while, you know there are several, very popular styling systems that all work completely differently. Because they're so diverse and we want to blend in with all of them, we call this a "chameleon" strategy.

Let's work through an example to explain how it works.

Consider that one of our components has a "primary button." By default, that button renders to this HTML:

Note: in this post, we're only focused on styles. We'll discuss customizing the "Action" string in the future.

To change the style of this button, developers will still pass a theme prop, but now the selector will be for this specific element:

In this snippet, customButton can have one of three values:

  1. A string with one or many class names. If passed, the value will replace the default clerk-button-primary class.
  2. A React component that renders a <button> and forwards all props (including children). If passed, the default element will not be rendered at all, and instead the passed component will be rendered.
  3. A dictionary that adheres to the CSSStyleInterface type. This is for completeness more than anything else. If passed, the value will be forwarded to the style prop, and the the default clerk-button-primary class will be omitted.

Now, let's see how it works for different styling libraries.

Tailwind

Simply pass in Tailwind classes as a string:

CSS modules

When a CSS module is imported, the object automatically returns class names. Simply pass it in:

styled-components

styled-components works by returning a React component that automatically forwards props to a <button> element – exactly as specified by Clerk:

Chakra

Chakra also provides React components, but they are modified with props, which makes the setup slightly more complex, but still quite simple:

Since the chameleon strategy ultimately hooks into HTML and React primitives, we're confident that we can make every styling library work with this strategy, not just the four we've listed above.

Thoughts, comments, questions? We're eager for your feedback! Please reach out to @clerk on X or contact support.