GuidesCustom Themes

Custom Themes

Theme Manager

Kavita supports customizing most of the colors via themes. You can either create your own or share it via our Theme’s Repo and download/update with the built-in client.

There are a few things to note:

  • You only need to add variables you want to override or any custom css
  • The file must be .css
  • The filename must only contain characters, numbers, and -
  • The filename must match the top-level CSS property
  • The .css file must be placed in /config/themes
  • After placing the file in the directory, you must scan for it using the Scan button on the User Settings > Themes page before you can apply it.
  • Optionally, you can set it as Default and all new accounts will have this theme auto-selected (they can override with their preference)
  • This is limited to the properties we have exposed. (See Available CSS Variables Below)
  • Technically, any css can be injected to customize the layout.

If you would like any other properties exposed, please feel free to suggest themes via a feature request.

So for instance, if we created /config/themes/test-theme-123.css then the CSS within the file should be structured as follows

:root .bg-test-theme-123 {
  /* CSS Variables here */
  }

Available CSS Variables

You can use color: var(--css-variable-name) to refer to a defined css variable.

Color-scheme

This refers to the scroll bar color as well as which color placeholder images to use.

--color-scheme: dark/light;

This refers to the tab color in the browser. Modifies the meta tag. (v0.6.1.27+)

--theme-color: hex/rgb;

This refers to the tile color for the windows tile view. Modifies the meta tag. (v0.6.1.28+)

--tile-color: hex/rgb;

Main Colors

These refer to base colors you can override, you can add more and use them as additional colors for hovers.

--primary-color: hex/rgb(a);  
--primary-color-dark-shade: hex/rgb(a);  
--primary-color-darker-shade: hex/rgb(a);  
--primary-color-darkest-shade: hex/rgb(a);  
--error-color: hex/rgb(a);  
--bs-body-bg: hex/rgb(a);  // Background color for pages  
--body-text-color: hex/rgb(a);   
--btn-icon-filter: invert(1) grayscale(%) brightness(%));  // Any filter chain. Useful mainly for dark themes
--dropdown-icon-white: url;
--dropdown-icon-black: url;

Elevation System

You can find more information about Elevation here.

--elevation-layer0: rgba;
--elevation-layer1: rgba;
--elevation-layer2: rgba;
--elevation-layer3: rgba;
--elevation-layer4: rgba;
--elevation-layer5: rgba;
--elevation-layer6: rgba;
--elevation-layer7: rgba;
--elevation-layer8: rgba;
--elevation-layer9: rgba;
--elevation-layer10: rgba;
 
--elevation-layer0-dark: rgba;
--elevation-layer1-dark: rgba;
--elevation-layer2-dark: rgba;
--elevation-layer3-dark: rgba;
--elevation-layer4-dark: rgba;
--elevation-layer5-dark: rgba;
--elevation-layer6-dark: rgba;
--elevation-layer7-dark: rgba;
--elevation-layer8-dark: rgba;
--elevation-layer9-dark: rgba;
--elevation-layer10-dark: rgba;
--elevation-layer11-dark: rgba;
 
--elevation-layer0-dark-solid: hex/rgb;
--elevation-layer1-dark-solid: hex/rgb;
--elevation-layer2-dark-solid: hex/rgb;
--elevation-layer3-dark-solid: hex/rgb;
--elevation-layer4-dark-solid: hex/rgb;
--elevation-layer5-dark-solid: hex/rgb;
--elevation-layer6-dark-solid: hex/rgb;
--elevation-layer7-dark-solid: hex/rgb;
--elevation-layer8-dark-solid: hex/rgb;
--elevation-layer9-dark-solid: hex/rgb;

Colorscape

Theming colors that performs a gradient for background. Can be disabled else automatically applied based on cover image colors. --colorscape-primary-color and the alpha variants will be updated in real time. the default variant is fixed and represents the default state and should match the non-default/alpha on launch.

--colorscape-enabled: true/false; // This will be overridden by User setting
 
/* These are the default background colors for the app. These will be updated on different pages with the generated colors. Must be RGB */
--colorscape-primary-color: rgb;
--colorscape-lighter-color: rgb;
--colorscape-darker-color: rgb;
--colorscape-complementary-color: rgb;
 
