Docs

You are viewing an archived version of the docs.Go to latest version

Appearance prop

The appearance prop can be applied to React's <ClerkProvider> to share styles across every component, or individually to any of the Clerk components.

This applies to all of the React-based packages, like Next.js and Gatsby, as well as the pure JavaScript ClerkJS package.

Using a pre-built theme

Clerk offers a set of themes that can be used with the appearance prop. The themes are available as a package called @clerk/themes.

terminal
npm install @clerk/themes
terminal
yarn add @clerk/themes
terminal
pnpm add @clerk/themes

Usage

To use a theme, import it from @clerk/themes and pass it to the appearance prop of a Clerk component. You can pass it to the <ClerkProvider> component to apply it to all Clerk components in your app or you can pass it to a single Clerk component.

Pass a theme to <ClerkProvider>

To apply a theme to all Clerk components, pass the appearance prop to the <ClerkProvider> component. The appearance prop accepts the property baseTheme, which can be set to a theme.

In the example below, the dark theme is applied to all Clerk components.

/src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark } from '@clerk/themes';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark
      }}
    >
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}
_app.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark } from '@clerk/themes';
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark
      }}
    >
      <Component {...pageProps}/>
    </ClerkProvider>
  )
}

export default MyApp;
app.tsx
import React from "react";
import "./App.css";
import { dark } from '@clerk/themes';
import { ClerkProvider } from "@clerk/clerk-react";

if (!process.env.REACT_APP_CLERK_PUBLISHABLE_KEY) {
  throw new Error("Missing Publishable Key")
}
const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY;

function App() {
  return (
    <ClerkProvider 
      appearance={{
        baseTheme: dark
      }} 
      publishableKey={clerkPubKey}
    >
      <div>Hello from clerk</div>
    </ClerkProvider>
  );
}

export default App;
app/root.tsx
// Import ClerkApp
import { ClerkApp } from "@clerk/remix";
import { dark } from '@clerk/themes';
import type { MetaFunction,LoaderFunction } from "@remix-run/node";

import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { rootAuthLoader } from "@clerk/remix/ssr.server";

export const meta: MetaFunction = () => ({
  charset: "utf-8",
  title: "New Remix App",
  viewport: "width=device-width,initial-scale=1",
});

export const loader: LoaderFunction = (args) => rootAuthLoader(args);

function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default ClerkApp(App, {
  appearance: {
    baseTheme: dark,
  },
});

You can also stack themes by passing an array of themes to the baseTheme property of the appearance prop. The themes will be applied in the order they are listed. If styles overlap, the last defined theme will take precedence.

In the example below, the dark theme is applied first, then the neobrutalism theme is applied on top of it.

/src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark, neobrutalism } from '@clerk/themes';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: [dark, neobrutalism]
      }}
    >
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}
_app.tsx
import { ClerkProvider, SignIn } from '@clerk/nextjs';
import { dark, neobrutalism } from '@clerk/themes';
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: [dark, neobrutalism]
      }}
    >
      <Component {...pageProps}/>
    </ClerkProvider>
  )
}

export default MyApp;
app.tsx
import React from "react";
import "./App.css";
import { dark, neobrutalism } from '@clerk/themes';
import { ClerkProvider } from "@clerk/clerk-react";

if (!process.env.REACT_APP_CLERK_PUBLISHABLE_KEY) {
  throw new Error("Missing Publishable Key")
}
const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY;

function App() {
  return (
    <ClerkProvider 
      appearance={{
        baseTheme: [dark, neobrutalism]
      }} 
      publishableKey={clerkPubKey}
    >
      <div>Hello from clerk</div>
    </ClerkProvider>
  );
}

export default App;
app/root.tsx
// Import ClerkApp
import { ClerkApp } from "@clerk/remix";
import { dark, neobrutalism } from '@clerk/themes';
import type { MetaFunction,LoaderFunction } from "@remix-run/node";

