Hook reference
Every stable data-* selector Signal exposes for Code injection — regions, components, variants, and parts — plus the protected names you must not rename.
The complete list of Signal's stable styling handles. These names don't change between theme updates, so you can build Code-injection CSS against them with confidence. See Code injection for how the system works.
Regions — data-region
A structural area, usually one per page.
| Value | Where |
|---|---|
site-header, masthead, primary-nav, mobile-nav | The header and its menus |
hero, hero-body | The homepage hero |
platforms | The "Watch & listen on" band |
featured-episodes, episode-feed | Homepage episode sections |
from-blog, blog-feed | The homepage "From the blog" band and the /blog/ index |
hosts, guests, guests-index, frequent-guests | Host & guest sections and the directory |
about, sponsors, membership | Homepage about / sponsors / support sections |
contact-hero, contact-reasons | The Contact page |
archive-header | The heading band on the /blog/, topic, and author archives |
post / page, page-body | An episode, a blog post, or a generic page |
post-header, post-media, post-body | The post header, the episode player area, and the body (post-media is episodes only) |
comments, newsletter | The comments and newsletter areas |
library, error / error-suggestions | The Library page and error pages |
site-footer, footer-nav | The footer |
Components — data-component
A reusable unit that can appear many times.
| Value | What |
|---|---|
episode-row, episode-card | Episode list rows and cards |
article-row, article-card | Blog-post rows and cards (the written-content counterparts of the episode ones) |
blog-byline, author-bio, more-from-blog | A blog post's byline, end-of-article author card, and related-articles row |
guest-card, host-card, guest-cta | People cards and the "be a guest" prompt |
author-socials, social-links | Social icon rows |
play-button | The play affordance |
platform-list | A listen-links mount |
sponsors, tier-list, tier-card | Sponsor logos and membership tiers |
contact-form, newsletter-cta | The contact and newsletter forms |
filter-chips, episode-tabs, pagination | Topic filters, episode tabs, pagination |
footer-brand, footer-legal | Footer blocks |
Variants — data-variant
A flavour of its host component or region.
| Host | Values |
|---|---|
hero | latest, podcast, host, listen, cinematic — the homepage hero layout (set by the Home hero setting) |
post | blog on a #blog written post; an episode carries no variant |
post-header | audio on #audio episodes, embed on #embed episodes; a default video episode header carries no variant |
archive-header | blog on the /blog/ index, tag on a topic archive |
error | 404 |
Parts — data-part
A piece inside a component or region. The core names are the same everywhere.
| Value | What |
|---|---|
title, kicker, excerpt, meta, image, read-time | The shared core (any preview, header, or card) |
logo, wordmark | The brand logo image and the brand link/text |
author, role, duration, episode-number | Episode and people details |
description | A row's summary line (episode and article rows) |
poster, transcript, chapters | The media poster and the transcript/chapters content |
Scoping a part
Parts repeat, so scope them to a region or component: [data-component="article-row"] [data-part="title"] targets only blog-row headlines, not every title on the page.
Protected hooks
These are theme-owned functional names that the player, transcript, Library, comments, and navigation depend on. You may read and style them, but renaming, moving, or removing them — or wrapping the player host — breaks playback, cross-page continuity, transcript seeking, the Library, or comments.
Don't build CSS that relies on changing these; treat them as read-only structure:
- Player:
#mp-player-host(and itsdata-mode/data-mp-position/data-mp-*attributes),#mp-live,#mp-progress,#main-content,.mp-focus-target. Never wrap or reparent the player host. - Media stage:
[data-mp-stage],data-mp-source-scope,data-mp-key,data-poster. - Transcript & chapters:
[data-transcript-empty]/-ready/-scroll/-search,[data-autoscroll-toggle],[data-chapters-empty]/-ready/-count/[data-chapters],[data-seek-seconds]. - Comments:
[data-lazy-comments-mount],[data-lazy-comments-template]. - Listen links:
[data-signal-platforms],[data-signal-listen-links],[data-signal-listen-section],[data-listen-built]. - Library:
[data-library-toggle],[data-library-widget]/-trigger/-panel/-tab/-list/-count,[data-library-page](and its post-hydration[data-hydrated]flag) /-section/-rows/-empty/-clear. - Navigation & state: the nav menu attributes,
[data-set-theme], the pre-hydration[data-nav-pending]gate on the header menu, and the[data-nav-collapsed]/[data-color-scheme]state on<html>(select on these, never override).
Pre-hydration guards (avoiding flash)
Signal is built to render cleanly on the very first paint, before its JavaScript runs. A few elements are therefore held by CSS until the scripts hydrate them, so they never flash in a half-finished state. Every guard is gated on the js class (added to <html> before paint, so a no-JS visitor always sees the full content) and released by a 2.5-second failsafe if the bundle ever fails to load — nothing can get stuck hidden.
| Held until hydrated | How it's held | Released by |
|---|---|---|
| Desktop header menu — the overflow "More" pass | [data-nav-pending] on the [data-region="primary-nav"] list → visibility: hidden | navigation.js, once it has measured the bar and built "More" |
Library empty states on /library/ | [data-library-page]:not([data-hydrated]) [data-library-empty] → display: none | library.js, once it has read your saved items |
| Below-the-fold sections | [data-reveal] → hidden until scrolled into view | reveal.js (IntersectionObserver) |
| Episode show-notes source blocks — raw transcript/chapter code and the duplicated media card | .js [data-component="episode-tabs"] .gh-content … → display: none | the player scripts, which lift them into the hero and tabs |
Don't force any of these visible from Code injection (for example visibility: visible on the pending nav, or display: block on [data-library-empty]). Overriding a guard re-introduces the exact flash it prevents — style the settled result instead.
Adding a hook
If you need a hook that isn't here, it can be added to the theme (and documented on this page). Renaming or removing an existing one is a breaking change. See For developers.
Code injection
Restyle any part of Signal with a few lines of CSS in Ghost's Code injection. Learn the stable data-* hooks, what's safe to target, and how to scope rules.
Common snippets
Ready-to-paste Code injection CSS for the most-requested Signal tweaks — resizing the logo, hiding a homepage section, and adjusting type.