/* These need to be an alpha 0 variant. */
--colorscape-primary-color: rgba;
--colorscape-lighter-color: rgba;
--colorscape-darker-color: rgba;
--colorscape-complementary-color: rgba;
 
/* These are the default background colors. They need to match and cannot be a var reference. They will not be updated. */
--colorscape-primary-default-color: rgb;
--colorscape-lighter-default-color: rgb;
--colorscape-darker-default-color: rgb;
--colorscape-complementary-default-color: rgb;

Global

--hr-color: hex/rgb(a);  
--accent-bg-color: hex/rgb(a);  
--accent-text-color: hex/rgb(a);  
--grid-breakpoints-xs: px;  
--grid-breakpoints-sm: px;  
--grid-breakpoints-md: px;  
--grid-breakpoints-lg: px;  
--grid-breakpoints-xl: px;  
--body-font-family: "Font-Family", sans-serif;  
--brand-font-family: "Font-Family", sans-serif;  
--primary-color-scrollbar: hex/rgb(a); 
--default-state-scrollbar: hex/rgb(a); 
--text-muted-color: hex/rgb(a); 
--mobile-series-img-background: true/false; // Should we render the series cover as background on mobile

Setting Item

--setting-header-text-color: hex/rgb(a);    
--setting-break-color: hex/rgb(a);  
--setting-header-font-size: px/rem;  
--setting-header-font-weight: bold/bolder;  

Table

--table-header-bg-color: hex/rgb(a);
--table-header-text-color: hex/rgb(a);
--table-body-bg-color: hex/rgb(a);
--table-body-text-color: hex/rgb(a);
--table-body-striped-bg-color: hex/rgb(a);
--table-body-border: hex/rgb(a);
--table-body-striped-bg-color: hex/rgb(a);
--navbar-bg-color: hex/rgb(a);    
--navbar-text-color: hex/rgb(a);  
--navbar-fa-icon-color: hex/rgb(a);  
--navbar-btn-hover-outline-color: hex/rgb(a);  
--navbar-header-margin: hex/rgb(a);
--navbar-header-border-radius: hex/rgb(a);
--navbar-header-mobile-x-margin: hex/rgb(a);
--navbar-header-mobile-y-margin: hex/rgb(a);
--nav-mobile-offset: px;
--nav-offset: px;

Inputs

--input-bg-color: hex/rgb(a);  
--input-bg-readonly-color: hex/rgb(a);  
--input-focused-border-color: hex/rgb(a);  
--input-text-color: hex/rgb(a);  
--input-placeholder-color: hex/rgb(a);  
--input-border-color: hex/rgb(a);  
--input-focus-boxshadow-color: hex/rgb(a);
--input-hint-border-color: hex/rgb(a);
--input-hint-text-color: hex/rgb(a);

Buttons

--btn-primary-text-color: hex/rgb(a);  
--btn-primary-bg-color: hex/rgb(a);  
--btn-primary-border-color: hex/rgb(a);  
--btn-primary-hover-text-color: hex/rgb(a);  
--btn-primary-hover-bg-color: hex/rgb(a);  
--btn-primary-hover-border-color: hex/rgb(a);  
 
--btn-primary-outline-text-color: hex/rgb(a);
--btn-primary-outline-bg-color: hex/rgb(a);
--btn-primary-outline-border-color: hex/rgb(a);
--btn-primary-outline-hover-text-color: hex/rgb(a);
--btn-primary-outline-hover-bg-color: hex/rgb(a);
--btn-primary-outline-hover-border-color: hex/rgb(a);
 
--btn-secondary-text-color: hex/rgb(a);
--btn-secondary-bg-color: hex/rgb(a);
--btn-secondary-border-color: hex/rgb(a);
--btn-secondary-hover-bg-color: hex/rgb(a);
--btn-secondary-hover-border-color: hex/rgb(a);
--btn-secondary-font-weight: bold/bolder;
 
