CSS Customization
Understanding the CSS class system
When you inspect the DOM in Storybook, you’ll notice most elements have at least a couple of classes applied to them:
A class starting with
kc
, for examplekcLabelClass
.One or more classes starting with
pf-
, for examplepf-c-form__label
,pf-c-form__label-text
.

Classes beginning with kc
don’t have any styles applied to them by default. Their sole purpose is to serve as selectors for your custom styles.
Classes beginning with pf-
are Patternfly classes. Patternfly is a CSS framework created by RedHat, similar to Bootstrap, that the Keycloak team uses to build all of its UIs.
What you’ll want to do is partially or completely remove the Patternfly styles and then apply your custom ones.
Applying your custom CSS
Do not edit any file in the public/keycloakify-dev-resources
directory. These files are used by Storybook to simulate a Keycloak environment during development, and they aren't part of your actual theme.
To apply your custom CSS style, use the kc
classes to target the components.
.kcLabelClass {
border: 3px solid red;
}
import "./main.css";
// ...
This is the result:

Removing Some of the Default Styles
Let’s consider the Sign In button on the login page:

Here’s how we can “unstyle” it so that we can apply custom styles without worrying about conflicts from the default Patternfly styles:

To remove the Patternfly styles, inspect the button in your browser:

We can see which Patternfly classes are applied by default to the standardized element:
kcButtonClass
->pf-c-button
kcButtonPrimaryClass
->pf-m-primary
andlong-pf-btn
kcButtonBlockClass
->pf-m-block
kcButtonLargeClass
->btn-lg
Since we want to remove all the default styles, we can tell Keycloakify to remove all classes assigned by default to these kc
classes:
// ...
const classes = {
kcButtonClass: "",
kcButtonPrimaryClass: "",
kcButtonBlockClass: "",
kcButtonLargeClass: ""
} satisfies { [key in ClassKey]?: string };
After saving these changes, here’s the result:

Now you can freely apply your own custom button styles without Patternfly interfering.

Remove All the Default Styles
You may prefer to remove all Patternfly styles altogether and start fresh.

A benefit of this approach is that not only are all pf-
classes stripped out in one go, but the global Patternfly stylesheet isn’t even loaded.
// ...
<DefaultPage
kcContext={kcContext}
i18n={i18n}
classes={classes}
Template={Template}
doUseDefaultCss={false}
UserProfileFormFields={UserProfileFormFields}
doMakeUserConfirmPassword={doMakeUserConfirmPassword}
/>
Disabling the default styles only on some pages
A common scenario is using npx keycloakify eject-page
to customize only certain pages of the login UI in depth.
For pages you've ejected, you’ll likely want to disable all default styles; however, you might prefer to keep the Patternfly styles on the pages you haven't redesigned.
Below is an example where login.ftl
has been ejected and its default styles are disabled, while the other pages remain styled:
switch (kcContext.pageId) {
case "login.ftl":
return (
<Login
{...{ kcContext, i18n, classes }}
Template={Template}
doUseDefaultCss={false}
/>
);
default:
return (
<DefaultPage
kcContext={kcContext}
i18n={i18n}
classes={classes}
Template={Template}
doUseDefaultCss={true}
UserProfileFormFields={UserProfileFormFields}
doMakeUserConfirmPassword={doMakeUserConfirmPassword}
/>
);
}
Removing the classes in ejected components (kcClsx)
If you have ejected some pages with npx keycloakify eject-page
and disabled the default styles by setting doUseDefaultCss
to false
, you might wonder if you need to keep the kcClsx
in the pages. For example:
<input
tabIndex={7}
disabled={isLoginButtonDisabled}
className={kcClsx(
"kcButtonClass",
"kcButtonPrimaryClass",
"kcButtonBlockClass",
"kcButtonLargeClass"
)}
name="login"
id="kc-login"
type="submit"
value={msgStr("doLogIn")}
/>
The short answer is no; feel free to remove them.
Just be aware that if you have defined any custom CSS targeting those classes (for example .kcButtonClass { /* ... */ }
), they will no longer apply once you remove the classes.
Last updated
Was this helpful?