Advanced

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.

Want to nudge a colour, hide a section, or resize your logo without forking the theme? Signal gives every major part of the page a stable handle you can target with a few lines of CSS. You paste that CSS once into Ghost's Code injection and it sticks, even when you update the theme.

No theme editing required

Everything in this guide is done through Ghost Admin → Settings → Code injection. You don't edit theme files, and you don't rebuild anything. Code injection survives theme updates, which is exactly why it's the safe place for custom CSS. (Editing theme files directly is not safe — your changes are erased the next time you upload a new signal.zip.)

This guide comes in four parts. This page teaches the system, and three companion pages cover fonts, the looking-up and the copy-pasting:

The naming convention

Signal labels its building blocks with a small, predictable set of HTML attributes. Once you know the four words below, you can usually guess the hook for something instead of looking it up:

  • data-region marks a big structural area — the site header, a homepage section, the episode body, the footer. Usually one of each per page.
  • data-component marks a reusable unit that can appear many times — an episode row, a guest card, the pagination bar.
  • data-variant tells apart flavours of the same thing — for example which homepage hero layout is in use, or an audio episode header versus the default video one.
  • data-part marks a piece inside a component or region — the title, kicker, excerpt, meta, image, plus Signal's own additions like logo, wordmark, poster, and people. These names are the same everywhere.

To target any of them, use an attribute selector in CSS:

<style>
  /* A structural region */
  [data-region="site-footer"] { font-size: 0.95rem; }

  /* Every episode row on the site */
  [data-component="episode-row"] { /* ... */ }

  /* The headline inside any episode row, whatever element it uses */
  [data-component="episode-row"] [data-part="title"] { /* ... */ }
</style>

You compose these by nesting — region, then component (with its variant), then part — and you can scope a rule to one area of the page so it doesn't leak elsewhere.

You rarely need !important

Code injection is added to the page after the theme's own stylesheet, and it sits outside the layers the theme organises its styles into. In practice that means your rules win over the theme's ordinary styling automatically, even when your selector looks simpler than the theme's. Start without !important; if a rule isn't applying, the cause is usually the property rather than the priority (setting max-height on something that already has a height, for example).

Two things you can't override, by design:

  • Anything the theme hides with the HTML hidden attribute. That's enforced at a level your CSS can't reach, so use the theme's own settings or page content to control those, not CSS.
  • A handful of layout rules the theme marks as essential, such as collapsing the desktop menu when Navigation style is set to Hamburger, and the mobile menu's own show and hide. Change those through the matching theme setting instead.

Add, don't rename

Some hooks are theme-owned functional names that the player, transcript, and Library depend on. You may safely read and style them, but don't rely on changing their values — and never try to rename or move them with CSS. The Hook reference marks which these are.