import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { rootAuthLoader } from "@clerk/remix/ssr.server";

export const meta: MetaFunction = () => ({
  charset: "utf-8",
  title: "New Remix App",
  viewport: "width=device-width,initial-scale=1",
});

export const loader: LoaderFunction = (args) => rootAuthLoader(args);

function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default ClerkApp(App, {
  appearance: {
    baseTheme: [dark, neobrutalism]
  },
});

You can apply a theme to all instances of a Clerk component by passing the component to the appearance prop of the <ClerkProvider>. The appearance prop accepts the name of the Clerk component you want to style as a key.

In the example below, the neobrutalism theme is applied to all instances of the <SignIn /> component.

/src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark, neobrutalism } from '@clerk/themes';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark,
        signIn: { baseTheme: neobrutalism },
      }}
    >
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}
_app.tsx
import { ClerkProvider, SignIn } from '@clerk/nextjs';
import { dark } from '@clerk/themes';
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark,
        signIn: { baseTheme: neobrutalism },
      }}
    >
      <Component {...pageProps}/>
    </ClerkProvider>
  )
}

export default MyApp;
app.tsx
import React from "react";
import "./App.css";
import { dark } from '@clerk/themes';
import { ClerkProvider } from "@clerk/clerk-react";

if (!process.env.REACT_APP_CLERK_PUBLISHABLE_KEY) {
  throw new Error("Missing Publishable Key")
}
const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY;

function App() {
  return (
    <ClerkProvider 
      appearance={{
        baseTheme: dark,
        signIn: { baseTheme: neobrutalism },
      }} 
      publishableKey={clerkPubKey}
    >
      <div>Hello from clerk</div>
    </ClerkProvider>
  );
}

export default App;
app/root.tsx
// Import ClerkApp
import { ClerkApp } from "@clerk/remix";
import { dark } from '@clerk/themes';
import type { MetaFunction,LoaderFunction } from "@remix-run/node";

import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { rootAuthLoader } from "@clerk/remix/ssr.server";

export const meta: MetaFunction = () => ({
  charset: "utf-8",
  title: "New Remix App",
  viewport: "width=device-width,initial-scale=1",
});

export const loader: LoaderFunction = (args) => rootAuthLoader(args);

function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default ClerkApp(App, {
  appearance: {
    baseTheme: dark,
    signIn: { baseTheme: neobrutalism },
  },
});

Pass a theme to a single Clerk component

To apply a theme to a single Clerk component, pass the appearance prop to the component. The appearance prop accepts the property baseTheme, which can be set to a theme.

/app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from "@clerk/nextjs";
import { dark } from "@clerk/themes";

export default function Page() {
  return <SignIn 
    appearance={{
      baseTheme: dark
    }}
  />;
}
/pages/sign-in/[[...index]].tsx
import { SignIn } from "@clerk/nextjs";
import { dark } from "@clerk/themes";

const SignInPage = () => (
  <SignIn 
    appearance={{
      baseTheme: dark
    }}
  />
);

export default SignInPage;
/src/sign-in/[[...index]].tsx
import { SignIn } from "@clerk/clerk-react";
import { dark } from "@clerk/themes";

const SignInPage = () => (
  <SignIn 
    appearance={{
      baseTheme: dark
    }}
  />
);

export default SignInPage;
app/routes/sign-in/$.tsx
import { SignIn } from "@clerk/remix";
import { dark } from "@clerk/themes";

export default function SignInPage() {
  return (
    <div style={{ border: "2px solid blue", padding: "2rem" }}>
      <h1>Sign In route</h1>
      <SignIn 
        appearance={{
          baseTheme: dark
        }}
        routing={"path"} 
        path={"/sign-in"} 
      />
    </div>
  );
}

Customize a theme using variables

You can customize a theme by passing an object of variables to the variables property of the appearance prop. The variables property is used to adjust the general styles of the component's base theme, like colors, backgrounds, typography.

