Creating a Custom "Announcements" Bar for your Ghost Blog

I was redeveloping some of my themes and realized most themes don’t have a native announcements bar. While you could add one in using third party scripts (such as with HelloBar), it’s also really easy to make one yourself.

So I wrote it up! You can find the instructions here: How To Build a Custom Announcements Bar for Your Ghost Theme

This is easy to add in to any premade theme or into any custom theme. You can control the announcement bar copy/link via the admin panel, and the javascript includes persistence for if you close the bar… and how to bring it back if you change the content.


Feel free to adapt it for your own projects, or let me know any suggestions you would add.


Great article, thanks for sharing!

1 Like

Thanks @sharedphysics !
I found two bugs i think:

  • when I press the button to close the notification bar, it does not close 100%. It is caused by the “padding”, what is the correct CSS style in this case?

  • If I close the announcement bar with the button, and press F5, the web refreshes and the bar is open again.

My website so you can see the error

Thank you very much and great job.

@Joan - So for the first issue, you should move your id="announcementbar" from the <a> tag to the <div> that houses it. What’s happening is that you’re toggling the visibility of the thing with the id (in this case, the link), but the <div> is where you added in the styles, which is why it looks like that’s some residual padding after you close it. So if you move the ID to the div, you’re going to be closing and hiding that entire container. I’ll make that a bit more clear in the tutorial as well.

For the second issue, it looks like the onload event isn’t being called. That was my typo! It should be onload="checkBarCookie()" (was missing the ()).


Thanks for your quickly response @sharedphysics .
The two errors has solved! Thanks!!

1 Like


I don’t know if you could help me.
I want that when .hellobar is active in mobile view, it does NOT show the DIV .gh-head-brand-wrapper, .gh-head-menu. This way, it doesn’t overlap the hellobar with the Casper theme menu.
Is this possible? I have tried with this script but without success.

$(".gh-head-brand-wrapper, .gh-head-menu").hide();

I don’t know if with the “:Not” CSS attribute it could be done. I am a newbie.
Thanks… :slight_smile:

hey @sharedphysics really like your tutorial also can u tell us how you have customized your theme i mean your blog looks minimal and has a clear focus on content.

your theme is open source or we have to buy it :)

1 Like

Hi @Joan - I’m not 100% sure what you means by overlap because I’m not seeing that on mobile, but if you want to have different styles for mobile and desktop views you can use CSS Media Queries, I don’t think you need JavaScript for this. So for example:

@media only screen and (max-width: 600px) {
  .gh-head-brand-wrapper, .gh-head-menu {
@media only screen and (min-width: 600px) {
  .gh-head-brand-wrapper, .gh-head-menu {
    display: flex;

(These are just example breakpoints and CSS).

1 Like

Yeah @sharedphysics , your CSS works, but i want “display: none” only when Announcement Bar remains open. It’s possible this?

Thanks for all…!

@Achintpanchal1 - Thanks! I meant to write a tutorial for rebuilding my theme, but I never got around to it! You can use something like Edition or Dawn as a starting point and mostly focus on rewriting the homepage. It’s pretty straightforward, my homepage is just two get loops:

  • For the “about” portion above the fold, I created a new page with the internal tag #cover, then used a get loop to pull that in. This way I am able to edit the content like any other page. Here’s the basic code:
<div class="cover-content">
    {{#get "pages" limit="1" filter="tag:[hash-cover]" include="content"}}
        {{#foreach pages}}
  • For the list of posts, same thing but with a little bit more logic. I pulled in all of my posts and added some {{#if}} and {{#has}} flags to bring in icons for specific posts. Except for some fiddling around with the css to adjust mobile and desktop styles, it’s basically:
{{#get posts }}
{{#foreach posts}}
<div style="display:table-row;">
    <div style="display:table-cell;" class="loop-div">
        <span class="mobile-loop-show">
            {{#if featured}}⭑{{/if}}
            {{#has tag="[notebook]"}}<span style="font-size:1.2rem;">📓</span>{{/has}}
        </span> <a href="{{url}}" aria-label="{{title}}">{{title}}</a>
        <div class="mobile-loop-show">
            <br><span style="font-size: 1rem; color:grey;">{{date published_at format="MMMM DD, YYYY"}}</span>

Keeping it minimal means the code is extremely easy to write and update! That said, I haven’t released it as a theme because I take a really hacky approach to my own themes (funky uses of certain tags and messy html/css, mostly) which means anyone else using the theme either needs a lot of documentation or to rewrite some elements to work for them.

If you’re interested in modifying a theme, I wrote this as a personal reference but it might be useful to you as well: Three Different Types of Post Loops in Ghost

@Joan - Got it. I’m not sure if there is pure CSS that would handle that, but you can probably do it in javascript w/ some listeners. There’s a few edge cases there to work through, but your logic would basically be:

Case 0:

  • Default CSS if there is no bar (no javascript)

Case 1:

  • Onload listener for if bar = closed, set other class to display:flex; (or whatever it currently is)

Case 2:

  • Onload listener for if bar exists and is open (or no cookie set) and if screen is below X dimensions, then set the other class attribute to display:none;
  • Window event listener for if screen size changes to desktop, then modify css
  • Second window event listener for if screen size changes back to mobile, then modify css again
  • Onclick event to toggle class of other element when bar is closed

The only problem with onload events is that you get a brief flicker as it is handled when the body loads. You can set the script in the header, but then you’re introducing render-blocking javascript that needs to be processed before the html/css starts to load, and that adds a few ms in load time.

I’m not great at javascript, so this would take me a while to figure out, test, and write up… and I’m not sure if there’s a better way to handle it. You might have better luck trying to go through the stack overflow community for some more specific guidance!

1 Like

Thanks for your great help. I will investigate :slight_smile:

Good night @sharedphysics ,
Now I understand when you were referring to the brief flicker while loading the page when the announcementbar is closed. It has a duration of just a few milliseconds.
Is there no way to avoid it?

Finally, can your JS be modified so that when you click on the “hide” button it makes a .fadeout effect? Make it smoother.