Add a site-wide dismissible notice bar to your WordPress website

Global, site-wide website notices are a pattern as old as websites themselves, and although they are being abused all the time they do have valid use-cases and are extremely useful in situations where we absolutely need to notify our visitors of something important, e.g. a great deal (as we do here at CSSIgniter), any kind of maintenance message or even the EU cookie law notice!

When the need rises for such functionality the first thing on anyone’s mind would probably be to have a look at the WordPress plugin repo for any suitable plugins, and, well, although it’s justified (there are a ton of plugins for this kind of thing) there’s no reason not to implement it ourselves since it’s so easy and fun.

Without any further ado, then, let’s see how we’d go about building a simple, global, dismissible site-wide notice bar.

Our basic architecture

We’ll store our notice’s text as a simple WordPress Customizer setting, and then we’ll use some JavaScript tinkering to handle its display logic. Of course, we’ll also use some basic CSS to style it.

The customizer setting

All we need for our notice currently is a single text field. Ever since version 3.4 WordPress has made it extremely simple to add site settings to our websites with the Theme Customization API; a few lines of code in our theme’s functions.php file will do it:

<?php

add_action( 'customize_register', 'mytheme_customize_register' );

function mytheme_customize_register( $wp_customize ) {
	$wp_customize->add_section( 'mytheme_site_notice', array(
		'title'    => __( 'Site Notice', 'mytheme' ),
		'priority' => 30,
	) );

	$wp_customize->add_setting( 'site_notice_text', array(
		'default'           => '',
		'sanitize_callback' => 'wp_kses_post',
	) );

	$wp_customize->add_control( 'site_notice_text', array(
		'type'    => 'text',
		'section' => 'mytheme_site_notice',
		'label'   => __( 'Site notice text', 'mytheme' ),
	) );
}
functions.php

Save the file and refresh the website and now navigating to Appearance > Customize from the admin dashboard menu we should see a new Customizer section named “Site Notice”, and in it our site section text field, which should already be functional! Let’s type something and save it.

Displaying the site notice

Time to fetch that text and display it on the front-end of our website. Still in functions.php, we’ll use the wp_footer action to render all the HTML and text of our notice:


add_action( 'wp_footer', 'mytheme_site_notice' );

function mytheme_site_notice() {
	$text = get_theme_mod( 'site_notice_text', '' );

	if ( is_admin() || empty( $text ) ) {
		return;
	}
	?>
	<div
		class="site-notice"
		data-id="<?php echo esc_attr( md5( $text ) ); ?>"
	>
		<p><?php echo esc_html( $text ); ?></p>
		<button
			aria-label="<?php esc_html_e( 'Dismiss site notice', 'mytheme' ); ?>"
			class="site-notice-dismiss"
		>
			×
		</button>
	</div>
	<?php
}
functions.php

Pretty basic stuff, we’re getting the text using get_theme_mod and output the HTML only if it’s not empty (i.e. we haven’t written anything) or if we’re not at the WordPress admin dashboard.

Only one line needs a bit of explaining:

<div
	class="site-notice"
	data-id="<?php echo esc_attr( md5( $text ) ); ?>"
>
what's that md5 hash doing there?

What we’re doing here is assigning an identifier on our notice (the md5 hash of its text). Of course there are a lot of ways of doing this but this is simple and straightforward. It will also prevent us from accidentally displaying the same notice again a second consecutive time to users that have already dismissed it. Keep this on the back of your mind for now, we’ll pick it up later on with JavaScript and use it to figure out whether we should display the notice or not.

Adding some styles

For styling we’ll definitely need to make our notice bar absolute or fixed positioned so that it sticks to the top or bottom and/or follows the viewport as the user is scrolling (obviously this is a matter of preference, I’ll leave it up to you). Other than that, some aesthetic touches for coloring, and finally positioning the dismissing button:

.site-notice {
  font-family: sans-serif;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  padding: 15px 25px;
  background-color: #145474;
  color: #fff;
  text-align: center;
}

.site-notice-dismiss {
  background: none;
  border: 0;
  color: #fff;
  font-size: 24px;
  position: absolute;
  right: 15px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
}

And here’s how it’s going to look:

light

Handling the display logic

All righty, we’ve got the notice bar styled and displaying at the top of our website, but currently there’s no way for our users to dismiss it (and never see it again). We’ll need a bit of JavaScript to make this happen.