In the example below, all Clerk components will have the dark theme with the neobrutalism theme applied on top of it, and the primary color will be set to red. All <SignIn /> components will have the shadesOfPurple theme applied on top of the dark and neobrutalism themes, and the primary color will be set to blue.

Note

For a list of all of the variables you can customize, and for more examples on how to use the variables property, see the Variables docs.

/src/app/layout.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark, neobrutalism, shadesOfPurple } from '@clerk/themes';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: [dark, neobrutalism],
        variables: { colorPrimary: 'red' },
        signIn: { 
          baseTheme: [shadesOfPurple], 
          variables: { colorPrimary: 'blue' }
        }
      }}
    >
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  )
}
_app.tsx
import { ClerkProvider } from '@clerk/nextjs';
import { dark, neobrutalism, shadesOfPurple } from '@clerk/themes';
import type { AppProps } from "next/app";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: [dark, neobrutalism],
        variables: { colorPrimary: 'red' },
        signIn: { 
          baseTheme: [shadesOfPurple], 
          variables: { colorPrimary: 'blue' }
        }
      }}
    >
      <Component {...pageProps}/>
    </ClerkProvider>
  )
}

export default MyApp;
app.tsx
import React from "react";
import "./App.css";
import { dark, neobrutalism, shadesOfPurple } from '@clerk/themes';
import { ClerkProvider } from "@clerk/clerk-react";

if (!process.env.REACT_APP_CLERK_PUBLISHABLE_KEY) {
  throw new Error("Missing Publishable Key")
}
const clerkPubKey = process.env.REACT_APP_CLERK_PUBLISHABLE_KEY;

function App() {
  return (
    <ClerkProvider 
      appearance={{
        baseTheme: [dark, neobrutalism],
        variables: { colorPrimary: 'red' },
        signIn: { 
          baseTheme: [shadesOfPurple], 
          variables: { colorPrimary: 'blue' }
        }
      }}
      publishableKey={clerkPubKey}
    >
      <div>Hello from clerk</div>
    </ClerkProvider>
  );
}

export default App;
app/root.tsx
// Import ClerkApp
import { ClerkApp } from "@clerk/remix";
import { dark, neobrutalism, shadesOfPurple } from '@clerk/themes';
import type { MetaFunction,LoaderFunction } from "@remix-run/node";

import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

import { rootAuthLoader } from "@clerk/remix/ssr.server";

export const meta: MetaFunction = () => ({
  charset: "utf-8",
  title: "New Remix App",
  viewport: "width=device-width,initial-scale=1",
});

export const loader: LoaderFunction = (args) => rootAuthLoader(args);

function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

export default ClerkApp(App, {
  appearance={{
    baseTheme: [dark, neobrutalism],
    variables: { colorPrimary: 'red' },
    signIn: { 
      baseTheme: [shadesOfPurple], 
      variables: { colorPrimary: 'blue' }
    }
  }}
});

Create a custom theme

You can make a custom theme for your app's Clerk component by customizing the styles that are applied to each element.

This can be done with one of three different methods of styling:

  1. Using global CSS styling
  2. Passing custom CSS classes
  1. Passing inline CSS to your Clerk options

No matter which method you choose, you'll need to know how to identify the element you want to style.

Identify the underlying element

You can identify the underlying element by inspecting the HTML of the Clerk component. You can do this by right-clicking on the component in your browser and selecting "Inspect Element" or "Inspect":

The inspect element tab opened with an element selected. It shows a list of classes and a lock icon in between human-readible classnames and randomly generated ones

When you select an element that is part of a Clerk component, you'll notice a list of classes like so:

cl-formButtonPrimary cl-button 🔒️ cl-internal-1ta0xpz

Any of the classes listed before the lock icon (🔒️) are safe to rely on, such as cl-formButtonPrimary or cl-button. You'll use these classes to target the respective Clerk component elements.

Anything after the lock icon (🔒️) are internal classes used for Clerk's internal styling and should not be modified.