--btn-secondary-outline-text-color: hex/rgb(a);
--btn-secondary-outline-bg-color: hex/rgb(a);
--btn-secondary-outline-border-color: hex/rgb(a);
--btn-secondary-outline-hover-bg-color: hex/rgb(a);
--btn-secondary-outline-hover-border-color: hex/rgb(a);
--btn-secondary-outline-font-weight: bold/bolder;
 
--btn-primary-text-text-color: hex/rgb(a);
--btn-secondary-text-text-color: hex/rgb(a);
--btn-danger-text-text-color: hex/rgb(a);
 
--btn-alt-bg-color: hex/rgb(a);  
--btn-alt-border-color: hex/rgb(a);  
--btn-alt-hover-bg-color: hex/rgb(a);  
--btn-alt-focus-bg-color: hex/rgb(a);  
--btn-alt-focus-boxshadow-color: hex/rgb(a);  
--btn-fa-icon-color: hex/rgb(a);
--btn-disabled-bg-color: hex/rgb(a);  
--btn-disabled-text-color: hex/rgb(a);  
--btn-disabled-border-color: hex/rgb(a);  
--btn-focus-boxshadow-color: hex/rgb(a);  
--nav-tab-border-color: hex/rgb(a);  
--nav-tab-text-color: hex/rgb(a);  
--nav-tab-bg-color: hex/rgb(a);  
--nav-tab-hover-border-color: hex/rgb(a);  
--nav-tab-active-text-color: hex/rgb(a);  
--nav-link-bg-color: hex/rgb(a);  
--nav-link-active-text-color: hex/rgb(a);  
--nav-link-text-color: hex/rgb(a);  
--nav-tab-border-top: hex/rgb(a);  
--nav-tab-border-left: hex/rgb(a);  
--nav-tab-border-bottom: var(--bs-body-bg);  
--nav-tab-border-right: hex/rgb(a);  
--nav-tab-hover-text-color: hex/rgb(a);  
--nav-tab-hover-bg-color: hex/rgb(a);  
--nav-tab-hover-border-top: hex/rgb(a);  
--nav-tab-hover-border-left: hex/rgb(a);  
--nav-tab-hover-border-bottom: hex/rgb(a);  
--nav-tab-hover-border-right: hex/rgb(a);  
--nav-tab-active-hover-bg-color: hex/rgb(a);  
--nav-link-bg-color: hex/rgb(a);  
--nav-link-active-text-color: hex/rgb(a);  
--nav-link-text-color: hex/rgb(a);  
--modal-bg-color: hex/rgb(a);  

Alerts

--alert-text-color: hex/rgb(a);  
--alert-bg-color: hex/rgb(a);  
--nav-header-text-color: hex/rgb(a);  
--nav-header-bg-color: hex/rgb(a);  

Toasts

--toast-success-bg-color: hex/rgb(a);  
--toast-error-bg-color: hex/rgb(a);  
--toast-info-bg-color: hex/rgb(a);  
--toast-warning-bg-color: hex/rgb(a);  

Checkboxes/Switch

--checkbox-checked-bg-color: hex/rgb(a);  
--checkbox-border-color: hex/rgb(a);  
--checkbox-focus-border-color: hex/rgb(a);  
--checkbox-focus-boxshadow-color: hex/rgb(a);  

Tag Badge

--tagbadge-border-color: hex/rgb(a);  
--tagbadge-text-color: hex/rgb(a);  
--tagbadge-bg-color: vhex/rgb(a);  
--tagbadge-filled-border-color: hex/rgb(a);  
--tagbadge-filled-text-color: hex/rgb(a);  
--tagbadge-filled-bg-color: hex/rgb(a);  

Side Nav

