Skip to content

Custom CSS

This page covers custom CSS for Zensical. This is a powerful way to customize the look and feel of your documentation.

Official Docs


Adding Custom CSS

To customize the appearance of your site, you can add a custom style sheet that overrides or extends Zensical’s default styles. Whether you want to adjust the design or apply specific branding, simply place your style sheet file within the docs directory:

.
├─ docs/
│  └─ stylesheets/
│     └─ extra.css
└─ zensical.toml

Then, add the following lines to zensical.toml:

[project]
extra_css = ["stylesheets/extra.css"]

Custom CSS Example

Below is a configurable custom .CSS file. It is easily modifiable by editing the top config portion of the file. This is create a Gruvbox Dark theme, but can be easily modified to create any theme you like.

/* ==========================================================================
   ZENSICAL — CUSTOM THEME
   extra.css

   SETUP:
     zensical.toml:  extra_css = ["stylesheets/extra.css"]
     mkdocs.yml:     extra_css: - stylesheets/extra.css

   Also set in your config:
     palette.primary = "custom"
     palette.accent  = "custom"
     palette.scheme  = "slate"

   HOW TO CREATE A NEW THEME:
     Edit ONLY Section 1. Everything else references those variables.

   CURRENT PRESET: Gruvbox Dark (Hard Contrast)
   ========================================================================== */


/* ==========================================================================
   SECTION 1 — THEME VARIABLES (The Control Panel)
   Edit only this section to create a new theme.
   ========================================================================== */
