Most Epic Win's front page and publishing system now has Dark Mode

Upgraded our publishing system last night and it came with a few free improvements I hadn’t banked on.

Ghost’s default theme (Casper :sunglasses:) has changed layout slightly and now has a “Dark Mode”.

Layout changes

Those writing articles will notice that the headline is more prominent, and the excerpt is now displayed as a subtitle right below the headline.

Bylines (the author) and avatar have been moved to the top, and the post image is now the fourth thing from the top (where it used to be the first thing).

I didn’t know how I felt about it at first, but it’s kinda grown on me in the past few hours.

Dark Mode

Casper also now has a Dark Mode, which it seems you will automagically get if you are using your operating system’s built-in dark theme.

It comes courtesy of new CSS voodoo in the form of a media query that checks a setting called “prefers-color-scheme”, as follows:

@media (prefers-color-scheme: dark) {
   style stuff

I’ve tested in a few browsers and it seems to work in Firefox, Chrome, and Safari. It does not work in Edge.

Opera is failing to download to my machine for some reason, but since it’s Chromium based I’d expect it to work.


Another interesting feature added to Ghost is Members.

This gives Ghost a built-in way to do subscriptions and pay-walls. From the official website:

  • Premium publications - create unique content that your audience can’t find anywhere else and offer premium memberships with recurring subscriptions.
  • Paid newsletters - Publish to email and the web at the same time with a native email newsletter feature, or integrate with your favourite tools.
  • New media - YouTube creators or Podcast producers can use Ghost to grow a list of paying members who subscribe to support their work.
  • Communities - Create comments sections and communities for logged in or paid-only members to foster engagement with your work.

I haven’t played with this yet, so I don’t know how it works exactly.

(Code warning) Making article comments “Dark Mode” friendly

This next part is fairly technical, so I’ve split it off from everything else. YE BE WARNED.

This is all pretty sweet, but created a small style headache for me because our comments are embedded from the forum. It does not yet automagically switch between light and dark modes.

When you don’t work in web development every day, you get rusty, but it was fun to wade back in to see if I could make the comments less garish on the dark mode of our fancy new website.

At first I messed around to see if I could style the comments from Discourse—which is in an iFrame—straight from Casper’s stylesheet.

This didn’t appear to be possible.

However, I remembered that our comments are pulled in using JavaScript. To make sure that my attempts at using Casper’s CSS weren’t failing because our Discourse iFrame is fetched using JavaScript, I tried some JavaScript of my own.

In the end, I found an example on W3Schools which looked like it would do the trick. I modified it like so:

var iframe = document.getElementById("discourse-embed-frame");
var discourse = (iframe.contentWindow || iframe.contentDocument);
if (discourse.document)discourse = discourse.document; = "#202228";

This also failed. When I tried running the script in my browser, it broke at if (discourse.document)discourse = discourse.document;, with the following error: “SecurityError: Permission denied to access property “document” on cross-origin object”.

This led me down an interesting rabbit-hole involving cross-site scripting attacks (XSS), and Cross Origin- Resource Sharing (CORS).

Our forum (Discourse) and our publishing system (Ghost) are on different subdomains, so cross-site scripting protections kick in.

I tried enabling CORS on the forum (you may have noticed a few seconds of downtime earlier), but it turns out that modern browsers don’t accept CORS headers anymore.

It just spits back another error: "Invalid X-Frame-Options: “ALLOWALL” header from “…”

Mercifully, Discourse includes options in its admin panel that lets me set Embedded CSS—style information that gets sent with the iFrame and which then gets used to display our comments section in articles.

What I was hoping for, was some way of figuring out whether someone was using the light or dark theme and then styling the comments accordingly. For now, it looks like I’ll have to make do with the Embedded CSS.


Just had a thought. It may be possible to use @media (prefers-color-scheme: dark) in the Embedded CSS.

I’ll give it a whirl another time… I kinda like the way my styling of the comment section turned out, so no need to change it for now.

(Code warning) Pretty comments in Dark and Light mode

I didn’t like the way Casper did the layout of our Discourse comments. They were too wide on Desktop, and any styles I applied either made them look disjointed, or made them blend into the background.

One of the cooler CSS tricks Ghost lets you use from inside the editor window, is placing images in your article that “break out” of the boundaries of the main text content.

These are called “full bleed images”.

I wanted to use this “full bleed” trick on the block containing our comments, so that I could give it a different background colour from the rest of the page. CSSTricks had me covered:

There are a few ways to do this, and CSS Tricks recommends the use of a media query. They also mention the use of the @supports CSS at-rule, which I tried out and ended up sticking with.

In the code below, #discourse-comments is a child of .post-full-comments

Variant 1

@supports(width:100vw) { /* Test that the browser supports 'vw' */
    .post-full-comments {
	max-width: 100vw;
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
	background-color: #222;

    #discourse-comments {
        max-width: 800px; /* Limit the comments to a reasonable width */
        margin: 0 auto; /* Center the comments in the window */

You can also substitute the margin definitions above with the following form, provided you know the width of the parent container:

.post-full-comments {
	margin-left: calc(-100vw / 2 + 1040px / 2)
	margin-right: calc(-100vw / 2 + 1040px / 2)

After messing around with the above, I found that using -99vw is more accurate. This is likely because the Casper stylesheet uses ‘vw’ shenanigans to set padding globally.

I did not test how this formulation of the calc() statement works when you resize the window. I’d imagine you’d have to put it in the same kind of media queries used by the theme to determine the width of the main content container.

Variant 2

In the end, this is the CSS I went with:

@supports(width:100vw) { /* Test that the browser supports "vw" */
    .post-full-comments {
        width: 100vw; /* Make container full width of the window */
        position: relative; /* Activate 'left' and 'right' */
        left: 50%; /* Push container to middle of window */
        margin-left: -50vw; /* Pull window back to the edge */
        right: 50%; /* In case direction: rtl is needed */
        margin-right: -50vw; /* In case direction: rtl is needed */
        margin-bottom: 0; /* Make container margin flush with footer */
        padding: 4vw; /* Replace whitespace deleted elsewhere*/
        background-color: #222; /* This is what it's all been for */

    #discourse-comments {
        max-width: 800px; /* Limit the comments to a reasonable width */
        margin: 0 auto; /* Center the comments in the window */

It looks great! I love it. Sorry, wanted to post yesterday but never got around to it.


I don’t really use dark mode.

But having the author on top makes sense.