---
title: Notice Bar using Alpine.js and Tailwind CSS
date: 2022-04-03T11:49:00-04:00
author: cc_admin
canonical_url: "https://caffeinecreations.ca/blog/notice-bar-using-alpine-js-and-tailwind-css/"
section: Blog
---
![Alpine plus tailwind](https://caffeinecreations.ca/uploads/blog/_1920x660_crop_center-center_none_ns/alpine-plus-tailwind.jpg)

- [Web Development](https://caffeinecreations.ca/blog/category/web-development/), [Code](https://caffeinecreations.ca/blog/category/code/), [Tutorial](https://caffeinecreations.ca/blog/category/code/tutorial/)

# Notice Bar using Alpine.js and Tailwind CSS

I'm working on my [Craft CMS starter package](https://github.com/CreateSean/craft-starter) and expanding what it has baked in out of the box. I'm planning on adding in several features or components that are common across most sites. The first one I've added is a notice bar.

![Notice bar](https://caffeinecreations.ca/uploads/blog/_960xAUTO_fit_center-center_none_ns/notice-bar1.png)

This is quite simple to do with AlpineJS. It uses 2 first party Alpine JS plugins [Collapse](https://alpinejs.dev/plugins/collapse) and [Persist](https://alpinejs.dev/plugins/persist). The collapse plugin makes for a smooth hide animation when closing the notice bar.

In Craft I have an entry with three fields `Text` (redactor), `Button` (link field) and `Notice Bar Location` (select field). The text field is for copy, the button for a button and the location field sets whether the notice bar should appear on the homepage only or on all pages.

Here is the complete code.

```
<button class="absolute z-10 flex items-center justify-center w-8 h-8 -translate-y-1/2  -right-4 -top-4" clipboard="" title="Copy to Clipboard" to="" type="button" x-clipboard.raw="{% set notice = craft.entries.section('noticeBar').one() %}

{% if notice.enableNoticeBar == '1'
    and ( notice.noticeBarLocation !="homePageOnly" or ( entry.slug == '__home__' ) )
%}

  <div x-data="{ expanded: $persist(true).as('notice-bar').using(sessionStorage) }">
    <div
      class="shadow-inner drop-shadow bg-gradient-to-b from-gray-100 via-gray-50 to-gray-100"
      x-show="expanded"
      x-collapse.duration.300ms >
      <div class="container">
        <div class="relative flex flex-row items-center w-full mx-auto lg:w-5/6">
          <div class="py-4 grow">
            {{ notice.text|retcon([
                ['attr', 'p', { class: 'm-0 text-sm' }]
              ]) }}
          </div>
          {% if notice.button|length %}
            {{ notice.button.getLink({
                class: 'btn mx-8',
              }) }}
          {% endif %}
          <button
            class="absolute text-xs font-bold text-red-400 top-1 right-2"
            @click="expanded = ! expanded"
            aria-label="Close">
            X
          </button>

        </div><!-- /.w-full flex flex-row -->
      </div><!-- /.container -->
    </div>
  </div>

{% endif %}" x-data="">
	<svg class="h-5 w-5" viewbox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
  <rect fill="#f3f4f6" height="53" rx="3" width="41" x="7" y="2"></rect>
  <rect fill="#f3f4f6" height="51" rx="3" width="39" x="19" y="11"></rect>
  <path d="M53.98 9.143h-3.97c-.082 0-.155.028-.232.047V5.023C49.778 2.253 47.473 0 44.64 0H10.217C7.384 0 5.08 2.253 5.08 5.023v46.843c0 2.77 2.305 5.023 5.138 5.023h6.037v2.268c0 2.67 2.216 4.843 4.941 4.843H53.98c2.725 0 4.942-2.173 4.942-4.843v-45.17c0-2.671-2.217-4.844-4.942-4.844zM7.11 51.866V5.023c0-1.649 1.394-2.991 3.106-2.991H44.64c1.712 0 3.106 1.342 3.106 2.99v46.844c0 1.649-1.394 2.991-3.106 2.991H10.217c-1.712 0-3.106-1.342-3.106-2.99zm49.778 7.29c0 1.551-1.306 2.812-2.91 2.812H21.195c-1.604 0-2.91-1.26-2.91-2.811v-2.268H44.64c2.833 0 5.138-2.253 5.138-5.023V11.128c.077.018.15.047.233.047h3.968c1.604 0 2.91 1.26 2.91 2.811v45.17z"></path>
  <path d="M38.603 13.206H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 21.333H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 29.46H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM28.444 37.587h-12.19a1.015 1.015 0 1 0 0 2.032h12.19a1.015 1.015 0 1 0 0-2.032z"></path>
</svg>
<div class="sr-only">Copy to clipboard</div></button>```twig
{% set notice = craft.entries.section('noticeBar').one() %}

{% if notice.enableNoticeBar == '1'
    and ( notice.noticeBarLocation !="homePageOnly" or ( entry.slug == '__home__' ) )
%}

  <div x-data="{ expanded: $persist(true).as('notice-bar').using(sessionStorage) }">
    <div
      class="shadow-inner drop-shadow bg-gradient-to-b from-gray-100 via-gray-50 to-gray-100"
      x-show="expanded"
      x-collapse.duration.300ms >
      <div class="container">
        <div class="relative flex flex-row items-center w-full mx-auto lg:w-5/6">
          <div class="py-4 grow">
            {{ notice.text|retcon([
                ['attr', 'p', { class: 'm-0 text-sm' }]
              ]) }}
          </div>
          {% if notice.button|length %}
            {{ notice.button.getLink({
                class: 'btn mx-8',
              }) }}
          {% endif %}
          <button
            class="absolute text-xs font-bold text-red-400 top-1 right-2"
            @click="expanded = ! expanded"
            aria-label="Close">
            X
          </button>

        </div><!-- /.w-full flex flex-row -->
      </div><!-- /.container -->
    </div>
  </div>

{% endif %}
```
```

Originally I was going to set a cookie when the notice was closed and not display the notice again until the cookie expired. However it was simpler to use the AlpineJs persist plugin and set the persist state to use session storage so that the notice bar does display via the current session but will display on the next visit.

```
<button class="absolute z-10 flex items-center justify-center w-8 h-8 -translate-y-1/2  -right-4 -top-4" clipboard="" title="Copy to Clipboard" to="" type="button" x-clipboard.raw="x-data="{ expanded: $persist(true).as('notice-bar').using(sessionStorage) }"" x-data="">
	<svg class="h-5 w-5" viewbox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
  <rect fill="#f3f4f6" height="53" rx="3" width="41" x="7" y="2"></rect>
  <rect fill="#f3f4f6" height="51" rx="3" width="39" x="19" y="11"></rect>
  <path d="M53.98 9.143h-3.97c-.082 0-.155.028-.232.047V5.023C49.778 2.253 47.473 0 44.64 0H10.217C7.384 0 5.08 2.253 5.08 5.023v46.843c0 2.77 2.305 5.023 5.138 5.023h6.037v2.268c0 2.67 2.216 4.843 4.941 4.843H53.98c2.725 0 4.942-2.173 4.942-4.843v-45.17c0-2.671-2.217-4.844-4.942-4.844zM7.11 51.866V5.023c0-1.649 1.394-2.991 3.106-2.991H44.64c1.712 0 3.106 1.342 3.106 2.99v46.844c0 1.649-1.394 2.991-3.106 2.991H10.217c-1.712 0-3.106-1.342-3.106-2.99zm49.778 7.29c0 1.551-1.306 2.812-2.91 2.812H21.195c-1.604 0-2.91-1.26-2.91-2.811v-2.268H44.64c2.833 0 5.138-2.253 5.138-5.023V11.128c.077.018.15.047.233.047h3.968c1.604 0 2.91 1.26 2.91 2.811v45.17z"></path>
  <path d="M38.603 13.206H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 21.333H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM38.603 29.46H16.254a1.015 1.015 0 1 0 0 2.032h22.35a1.015 1.015 0 1 0 0-2.032zM28.444 37.587h-12.19a1.015 1.015 0 1 0 0 2.032h12.19a1.015 1.015 0 1 0 0-2.032z"></path>
</svg>
<div class="sr-only">Copy to clipboard</div></button>```html
x-data="{ expanded: $persist(true).as('notice-bar').using(sessionStorage) }"
```
```

In the above x-data I've added the `.as('notice-bar')` [custom key](https://alpinejs.dev/plugins/persist#custom-key) so that if I use persist anywhere else it will be a unique instance.

## More Articles

[![Using a Screen Reader Thumbnail](https://caffeinecreations.ca/uploads/blog/_680x320_crop_center-center_65_none_ns/accessibilty-hero1.jpg)### Using a Screen Reader](https://caffeinecreations.ca/blog/using-a-screen-reader/)

[![Reactive Pagination With Sprig and Craft Thumbnail](https://caffeinecreations.ca/uploads/blog/_680x320_crop_center-center_65_none_ns/sprig-hero.jpg)### Reactive Pagination With Sprig and Craft](https://caffeinecreations.ca/blog/reactive-pagination-with-sprig-and-craft/)

[![Browsersync Proxy URL from DOTENV file Thumbnail](https://caffeinecreations.ca/uploads/blog/_680x320_crop_center-center_65_none_ns/browsersync-proxy1.png)### Browsersync Proxy URL from DOTENV file](https://caffeinecreations.ca/blog/browsersync-proxy-url-from-dotenv-file/)