:root {

  /* ── 1A. BASE PALETTE ─────────────────────────────────────────────────────
     Raw named colors. Referenced by all other variables below.
     Swap these first when changing the overall color palette.           */
  --color-red:              #fb4934;
  --color-orange:           #fe8019;
  --color-yellow:           #fabd2f;
  --color-green:            #b8bb26;
  --color-aqua:             #8ec07c;
  --color-blue:             #83a598;
  --color-purple:           #d3869b;
  --color-gray:             #928374;
  --color-white:            #fbf1c7;
  --color-black:            #1d2021;

  /* ── 1B. BACKGROUNDS ──────────────────────────────────────────────────────
     bg-base      → Body, footer, deepest layer (darkest)
     bg-surface   → Cards, sidebar, header, elevated panels
     bg-highlight → Code blocks, active inputs, hovered rows
     bg-border    → Dividers, table lines, input outlines               */
  --theme-bg-base:          #1d2021;
  --theme-bg-surface:       #282828;
  --theme-bg-highlight:     #3c3836;
  --theme-bg-border:        #504945;

  /* ── 1C. TYPOGRAPHY ───────────────────────────────────────────────────────
     text-main  → Primary body text
     text-bold  → Bold/strong text, nav titles
     text-muted → Subtitles, secondary nav, captions
     text-dim   → Comments, placeholders, disabled states               */
  --theme-text-main:        #ebdbb2;
  --theme-text-bold:        #fbf1c7;
  --theme-text-muted:       #d5c4a1;
  --theme-text-dim:         #928374;

  /* ── 1D. HEADING COLORS ───────────────────────────────────────────────────
     Each heading level is independently colored.
     For monochrome: set all to var(--theme-text-bold).                 */
  --h1-color:               var(--color-red);
  --h2-color:               var(--color-orange);
  --h3-color:               var(--color-yellow);
  --h4-color:               var(--color-green);
  --h5-color:               var(--color-blue);
  --h6-color:               var(--color-purple);

  /* ── 1E. ACCENTS & INTERACTION ───────────────────────────────────────────
     accent-main   → Buttons, progress bar, active tabs, scrollbar thumb
     accent-hover  → Hover color for links and interactive elements
     link          → Default unvisited link color
     link-active   → Active / currently selected nav link
     nav-title     → Collapsible nav section label color                */
  --theme-accent-main:      #fe8019;
  --theme-accent-hover:     #fabd2f;
  --theme-link:             #83a598;
  --theme-link-active:      #fe8019;
  --theme-nav-title:        var(--color-red);

  /* ── 1F. STATUS / ADMONITION COLORS ──────────────────────────────────────
     Left-border stripe colors for admonition/callout boxes.
     Covers: note/info, tip/success, warning, danger/failure, example   */
  --status-info:            #83a598;
  --status-success:         #b8bb26;
  --status-warning:         #fabd2f;
  --status-danger:          #fb4934;
  --status-special:         #d3869b;

  /* ── 1G. CODE SYNTAX HIGHLIGHTING ────────────────────────────────────────
     Pygments token type colors for fenced code blocks.                 */
  --code-keyword:           #fb4934;   /* if, for, return, def, class...   */
  --code-function:          #fabd2f;   /* function and method names        */
  --code-string:            #b8bb26;   /* string literals                  */
  --code-number:            #d3869b;   /* numeric literals                 */
  --code-comment:           #928374;   /* inline comments                  */
  --code-class:             #8ec07c;   /* class and type names             */
  --code-variable:          #83a598;   /* variable references              */
  --code-operator:          #ebdbb2;   /* +, =, !=, ->, ...                */
  --code-punctuation:       #d5c4a1;   /* brackets, commas, semicolons     */

  /* ── 1H. FONTS ───────────────────────────────────────────────────────────
     Per Zensical docs: always define fonts via CSS variables, not
     font-family directly, to preserve system font fallback.
     Also set theme.font in your config if loading from Google Fonts.   */
  --md-text-font:           "Inter";
  --md-code-font:           "JetBrains Mono";

  /* ── 1I. LAYOUT ──────────────────────────────────────────────────────────
     content-width → Max width of the main content column
     sidebar-width → Width of left/right navigation sidebars
     header-height → Height of the top fixed header bar                 */
  --layout-content-width:   60rem;
  --layout-sidebar-width:   14rem;
  --layout-header-height:   2.4rem;

  /* ── 1J. HERO SECTION ────────────────────────────────────────────────────
     bg-image      → Path to hero background image (relative to docs/)
     overlay-rgb   → RGB values of the overlay tint (match bg-base)
     overlay-alpha → Opacity of the tint overlay (0.0–1.0)             */
  --hero-bg-image:          url('../assets/landing-bg-gruvbox.png');
  --hero-overlay-rgb:       29, 32, 33;
  --hero-overlay-alpha:     0.85;

  /* ── 1K. TRANSITIONS ─────────────────────────────────────────────────────
     Shared animation timing used across all hover/focus interactions.  */
  --transition-speed:       0.2s;
  --transition-easing:      ease;

  /* ── 1L. SHADOWS ─────────────────────────────────────────────────────────
     z1 → Subtle: dropdowns, tooltips
     z2 → Medium: floating panels
     z3 → High: modals, overlays                                        */
  --shadow-z1: 0 0.2rem 0.5rem rgba(0,0,0,0.2), 0 0 0.05rem rgba(0,0,0,0.3);
  --shadow-z2: 0 0.3rem 0.8rem rgba(0,0,0,0.3), 0 0 0.05rem rgba(0,0,0,0.4);
  --shadow-z3: 0 0.4rem 1.2rem rgba(0,0,0,0.5), 0 0 0.05rem rgba(0,0,0,0.5);
}


/* ==========================================================================
   SECTION 2 — ZENSICAL INTERNAL VARIABLE MAPPING
   Maps Section 1 variables to the --md-* system used by Zensical internally.
   Do not edit values here — change Section 1 instead.
   ========================================================================== */