--side-nav-width: hex/rgb(a);  
--side-nav-bg-color: hex/rgb(a);  
--side-nav-mobile-bg-color: hex/rgb(a);  
--side-nav-openclose-transition: s ease-in-out;  
--side-nav-box-shadow: hex/rgb(a);  
--side-nav-mobile-box-shadow: px/em hex/rgb(a);  
--side-nav-hover-text-color: hex/rgb(a);  
--side-nav-hover-bg-color: hex/rgb(a);  
--side-nav-header-text-color: hex/rgb(a);
--pref-side-nav-header-text-color: hex/rgb(a);
--side-nav-text-color: hex/rgb(a);  
--side-nav-border-radius: px;  
--side-nav-border: hex/rgb(a)/none;  
--side-nav-border-closed: hex/rgb(a)/none;  
--side-nav-border-transition: s ease-in-out;  
--side-nav-companion-bar-transistion:s linear;  
--side-nav-bg-color-transition: s ease-in-out;  
--side-nav-closed-bg-color: hex/rgb(a);  
--side-nav-item-color: hex/rgb(a);
--side-nav-item-active-color: hex/rgb(a);  
--side-nav-item-active-text-color: hex/rgb(a);  
--side-nav-active-bg-color: hex/rgb(a);  
--side-nav-overlay-color: hex/rgb(a);  
--side-nav-item-closed-color: hex/rgb(a);
--side-nav-item-closed-hover-color: hex/rgb(a);

List items

--list-group-item-text-color: hex/rgb(a);  
--list-group-item-bg-color: hex/rgb(a);  
--list-group-item-border-color: hex/rgb(a);  
--list-group-hover-text-color: hex/rgb(a);  
--list-group-hover-bg-color: hex/rgb(a);  
--list-group-active-border-color: hex/rgb(a);
--list-group-item-text-color: hex/rgb(a);
--list-group-item-bg-color: hex/rgb(a);
--search-list-group-item-bg-color: hex/rgb(a);
--list-group-hover-text-color: hex/rgb(a);
--list-group-hover-bg-color: hex/rgb(a);
--list-group-active-border-color: hex/rgb(a)/none;
--list-group-item-border-top-left-radius: px;
--list-group-item-border-top-right-radius: px;
--list-group-item-border-bottom-left-radius: px;
--list-group-item-border-bottom-right-radius: px;
--list-group-item-border-width: px;
--list-group-item-border-color: rgba;
--list-group-item-border-style: solid;
--list-group-item-first-border-width: px;
--list-group-item-last-border-width: px;

Popover

--popover-body-bg-color: hex/rgb(a);  
--popover-body-text-color: hex/rgb(a);  
--popover-outerarrow-color: hex/rgb(a);  
--popover-arrow-color: hex/rgb(a);  
--popover-bg-color: hex/rgb(a);  
--popover-border-color: hex/rgb(a);  

Pagination

--pagination-active-link-border-color: hex/rgb(a);  
--pagination-active-link-bg-color: hex/rgb(a);  
--pagination-active-link-text-color: hex/rgb(a);  
--pagination-link-border-color: hex/rgb(a);  
--pagination-link-text-color: hex/rgb(a);  
--pagination-link-bg-color: hex/rgb(a);  
--pagination-focus-border-color: hex/rgb(a);  
--pagination-link-hover-color: hex/rgb(a);

Progress Bar

--progress-striped-animated-color: linear-gradient(deg, rgba %, deg, rgba %, ..., deg, rgba %));  
--progress-bg-color: hex/rgb(a);  
--progress-bar-color: hex/rgb(a);  
--dropdown-item-hover-text-color: hex/rgb(a);  
--dropdown-item-hover-bg-color: hex/rgb(a);  
--dropdown-item-text-color: hex/rgb(a);  
--dropdown-item-bg-color: hex/rgb(a);  
--dropdown-overlay-color: hex/rgb(a);  

Accordion

--accordion-header-text-color: hex/rgb(a);  
--accordion-header-bg-color: hex/rgb(a);  
--accordion-body-bg-color: hex/rgb(a);  
--accordion-body-border-color: hex/rgb(a);  
--accordion-body-text-color: hex/rgb(a);  
--accordion-header-collapsed-text-color: hex/rgb(a);  
--accordion-header-collapsed-bg-color: hex/rgb(a);  
--accordion-button-focus-border-color: hex/rgb(a);  
--accordion-button-focus-box-shadow: hex/rgb(a);  
--accordion-active-body-bg-color: hex/rgb(a);  
--accordion-body-box-shadow: hex/rgb(a);  
--breadcrumb-bg-color: hex/rgb(a);  
--breadcrumb-item-text-color: hex/rgb(a);  