Use global CSS to style Clerk components

Using this knowledge about the publicly available classes, you can target the elements with global CSS.

Here's an example of how you can target the primary button in a Clerk component:

styles/global.css
.cl-formButtonPrimary {
  font-size: 14px;
  text-transform: none;
  background-color: #611bbd;
}

.cl-formButtonPrimary:hover,
.cl-formButtonPrimary:focus,
.cl-formButtonPrimary:active {
  background-color: #49247a;
}
The previously blue "Continue" button is now purple

Use custom CSS classes to style Clerk components

You're able to pass additional classes to Clerk component elements by using the elements property on appearance in your ClerkProvider.

If you look back to the list of classes applied to a Clerk component's element, you'll see a list of classes like so:

cl-formButtonPrimary cl-button 🔒️ cl-internal-1ta0xpz

Remove the cl- prefix and use it as the key for a new object in the elements property. The value of this object should be the string of classes you want to apply to the element.

app.tsx
import { ClerkProvider, SignIn } from "@clerk/nextjs";
import type { AppProps } from "next/app";

function MyApp({ pageProps }: AppProps) {
  return (
    <ClerkProvider {...pageProps}>
      <SignIn
        appearance={{
          elements: {
            formButtonPrimary: "your-org-button org-red-button",
          },
        }}
      />
    </ClerkProvider>
  );
}

export default MyApp;

Use Tailwind classes to style Clerk components

By using the method outlined above, you can use Tailwind classes to style Clerk components.

app.tsx
import { ClerkProvider, SignIn } from "@clerk/nextjs";
import type { AppProps } from "next/app";

function MyApp({ pageProps }: AppProps) {
  return (
    <ClerkProvider {...pageProps}>
      <SignIn
        appearance={{
          elements: {
            formButtonPrimary:
              "bg-slate-500 hover:bg-slate-400 text-sm normal-case",
          },
        }}
      />
    </ClerkProvider>
  );
}

export default MyApp;
A previously blue "Sign in" button is now Slate gray

Using CSS Modules

CSS modules are a great way to scope your CSS to a specific component. Clerk components can be styled with CSS modules by using the same method as outlined above.

Simply create your Module file and add the CSS you want to apply.

styles/SignIn.module.css
.primaryColor {
  background-color: bisque;
  color: black;
}

Then you can apply this by importing the file and using the classes whenever required:

app.tsx
import styles from "../styles/SignIn.module.css";
import { ClerkProvider, SignIn } from "@clerk/nextjs";
import type { AppProps } from "next/app";

function MyApp({ pageProps }: AppProps) {
  return (
    <ClerkProvider {...pageProps}>
      <SignIn
        appearance={{
          elements: {
            formButtonPrimary: styles.primaryColor,
          },
        }}
      />
    </ClerkProvider>
  );
}

export default MyApp;

Use inline CSS objects to style Clerk components

Using the same method for identifying elements as mentioned previously, you can pass an object of CSS properties to the elements property on appearance in your ClerkProvider.

app.tsx
import { ClerkProvider, SignIn } from "@clerk/nextjs";
import type { AppProps } from "next/app";

function MyApp({ pageProps }: AppProps) {
  return (
    <ClerkProvider {...pageProps}>
      <SignIn
        appearance={{
          elements: {
            formButtonPrimary: {
              fontSize: 14,
              textTransform: "none",
              backgroundColor: "#611BBD",
              "&:hover, &:focus, &:active": {
                backgroundColor: "#49247A",
              },
            },
          },
        }}
      />
    </ClerkProvider>
  );
}

export default MyApp;

Next steps

Here are a few resources you can utilize to customize your Clerk components further:

Localization

Learn how to localize the Clerk components.

Pre-built Themes

See which pre-built theme you'd like to use as a base.

Component Layout Customization

Learn how to change the layout and links of the Clerk components.

Feedback

What did you think of this content?

Last updated on