[data-md-color-scheme="slate"] {

  /* 2.1 Backgrounds */
  --md-default-bg-color:              var(--theme-bg-base);
  --md-default-bg-color--light:       var(--theme-bg-surface);
  --md-default-bg-color--lighter:     var(--theme-bg-highlight);
  --md-default-bg-color--lightest:    var(--theme-bg-surface);

  /* 2.2 Foreground / text */
  --md-default-fg-color:              var(--theme-text-main);
  --md-default-fg-color--light:       var(--theme-text-muted);
  --md-default-fg-color--lighter:     var(--theme-text-dim);
  --md-default-fg-color--lightest:    var(--theme-bg-border);

  /* 2.3 Primary: header bar (classic variant) + mobile drawer */
  --md-primary-fg-color:              var(--theme-bg-surface);
  --md-primary-fg-color--light:       var(--theme-text-bold);
  --md-primary-fg-color--dark:        var(--theme-bg-base);
  --md-primary-bg-color:              var(--theme-text-main);
  --md-primary-bg-color--light:       var(--theme-text-muted);

  /* 2.4 Accent: buttons, active tabs, scrollbar, loading bar */
  --md-accent-fg-color:               var(--theme-accent-main);
  --md-accent-fg-color--transparent:  rgba(254, 128, 25, 0.1);
  --md-accent-bg-color:               var(--theme-bg-surface);

  /* 2.5 Links */
  --md-typeset-a-color:               var(--theme-link);

  /* 2.6 Footer */
  --md-footer-bg-color:               var(--theme-bg-base);
  --md-footer-bg-color--dark:         var(--theme-bg-base);
  --md-footer-fg-color:               var(--theme-text-main);
  --md-footer-fg-color--light:        var(--theme-text-muted);
  --md-footer-fg-color--lighter:      var(--theme-text-dim);

  /* 2.7 Inputs and search box */
  --md-inputs-bg-color:               var(--theme-bg-highlight);
  --md-inputs-fg-color:               var(--theme-text-main);

  /* 2.8 Tables: alternating row tint */
  --md-typeset-table-color:           rgba(235, 219, 178, 0.05);

  /* 2.9 Admonitions */
  --md-admonition-bg-color:           var(--theme-bg-surface);
  --md-admonition-fg-color:           var(--theme-text-main);

  /* 2.10 Code */
  --md-code-bg-color:                 var(--theme-bg-surface);
  --md-code-fg-color:                 var(--theme-text-main);
  --md-code-hl-color:                 var(--theme-bg-highlight);
  --md-code-hl-keyword-color:         var(--code-keyword);
  --md-code-hl-function-color:        var(--code-function);
  --md-code-hl-string-color:          var(--code-string);
  --md-code-hl-number-color:          var(--code-number);
  --md-code-hl-special-color:         var(--status-special);
  --md-code-hl-comment-color:         var(--code-comment);
  --md-code-hl-variable-color:        var(--code-variable);
  --md-code-hl-name-color:            var(--code-class);
  --md-code-hl-operator-color:        var(--code-operator);
  --md-code-hl-punctuation-color:     var(--code-punctuation);
  --md-code-hl-generic-color:         var(--theme-text-muted);

  /* 2.11 Shadows */
  --md-shadow-z1:                     var(--shadow-z1);
  --md-shadow-z2:                     var(--shadow-z2);
  --md-shadow-z3:                     var(--shadow-z3);
}


/* ==========================================================================
   SECTION 3 — COMPONENT OVERRIDES
   Targeted element styling. All values reference Section 1 variables only.
   ========================================================================== */

/* ── 3.1 LAYOUT ─────────────────────────────────────────────────────────── */

.md-grid       { max-width: var(--layout-content-width); }
.md-sidebar    { width: var(--layout-sidebar-width); }
.md-header     { height: var(--layout-header-height); line-height: var(--layout-header-height); }

/* ── 3.2 TYPOGRAPHY ─────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] strong { color: var(--theme-text-bold); }
[data-md-color-scheme="slate"] .md-typeset { line-height: 1.75; }

[data-md-color-scheme="slate"] .md-typeset h1 { color: var(--h1-color); font-weight: 800; }
[data-md-color-scheme="slate"] .md-typeset h2 { color: var(--h2-color); font-weight: 700; }
[data-md-color-scheme="slate"] .md-typeset h3 { color: var(--h3-color); font-weight: 600; }
[data-md-color-scheme="slate"] .md-typeset h4 { color: var(--h4-color); font-weight: 600; }
[data-md-color-scheme="slate"] .md-typeset h5 { color: var(--h5-color); font-weight: 600; }
[data-md-color-scheme="slate"] .md-typeset h6 { color: var(--h6-color); font-weight: 600; }

/* ── 3.3 LINKS ──────────────────────────────────────────────────────────── */

.md-typeset a {
  transition: color var(--transition-speed) var(--transition-easing);
}
.md-typeset a:hover {
  color: var(--theme-accent-hover);
}

/* ── 3.4 NAVIGATION ─────────────────────────────────────────────────────── */

/* Collapsible section label */
[data-md-color-scheme="slate"] .md-nav__item--section > .md-nav__link[for] {
  color: var(--theme-nav-title);
  font-weight: 700;
}