Rating star

--ratingstar-color: hex/rgb(a);  
--rating-star-color: hex/rgb(a);
--ratingstar-star-empty: hex/rgb(a);
--ratingstar-star-filled: hex/rgb(a);

Card

--card-bg-color: hex/rgb(a);  
--card-text-color: hex/rgb(a);  
--card-title-text-color: hex/rgb(a);
--card-body-bg-color: hex/rgb(a);
--card-border-width: hex/rgb(a);  
--card-border-style: hex/rgb(a);  
--card-border-color: hex/rgb(a);  
--card-progress-bar-color: hex/rgb(a);  
--card-overlay-bg-color: hex/rgb(a);  
--card-overlay-text-color: hex/rgb(a);
--card-overlay-hover-bg-color: hex/rgb(a);  
--card-progress-triangle-size: hex/rgb(a);  

Slider

--slider-text-color: hex/rgb(a);
--input-range-color: hex/rgb(a);
--input-range-active-color: hex/rgb(a);

Manga Reader

--manga-reader-overlay-filter: Filter(px);  
--manga-reader-overlay-bg-color: hex/rgb(a);  
--manga-reader-overlay-text-color: hex/rgb(a);  
--manga-reader-next-highlight-bg-color: hex/rgb(a);  
--manga-reader-prev-highlight-bg-color: hex/rgb(a);  

Radios

--radio-accent-color: hex/rgb(a);  
--radio-hover-accent-color: hex/rgb(a);  
--radio-focus-boxshadow-color: hex/rgb(a);  
--carousel-header-text-color: hex/rgb(a);  
--carousel-header-text-decoration: hex/rgb(a);  
--carousel-hover-header-text-decoration: hex/rgb(a);  
--carousel-btn-color: hex/rgb(a);

Series view

--detail-title-color: hex/rgb(a);  
--detail-subtitle-color: hex/rgb(a);  

Drawer

--drawer-bg-color: hex/rgb(a);
--drawer-text-color: hex/rgb(a);

Event Widget

--event-widget-bg-color: hex/rgb(a);  
--event-widget-item-bg-color: hex/rgb(a);  
--event-widget-text-color: hex/rgb(a);  
--event-widget-item-border-color: hex/rgb(a);  
--event-widget-border-color: hex/rgb(a);  
--event-widget-info-bg-color: hex/rgb(a);  
--event-widget-activity-bg-color: hex/rgb(a);  
--event-widget-update-bg-color: hex/rgb(a);  
--event-widget-error-bg-color: hex/rgb(a);  

Search Results

--search-result-text-lite-color: hex/rgb(a);

Bulk Selection

--bulk-selection-highlight-text-color: hex/rgb(a);
--bulk-selection-text-color: hex/rgb(a);
--bulk-selection-bg-color: hex/rgb(a);

Card List Item

--card-list-item-bg-color: hex/rgb(a);

Review Card

--review-card-star-color: hex/rgb(a);
--review-spoiler-bg-color: hex/rgb(a);
--review-spoiler-text-color: hex/rgb(a);

Rating Star

--rating-star-color: hex/rgb(a);

Badge

--badge-text-color: hex/rgb(a);

Breakpoints

--setting-mobile-breakpoint: number;
--setting-tablet-breakpoint: number;
--setting-desktop-breakpoint: number;

Charts

--charts-palette1: hex/rgb(a);
--charts-palette2: hex/rgb(a);
--charts-palette3: hex/rgb(a);
--charts-palette4: hex/rgb(a);
--charts-palette5: hex/rgb(a);
--charts-palette6: hex/rgb(a);
--charts-palette7: hex/rgb(a);

Tooltips

--tooltip-bg-color: hex/rgb(a);
--tooltip-outline-color: hex/rgb(a);
--tooltip-caret-color: hex/rgb(a);

Misc

--offwhite-text-color: hex/rgb(a);

Activity Card

--activity-card-client-platform-badge-bg-color: hex/rgb(a);
--activity-card-client-device-badge-bg-color: hex/rgb(a);