WebDevChallenges Logo

Implement a nice looking lightweight cookie consent

Updated June 13, 21
There are cookie consent solutions available that are easy to implement but they lack a few things that are important to me, here's what I did

Cookie consent banners are ugly and annoying. But you are required by law to implement one if you use any cookies that are non essential to the functionality of your site.

I noticed, that my blog was missing a cookie consent solution. I researched a little and came to the conclusion to implement the solution myself. There were two reasons for that:

  • Existing solutions require you to add a js bundle to your site which I do not want because I want to avoid bloat / keep performance high
  • I want to make it as easy as possible to accept the consent, place the “Accept” button in the (horizontal) center of the mobile screen where it is easy to reach with your thumb. Also I want a small button but a big “hitbox” so you don’t miss that button on mobile


Cookie Consent Desktop

Mobile (iPhone XR)

Cookie Consent Mobile

The solution

The HTML part simply renders the cookie consent element fixed at the bottom and adds a class (cookie-consent) to it. I use Tailwind for styling but it should be easy to translate these classes into pure CSS if you’re interested in that.

Inside of the cookie consent element, we have the text as first “pseudo element” and the second element is the wrapper around the button. That wrapper has the data-behavior="accept-cookie-consent" attribute set which we later use in JavaScript to register the click handler. This wrapper allows us to add some padding around the button and make the “hitbox” bigger than the actual size of the button.

These Tailwind classes result in a layout that places the button in the horizontal center and vertically above the text on mobile screens. That way it’s easy to reach with your thumb. On bigger resolutions, the button is to the right of the text as you can see in the images above.

<div class="fixed left-0 bottom-0 right-0 px-4 pt-2 pb-4 md:py-2 bg-blue-100 z-10 border-t border-blue-700 text-center flex flex-col-reverse md:flex-row items-center justify-center" id="cookie-consent">
  Cookies help to deliver this service. By using this site, you agree to this site's use of cookies.
  <div class="cursor-pointer px-6 pt-2 pb-4 md:px-0 md:pt-0 md:pb-0" data-behavior="accept-cookie-consent">
    <button class="md:mb-0 ml-0 md:ml-4 px-3 py-1 rounded-lg bg-blue-200">Okay</button>

The JavaScript part simply queries all [data-behavior="accept-cookie-consent"] elements once the DOM content is loaded, it then registers click listeners for these elements. Once this element is clicked, a cookie gets set and the cookie consent element gets hidden.

Make sure you set the expires flag for the cookie explicitly. Otherwise the cookie automatically expires when the session ends e.g. when you close your browser. In this case, we set the expiration date to a year from now.

  document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('[data-behavior="accept-cookie-consent"]').forEach(element => {
      element.addEventListener('click', () => {
        const expirationDate = new Date();
        expirationDate.setFullYear(expirationDate.getFullYear() + 1);
        document.cookie = 'cookie_consent_accepted=true; path=/; expires=' + expirationDate.toUTCString();

Hiding the cookie consent on page load

If you’re developing a client side rendered application you need to determine if the user has accepted the cookie consent in your JavaScript code and then based on that value either show or hide the cookie consent. Here’s how you can read cookies in JavaScript

Thankfully though, my application is Server rendered. That means, whenever a user requests a page, the user’s client (the browser) sends all cookies to the backend. The backend then can check if the cookie_consent_accepted cookie is present and truthy. If that’s the case, the backend simply does not render the cookie consent and also doesn’t render the associated JavaScript code.