⌘K

Theming Guide

A practical reference for the CSS conventions, load order, and system variables that apply to every SynaptikCMS theme.


CSS load order

The CMS injects stylesheets in this exact order, via render_header_scripts() in header.php:

  1. css/synaptikCSS.php — combined system styles: gallery-layout.css, lightbox.css, search.css, shortcodes.css
  2. theme/{active}/css/style.css — your theme stylesheet (with ?v=mtime cache busting)

Consequence: your style.css always loads last. Any rule with equal or greater specificity overrides a system rule. You do not need !important for standard overrides — fix specificity at the selector level instead.

Consequence for shortcodes: shortcodes.css loads before your style.css. Shortcode classes (.sc-callout, .sc-button, .sc-quote, etc.) can be freely overridden in your theme.


System CSS custom properties

The CMS injects one custom property into :root at runtime:

PropertyWhen setValue
--snk-adminbar-heightAdmin is logged in36px

When no admin session is active, the property is not declared. Use the var() fallback syntax:

.site-header {
  top: var(--snk-adminbar-height, 0px);
}

Do not declare --snk-adminbar-height in your theme — the fallback handles the default case automatically.


Admin bar offset

The CMS injects a 36 px admin toolbar at the top of the viewport when an administrator is logged in. Two things to handle:

1. Offset fixed navigation

Any position: fixed element with a top offset must account for the bar:

.site-header {
  position: fixed;
  top: var(--snk-adminbar-height, 0px);
}

For elements below the header, use calc():

.sidebar {
  position: fixed;
  top: calc(var(--snk-adminbar-height, 0px) + var(--header-h));
}

position: sticky elements do not need this — they follow the normal document flow.

2. Render the bar before your navigation

If your header uses backdrop-filter, it creates a CSS stacking context that can push the admin bar behind it regardless of z-index. Call render_adminbar() as the first child of <body>:

</head>
<body>
<?php render_adminbar(); ?>

<header class="site-header">
  ...

This is a no-op for non-admin visitors. Calling it explicitly is recommended for all themes as a best practice, even without backdrop-filter.


Search overlay variables

The search overlay (css/search.css) is fully themeable via CSS custom properties. All of the following are required in your theme's :root:

:root {
  --search-overlay-bg:        #1a1a18;
  --search-card-bg:           #2a2a25;
  --search-card-bg-hover:     #111009;
  --search-accent:            #3ea34e;
  --search-accent-dark:       #2d8a3d;
  --search-accent-light:      #52c463;
  --search-text:              rgba(255,255,255,.85);
  --search-section-heading:   rgba(255,255,255,.35);
  --search-radius:            4px;
}

See Search Overlay Theming for the full reference, light/dark examples, and how to map these to your existing theme tokens.


Required CSS classes

The CMS core and default card renderers emit these classes. Your theme must style them (or accept the unstyled output):

ClassRendered by
.articles-gridrender_home_articles()
.article-cardrender_article_card()
.projects-gridrender_home_projects()
.project-cardrender_project_card()
.related-itemsrender_related_items()
.custom-fields-blockrender_item_custom_fields()
.featured-imagerender_featured_image()
.content-titlerender_content_title()
.content-daterender_content_date()
.content-categoryrender_content_category()
.content-tagsrender_content_tags()

Card classes (.article-card, .project-card) can be fully replaced by providing card partials.

Other classes that must be sylized in CSS, or at least not broken:

/* Search overlay (generated by `render_search_ui()`) */
.search-overlay { }
.search-input { }
.search-results { }

/* Shortcodes (in rich editor) */
.sc-callout { }
.sc-quote { }
.sc-btn { }
.sc-toc { }
.sc-grid { }

/* Galleries */
.gallery-grid { }
.gallery-masonry { }
.lightbox-trigger { }

/* Breadcrumbs */
.breadcrumbs { }

/* Contact form */
.contact-form { }
.contact-field { }
.contact-status { }

Shortcode CSS classes

Shortcode output uses sc- prefixed classes defined in shortcodes.css. Override them freely in your style.css:

ShortcodeWrapper class
[callout].sc-callout, .sc-callout--info, .sc-callout--warning, etc.
[quote].sc-quote
[button].sc-button, .sc-button--primary, .sc-button--secondary, .sc-button--outline
[columns] / [column].sc-columns, .sc-column

theme/functions.php load order

Your theme's functions.php is loaded after all CMS core files but before any template variables exist. You can use it to:

  • Register hooks and filters via add_theme_action() / add_theme_filter()
  • Enqueue additional stylesheets with add_theme_stylesheet()
  • Enqueue additional scripts with add_theme_script()
  • Pre-fetch and cache data in $GLOBALS

You cannot redefine CMS functions (PHP fatal) or access template variables like $item (not yet defined).

Use sl_load_index('article') for data access in functions.php, never $GLOBALS['data']['article'] — the data array is not yet populated at that point.


Additional stylesheets and scripts

style.css and script.js are injected automatically. For additional files:

// In theme/functions.php
add_theme_stylesheet('css/print.css');         // Injected in <head>
add_theme_script('js/animations.js');          // Injected before </body>
add_theme_script('js/polyfill.js', false);     // Injected in <head>

Paths are relative to your theme directory (theme/{name}/).