/* Sidebar and header nav title */
[data-md-color-scheme="slate"] .md-nav__title {
  color: var(--theme-text-bold);
}

/* Currently active nav item */
[data-md-color-scheme="slate"] .md-nav__item--active > .md-nav__link {
  color: var(--theme-link-active);
}

/* ── 3.5 CODE ───────────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] .md-typeset code          { border-radius: 0.2rem; }
[data-md-color-scheme="slate"] .md-typeset pre > code    { border-radius: 0.3rem; }

/* ── 3.6 ADMONITIONS ────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] .md-typeset .admonition,
[data-md-color-scheme="slate"] .md-typeset details {
  border-width: 0 0 0 0.4rem;
  border-style: solid;
}

[data-md-color-scheme="slate"] .md-typeset :is(.admonition, details):is(.note, .info)     { border-color: var(--status-info); }
[data-md-color-scheme="slate"] .md-typeset :is(.admonition, details):is(.tip, .success)   { border-color: var(--status-success); }
[data-md-color-scheme="slate"] .md-typeset :is(.admonition, details).warning              { border-color: var(--status-warning); }
[data-md-color-scheme="slate"] .md-typeset :is(.admonition, details):is(.danger, .failure){ border-color: var(--status-danger); }
[data-md-color-scheme="slate"] .md-typeset :is(.admonition, details).example              { border-color: var(--status-special); }

/* ── 3.7 TABLES ─────────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] .md-typeset table:not([class]) {
  border: 1px solid var(--theme-bg-border);
  border-radius: 0.3rem;
}
[data-md-color-scheme="slate"] .md-typeset table:not([class]) th {
  background-color: var(--theme-bg-highlight);
  color: var(--theme-text-bold);
}
[data-md-color-scheme="slate"] .md-typeset table:not([class]) tr:hover {
  background-color: var(--theme-bg-highlight);
}

/* ── 3.8 SEARCH ─────────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] .md-search-result mark {
  color: var(--theme-accent-hover);
  background-color: transparent;
}

/* ── 3.9 SCROLLBAR ──────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] * {
  scrollbar-color: var(--theme-accent-main) var(--theme-bg-surface);
  scrollbar-width: thin;
}

/* ── 3.10 FOOTER ────────────────────────────────────────────────────────── */

[data-md-color-scheme="slate"] .md-footer a {
  color: var(--theme-text-muted);
  transition: color var(--transition-speed) var(--transition-easing);
}
[data-md-color-scheme="slate"] .md-footer a:hover {
  color: var(--theme-accent-hover);
}


/* ==========================================================================
   SECTION 4 — HERO (Landing Page)
   Full-viewport splash with overlay + background image.
   ========================================================================== */

body, html {
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

.hero-container {
  /* Breakout: span full viewport, ignore page padding */
  position: relative;
  width: 100vw;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;

  /* Alignment */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;

  /* Sizing */
  min-height: 100vh;
  padding: 4rem;
  margin-top: -5rem;    /* Pull up behind fixed header */
  margin-bottom: -5rem;
  box-sizing: border-box;

  /* Overlay tint over background image */
  background:
    linear-gradient(
      rgba(var(--hero-overlay-rgb), var(--hero-overlay-alpha)),
      rgba(var(--hero-overlay-rgb), var(--hero-overlay-alpha))
    ),
    var(--hero-bg-image);
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
}

.hero-container h1 {
  color: var(--h1-color);
  font-size: 3.5rem;
  font-weight: 800;
  margin: 0 0 1rem;
  text-shadow: 2px 2px 4px rgba(0,0,0,0.8);
}

.hero-container p {
  color: var(--theme-text-main);
  font-size: 1.4rem;
  max-width: 600px;
  margin-bottom: 2rem;
  line-height: 1.6;
  text-shadow: 1px 1px 2px rgba(0,0,0,0.8);
}

/* Call-to-action button inside hero */
.hero-container .hero-cta {
  display: inline-block;
  padding: 0.75rem 1.75rem;
  background-color: var(--theme-accent-main);
  color: var(--theme-bg-base);
  font-weight: 700;
  border-radius: 0.3rem;
  text-decoration: none;
  transition: background-color var(--transition-speed) var(--transition-easing);
}
.hero-container .hero-cta:hover {
  background-color: var(--theme-accent-hover);
}