Code injection
Restyle any part of Meridian by pasting a few lines of CSS into Ghost's Code injection box. Every major section and component has a stable, named handle, so your tweaks keep working after theme updates.
Want to nudge a colour, hide a section, or tighten some spacing without forking the theme? Meridian 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 on this page 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 the theme files directly is not safe: your changes are erased the next time you upload a new meridian.zip.)
The naming convention
Meridian labels its building blocks with a small, predictable set of HTML attributes — a naming convention you can reason about. Once you know the four words below, you can usually guess the hook for something instead of looking it up:
data-regionmarks a big structural area, like the site header, the article body, or the homepage hero. There's usually one of each per page.data-componentmarks a reusable unit that can appear many times, like a post card, a story link in a rail, or the pagination bar.data-varianttells apart flavours of the same component — for example a post card rendered as the bigheroversus a compactdenselist item.data-partmarks a piece inside a component or region — thetitle,kicker,excerpt,meta(byline/date),image, orread-time. These names are the same everywhere, so the headline of any story preview is[data-part="title"], whether it's an<h1>or a<p>. A few parts live outside story previews:rank(the position number in numbered rails),logo(the brand logo image), andwordmark(the text site title shown when there's no logo).
| Attribute | Means | How many | Example values |
|---|---|---|---|
data-region | a structural area | ~one per page | site-header, post-body, most-read-rail, lead-story, comments |
data-component | a repeating unit | many | post-card, story-link, story-card, pagination, newsletter-cta |
data-variant | a flavour of its host | paired | hero, dense, compact, editorial, next |
data-part | a piece inside the host | many | title, kicker, excerpt, meta, image, read-time, rank, logo, wordmark |
You compose these by nesting — region, then component (with its variant), then part — and you can scope the whole thing to one page type with a Ghost body class (shown in the next section).
To target any of them, use an attribute selector in CSS:
<style>
/* A structural region */
[data-region="post-body"] { font-size: 1.05rem; }
/* Every post card on the site */
[data-component="post-card"] { /* ... */ }
/* Only the hero-style post card */
[data-component="post-card"][data-variant="hero"] { /* ... */ }
/* The headline inside any post card, whatever element it uses */
[data-component="post-card"] [data-part="title"] { /* ... */ }
</style>What not to target
Meridian uses other data-* attributes internally — they wire up JavaScript or belong to Ghost itself — and those are not part of this styling API. Only the four above (data-region, data-component, data-variant, data-part) are a promise. Leave the rest alone, because they can change or disappear in any update:
- Theme machinery (drives Meridian's own scripts):
data-breaking-ticker,data-ticker-*,data-footer-nav-*,data-post-toolbar,data-reading-progress,data-toc-mount,data-favicon-fallback, and the like. - Page state on
<html>:data-color-scheme,data-palette,data-font-size. For dark-mode tweaks, use the.darkclass instead (shown later). - Ghost & libraries (owned by Ghost, not the theme):
data-portal,data-members-*,data-ghost-search,data-pswp-*.
A quick test: if the name reads like the four-word grammar — an area, a unit, a flavour, or a piece — it's fair game. If it reads like a wiring label (-toolbar, -mount, -track, portal), don't style against it.
Scope a change to one kind of page
Ghost adds a class to the <body> of every page that tells you what kind of page it is — home-template, post-template, page-template, tag-template, author-template, and error-template (plus paged on pages 2, 3, and so on). Combine that with a hook to scope a change to just one place:
<style>
/* The hero headline, but only on the homepage */
.home-template [data-component="post-card"][data-variant="hero"] h1 { /* ... */ }
/* Pagination, but only on tag archives */
.tag-template [data-component="pagination"] { /* ... */ }
</style>Reach the elements inside a region
The hooks mark the containers. To style something inside one, add a selector after the hook. For the parts of a story preview, prefer the data-part hook over a bare element selector — the heading level varies between layouts, but the part name doesn't:
<style>
[data-component="post-card"] [data-part="title"] { letter-spacing: -0.01em; } /* card headlines */
[data-component="post-card"] [data-part="image"] { border-radius: 4px; } /* card images */
[data-component="post-card"] [data-part="meta"] time { font-style: italic; } /* the date line */
</style>Inside the article body, Meridian renders the content Ghost's editor produces, which already has its own stable classes. Target those directly under [data-region="post-body"]:
<style>
[data-region="post-body"] .kg-image-card { /* images */ }
[data-region="post-body"] .kg-button-card { /* buttons */ }
[data-region="post-body"] blockquote { /* pull-quotes */ }
</style>Targeting parts of a story
Every story preview — the linked headline blocks in feeds, rails, grids, carousels, and "more to read" lists — is built from the same handful of parts, each with a data-part hook:
| Part | Hook | What it is |
|---|---|---|
| Title | [data-part="title"] | the headline link |
| Kicker | [data-part="kicker"] | the small primary-tag label above the title |
| Excerpt | [data-part="excerpt"] | the short summary / dek |
| Meta | [data-part="meta"] | the byline and/or date line |
| Image | [data-part="image"] | the thumbnail <figure> |
| Read time | [data-part="read-time"] | the "5 min read" label inside the meta line |
Because the names never change, you can restyle a part everywhere it appears with a single rule — no matter which heading level or element the layout happens to use:
<style>
/* Every story headline on the site */
[data-part="title"] { font-variation-settings: "wght" 620; }
</style>…or scope it to one region. To recolour just the headlines in the homepage "More to read" rail, combine the region with the part:
<style>
[data-region="most-read-rail"] [data-part="title"] {
color: var(--color-accent);
}
</style>Not every preview has every part — a text-only rail row has no image or excerpt — but when a part is present, it always carries the same hook.
A few parts live outside story previews, for the same convenience: [data-part="rank"] is the position number in numbered rails (the "More to read" list, some section rows), while [data-part="logo"] (the brand logo image) and [data-part="wordmark"] (the text site title, when there's no logo) appear in the masthead, the Compact header, and the hamburger menu. The menu is its own region — [data-region="menu"] — so you can size each place's logo on its own (see the logo snippets below).
Hook reference
Every targetable part of Meridian, grouped by where it lives. Pair any of these with a body class above to scope it to one page type.
Site-wide chrome
| Part of the page | Selector |
|---|---|
| Breaking-news ticker | [data-component="breaking-ticker"] |
| Site header (both styles) | [data-region="site-header"] |
| Editorial header only | [data-region="site-header"][data-variant="editorial"] |
| Compact header only | [data-region="site-header"][data-variant="compact"] |
| Masthead / nameplate | [data-region="masthead"] |
| Brand logo image | [data-part="logo"] |
| Site-title text (wordmark, no-logo sites) | [data-part="wordmark"] |
| Hamburger menu (off-canvas) | [data-region="menu"] |
| Primary sections nav | [data-region="primary-nav"] |
| Sign in / Subscribe links | [data-component="auth-links"] |
| Reading-progress bar | [data-component="reading-progress"] |
| Footer | [data-region="site-footer"] |
| Footer brand column | [data-component="footer-brand"] |
| Footer link columns | [data-region="footer-nav"] |
| Footer copyright row | [data-region="footer-legal"] |
| Advertisement slot (any) | [data-component="ad-slot"] |
| A specific ad position | [data-component="ad-slot"][data-variant="leaderboard"] (also in-feed, billboard, in-article, post-footer) |
| Bold section divider (the heavy 3px rule between sections) | [data-component="divider"][data-variant="section"] |
Homepage
| Part of the page | Selector |
|---|---|
| Front grid wrapper | [data-region="home-grid"] |
| Lead story column | [data-region="lead-story"] |
| Sub-leads under the lead | [data-region="sub-leads"] |
| Secondary stories column | [data-region="secondary-stories"] |
| Editor's note box | [data-component="editors-note"] |
| "More to read" rail | [data-region="most-read-rail"] |
| Editor's Picks carousel | [data-component="editors-picks"] |
| A homepage section row | [data-component="section-row"] |
| Carousel-style section row | [data-component="section-row"][data-variant="carousel"] |
| Feature-rail section row | [data-component="section-row"][data-variant="feature-rail"] |
| Tag-columns section row | [data-component="section-row"][data-variant="tag-columns"] |
| Sections page (topic hubs) | [data-region="sections-page"] |
| "From the archive" tail | [data-region="archive-tail"] |
Posts & pages
| Part of the page | Selector |
|---|---|
| Whole article | [data-region="post"] |
| Static page | [data-region="page"] |
| Post header block | [data-region="post-header"] |
| Byline + date line | [data-region="post-meta"] |
| Feature image | [data-region="feature-image"] |
| Feature-image caption (posts, pages & cards) | [data-component="image-caption"] |
| Article body | [data-region="post-body"] |
| Article action toolbar | [data-component="article-toolbar"] |
| Reader-preferences panel | [data-component="reader-panel"] |
| Sticky bar (after scroll) | [data-component="sticky-bar"] |
| Table of contents | [data-component="table-of-contents"] |
| Author card | [data-region="author-card"] |
| A single author block | [data-component="author"] |
| Comments section | [data-region="comments"] |
| Previous / next links | [data-component="post-navigation"] |
| Breadcrumb | [data-component="breadcrumb"] |
| Static page header | [data-region="page-header"] |
Recommendation rails (below a post)
| Part of the page | Selector |
|---|---|
| Latest articles | [data-component="latest-articles"] |
| Related coverage | [data-component="related-coverage"] |
| You may be interested in | [data-component="you-may-like"] |
| From this writer | [data-component="from-this-writer"] |
| Ghost recommendations | [data-component="recommendations"] |
Post cards
A post card is the linked story preview that appears in feeds, rails, and grids. Target all of them with [data-component="post-card"], or one style with a data-variant:
| Card style | Selector | Where it shows |
|---|---|---|
| Hero | [data-component="post-card"][data-variant="hero"] | Homepage lead story |
| Hero (split) | [data-component="post-card"][data-variant="hero-split"] | Top of archive pages |
| Feed | [data-component="post-card"][data-variant="feed"] | Default grid card |
| Horizontal | [data-component="post-card"][data-variant="horizontal"] | Wide image-left rows |
| Grid | [data-component="post-card"][data-variant="grid"] | Image-top cards in the homepage grid carousels (3- and 4-column) |
| Dense | [data-component="post-card"][data-variant="dense"] | Text-only rail items |
| Dense + thumb | [data-component="post-card"][data-variant="dense-thumb"] | Rail items with a thumbnail |
| Thumb row | [data-component="post-card"][data-variant="thumb-row"] | Recommendation grids |
Other story previews & their parts
Not every story preview is a post card. Compact list rows and a few hand-built cards carry their own component hook, and every preview exposes the same parts:
| Hook | Selector | Where it shows |
|---|---|---|
| Story link | [data-component="story-link"] | compact text rows in rails, related coverage, recommendations, and the "more to read" rail |
| Story card | [data-component="story-card"] | hand-built cards like Editor's Picks and some homepage section rows |
| Previous / next link | [data-component="post-nav-link"] | the links below a post (data-variant="next" and data-variant="prev") |
| Story part | [data-part="title"] | the headline of any preview (also kicker, excerpt, meta, image, read-time) |
Archives, members & CTAs
| Part of the page | Selector |
|---|---|
| Archive header | [data-region="archive-header"] |
| Desk filter chips | [data-component="archive-filters"] |
| Author archive header | [data-region="author-header"] |
| A post grid row | [data-component="post-grid"] (variants two-up, three-up, four-up) |
| Pagination bar | [data-component="pagination"] |
| Newsletter signup | [data-component="newsletter-cta"] |
| Membership band | [data-component="membership-cta"] |
| Member CTA (signed-out) | [data-component="member-cta"][data-variant="signup"] |
| 404 hero | [data-region="error-hero"] |
| 404 browse suggestions | [data-region="error-browse"] |
Common snippets
Paste any of these into Settings → Code injection → Site Header and click Save. They're grouped by what they change; click a snippet to expand it. Mix and match — keep the ones you want and delete the rest.
Check the settings first
Many look-and-feel choices are built into Meridian, so you don't need CSS for them: accent colour and heading/body fonts live in Ghost's Settings → Design & branding (see Brand), while default light/dark mode, background palette, header style, single-author bylines, the breaking-news ticker, and ads are theme settings (see Site-wide settings). Reach for Code injection only for tweaks the settings don't cover.
Brand & colours
Typography
To switch the heading or body typeface, use the font settings in Design & branding rather than CSS.
Header, logo & navigation
Hiding things
Layout & spacing
Dark mode
Mobile
Need something else? See the full handle reference above, or the Sections and Membership CTA guides for component context.
Targeting with JavaScript
The same handles work from JavaScript, which you can add in Settings → Code injection → Site Footer:
<script>
document.querySelectorAll('[data-component="post-card"]').forEach((card) => {
// do something with each card
});
</script>These handles are a promise
The data-region, data-component, data-variant, and data-part names on this page are a supported part of Meridian. We treat renaming or removing one as a breaking change, called out in the changelog — so the CSS you write today keeps working.
Troubleshooting
Find the handle for anything on the page
Not sure which hook to use? Right-click the thing you want to style and choose Inspect. In the panel that opens, look for the nearest tag with a data-region or data-component attribute — that's your selector.
My CSS isn't taking effect
Meridian's own styles are sometimes more specific than a plain selector. If your rule is being ignored, make the selector more specific (for example, lead with a page class like .post-template ...) or, as a last resort, add !important to the property. Also double-check you wrapped the CSS in <style> tags inside the Site Header box.
The snippet looks broken after pasting
Some editors silently turn straight quotes (") into "smart quotes" (" and "), which CSS doesn't understand. If a snippet stops working after you copied it from a document or chat, retype the quotes, or paste into a plain-text editor first so the quotes stay straight.
See also: Social Links for adding more social icons, and For developers if you'd rather fork the theme and edit the source.