This page is a must-read. Even if you plan to redesign the pages at the component level, you should at least understand how to remove the default CSS styles.
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 example kcLabelClass.
One or more classes starting with pf-, for example pf-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.
Having different stylesheets for the login page, the register page, etc...
Here, we used a global stylesheet that applies to all pages of the login theme. However, you can also apply different stylesheets on a page-by-page basis (one for the login page, another one for the register page, etc...).
If you plan to customize the pages using React/Angular/Svelte at the component level, it will be very clear how to do so after reading the using a component library page.
However, if you plan to only customize with CSS, it might not be immediately obvious. Below is showing how you can achieve separate stylesheets:
src/login/KcPage.tsx
import { Suspense, lazy, useMemo} from"react";exportdefaultfunctionKcPage(props: { kcContext:KcContext }) {const { kcContext } = props;const { i18n } =useI18n({ kcContext });constclasses=useCustomStyles(kcContext);return ( <Suspense> {(() => {switch (kcContext.pageId) {default:return ( <DefaultPagekcContext={kcContext}i18n={i18n}classes={classes}Template={Template}doUseDefaultCss={true}UserProfileFormFields={UserProfileFormFields}doMakeUserConfirmPassword={doMakeUserConfirmPassword} /> ); } })()} </Suspense> );}functionuseCustomStyles(kcContext:KcContext) {returnuseMemo(() => {// Your stylesheet that applies to all pages.import("./main.css");let classes: { [keyinClassKey]?:string } = {// Classes that apply to all pages };switch (kcContext.pageId) {case"login.ftl":// A login page-specific stylesheet.import("./pages/login.css"); classes = {...classes,// Classes that apply only to the login page };break;case"register.ftl":// A register page-specific stylesheet.import("./pages/register.css"); classes = {...classes,// Classes that apply only to the register page };break;// ... }return classes; }, []);}
If this code doesn’t make much sense, you can watch this video tutorial where this approach is demonstrated in practice.
Using Tailwind
Of course, you can use Tailwind in the usual way by applying utility classes to the React/Angular/Svelte components.
But note that you can also use Tailwind without modifying the page structure by using the @apply directive. This is shown in this page.
If you want to use Bootstrap or another CSS framework that provides standardized classes, you might wonder how to apply these classes.
Here’s an example with Bootstrap:
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:
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:
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.