The general concept is based on leveraging the browser’s localStorage API to store the “ID” of the notice every time the user clicks on the dismiss button. We’ll always start with the notice hidden (via CSS) and on page load we’ll check (with JavaScript) if the ID matches with the one we have in localStorage. If it does, we’ll do nothing (keep it hidden), if it doesn’t we’ll show it! Simple enough, let’s see how we’ll go about it.

First, we’ll need to start with the notice bar hidden so let’s add that to our previous styles:

.site-notice {
  ...
  display: none;
  ...
}
style.css

Then the “tricky” part, in our theme’s custom scripts file:

(function () {
	var notice, noticeId, storedNoticeId, dismissButton;
	notice = document.querySelector('.site-notice');

	if (!notice) {
		return;
	}

	dismissButton = document.querySelector('.site-notice-dismiss');
	noticeId = notice.getAttribute('data-id');
	storedNoticeId = localStorage.getItem('myThemeSiteNotice');

	// This means that the user hasn't already dismissed
	// this specific notice. Let's display it.
	if (noticeId !== storedNoticeId) {
		notice.style.display = 'block';
	}

	dismissButton.addEventListener('click', function () {
		// Hide the notice
		notice.style.display = 'none';

		// Add the current id to localStorage
		localStorage.setItem('myThemeSiteNotice', noticeId);
	});
}());
scripts.js

Let’s go through the code line by line:

(function () {
  ...
}());
IIFE

Wrapping our whole code in an IIFE (Immediately Invoked Function Expression). Just as a good practice in order to keep our variables scoped and to be able to escape out of the whole logic if we need to by simply returning.

var notice, noticeId, storedNoticeId, dismissButton;
notice = document.querySelector('.site-notice');

if (!notice) {
	return;
}

Define our initial variables, get a DOM reference from our site notice HTML element and do nothing (return on line 5) if there’s no site notice to begin with (i.e. we haven’t set any text).

dismissButton = document.querySelector('.site-notice-dismiss');
noticeId = notice.getAttribute('data-id');
storedNoticeId = localStorage.getItem('myThemeSiteNotice');

We’re storing the DOM reference of our dismiss button (so that we can attach a click handler later on) and allocate the two IDs: noticeId is the current notice’s ID (the one that currently is in our document) and storedNoticeId is the one we’ve stored in localStorage from a previous dismiss click. storedNoticeId could be null if, for example, someone is visiting our website for the first time or has never dismissed any of our notices. That’s ok though!

if (noticeId !== storedNoticeId) {
  notice.style.display = 'block';
}
Determine if we should display the notice

Remember we always echo our notice’s HTML in the DOM (if there is any text assigned) and we initially just render it hidden via CSS.

By comparing what ID we’ve got stored in localStorage (storedNoticeId) with the current notice’s ID (noticeId) we can determine if the user has already dismissed this specific one, and if they haven’t, we show it.

dismissButton.addEventListener('click', function () {
  notice.style.display = 'none';
  localStorage.setItem('myThemeSiteNotice', noticeId);
});
Dismissing the notice

Finally the button’s click handler. It’s responsible for hiding the notice (via setting its display property to none) and storing its ID in localStorage. The next time we refresh this ID will be the storedNoticeId variable we mentioned and used before for the displaying logic.

Here’s how the full code looks and behaves (don’t blink or you’ll miss it – you can dismiss the notice and refresh the page, it won’t be there unless you change its ID):

light

And that’s about it! We have a fully functional, dismissible site-wide notice bar on our website ready to go. Building on top of what we just implemented we could also add functionality such as new customizer fields (i.e. images, setting custom colors) or even countdown timers and activation windows! If you happen to experiment with the code and enhance its functionality make sure to share with us in the comments below!

Subscribe to our newsletter.

Get fresh WordPress content straight into your inbox. We hate spam more than you do.

2 comments

  1. Great article. Can you explain why you are using localstorage as oppose to cookies?

    1. Vassilis Mastorostergios says:

      Thanks for the comment!

      No particular reason except for the simplicity localStorage provides for the context of a tutorial as a basis.

      Cookies are a good alternative for achieving the same functionality plus since they’re server-read you could do a bit more, like not echoing the markup at all if the notice is expired.

      It’s up to the curious mind to decide what they’re going to use (as always); in a larger, more complex application maybe this kind of state tracking could belong in a Redis store or a database!

Leave a Reply

Your email address will not be published. Required fields are marked *