JavaScript mouse-tracking Glow Effect with Tailwind CSS
Tags: javascript, tailwindcss, css
Published: 2024-03-05 19:29:57

---
title: JavaScript mouse-tracking Glow Effect with Tailwind CSS
published: true
date: 2024-01-16 21:13:58 UTC
tags: javascript, tailwind, css
canonical_url: https://webcrunch.com/posts/mouse-tracking-glow-effect-tailwind-css
---

{% youtube 2Cp9ECsQZ_Y %}

In this Tailwind CSS tutorial, we'll explore how to add an interactive, mouse-tracking glow effect to web elements using just JavaScript and Tailwind CSS. This simple yet eye-catching effect will enhance the user experience on your webpage.

**Prerequisites:**

- Basic knowledge of HTML, CSS, and JavaScript.
- Tailwind CSS installed in your project.

## Setting up a project

[I like to use vite.js for projects like this,](https://vitejs.dev/)but you could easily use something else. Vite has built-in support for many things, so it’s more efficient for me to test out new ideas and create tutorials such as this one.

You can reference the [docs](https://vitejs.dev/guide/#scaffolding-your-first-vite-project) or follow along as I create a new project. I used [bun](https://bun.sh) for package management and vanilla JavaScript to keep things simple. Be sure to remove all the boilerplate Vite.js installs when scaffolding a project.

```bash
bunx create-vite # go through the wizard, then cd into your project
```

### Install Tailwind CSS

Tailwind has some dependencies, so we’ll install those using bun. These are saved as dev dependencies because the `-d` flag passed. You can confirm inside your `package.json` file post-install.

```bash
bun add tailwindcss postcss autoprefixer @tailwindcss/typography -d
```

Next, we need to generate a tailwind configuration and postcss configuration file. This can be done with the following:

```bash
bunx tailwindcss init -p
```

Add the default Tailwind styles to your stylesheet.

```css
/* style.css */

@tailwind base;
@tailwind components;
@tailwind utilities;
```

Finally, you can boot your server running:

```bash
bun dev
```

I updated the default `tailwind.config.js` file to the following for this tutorial. You will want to add directories of files possibly. [Read the docs](https://tailwindcss.com/docs/content-configuration) for more information.

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: ["index.html"],
  theme: {
    extend: {},
  },
  plugins: [require("@tailwindcss/typography")],
}
```

### Initial HTML Structure

To make the glow effect more impactful, we can create a custom card that would benefit from the effect in the first place. I chose tropical fish.

You can start by creating a basic HTML structure. Here, we have a `div` containing a heading, paragraph, and button, wrapped in a parent `div` with the class `glow-capture.`

```html
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Create a custom mouse tracking Glow Effect with Tailwind CSS</title>
</head>

<body class="bg-zinc-950 text-zinc-50 antialiased h-screen">
  <div class="max-w-3xl mx-auto px-4 space-y-12 pb-32 pt-16 mt-10 mb-24">
    <!-- Fish 1 -->
    <div class="relative glow-capture">
       <div
        class="group bg-zinc-900/50 border-4 border-white/5 rounded-2xl p-10 shadow-lg shadow-black/80 flex md:flex-row flex-col flex-wrap md:items-start items-center md:justify-between justify-center gap-6 backdrop-blur-md">
        <div class="flex-1 md:order-1 order-2">
          <p class="opacity-50">Tropical fish</p>
          <h2 class="font-bold text-4xl tracking-tighter mb-3">Banana Wrasse</h2>
             <div class="md:prose-base prose-lg prose-zinc prose-invert text-opacity-90">
            <p>The Banana Wrasse is known for its vibrant yellow color and elongated body, resembling a banana.</p>
            <p>This active and playful fish thrives in tropical reef environments, often seen darting among corals and
              rocks.</p>
          </div>

          <button class="font-semibold px-6 bg-zinc-950/50 backdrop-blur-md py-3 rounded-xl text-white/90 border-2 border-white/10 mt-6">Learn more</button>
        </div>
         <img src="fish-1.jpg" alt="Banana Wrasse" class="max-w-sm rounded-full object-cover w-40 h-40 border-4 border-white/5 md:order-2 order-1 shadow-inner" />
      </div>
      <div class="glow-overlay" style="--glow-color: #7c3aed"></div>
    </div>
  </div>
</body>
```

I’ll start with one section that focuses on one fish for now. We can then duplicate the code and swap some colors, images, and content.

You’ll see some custom classes, such as `glow-capture` and `glow-overlay`. These will come in handy when we define some JavaScript and extend Tailwind.

Let’s tackle the CSS first.

## Styling with Tailwind CSS

Add the following styles for the `.glow-overlay` class. These styles create the base for our glow effect. You can leverage the `@apply` logic with Tailwind CSS here. I kept this code traditional CSS for now.

We use `mask` and pass a `radial-gradient` method. It's a fancy way to make gradients that aren't the simpler gradients you might be used to. Read more about [masks](https://developer.mozilla.org/en-US/docs/Web/CSS/mask) and [radial gradients](https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient) on mdn.

```css
.glow-overlay {
  --glow-size: 25rem;
  position: absolute;
  inset: 0;
  pointer-events: none;
  user-select: none;
  opacity: var(--glow-opacity, 0);
  mask: radial-gradient(
    var(--glow-size) var(--glow-size) at var(--glow-x) var(--glow-y),
    var(--glow-color) 1%,
    transparent 50%
  );
  transition: 400ms mask ease;
  will-change: mask;
}
```

## Extend Tailwind

We need to extend Tailwind to have a new variant called `glow`. Read more about [plugins](https://tailwindcss.com/docs/plugins#overview) and [adding variants](https://tailwindcss.com/docs/plugins#adding-variants) on the Tailwind CSS documentation.

Here’s my revised `tailwind.config.js` file.

```javascript
/** @type {import('tailwindcss').Config} */

const plugin = require("tailwindcss/plugin")

export default {
  content: ["index.html"],
  theme: {
    extend: {},
  },
  plugins: [
    require("@tailwindcss/typography"),
    plugin(
      function ({ addVariant }) {
        addVariant("glow", ".glow-capture .glow-overlay &")
      },
      {
        theme: {
          extend: {
            colors: {
              glow: "color-mix(in srgb, var(--glow-color) calc(<alpha-value> * 100%), transparent)",
            },
          },
        },
      }
    ),
  ],
}
```

The code uses the `plugin` extension of the Tailwind CSS library. We pass a new variant called `glow`, which targets elements within the `glow-capture` and `glow-overlay` classes. The `&` sign acts as a placeholder.

Finally, with the new variant, we can extend the theme based on its usage. To do so, we use the color-mix property in CSS, leveraging the `—-glow-color` CSS variable that gets defined in our HTML and later manipulated with JavaScript.

## Add JavaScript for Mouse Tracking

Write a JavaScript function to track the mouse movement and apply the glow effect. This code listens for mouse movement over the `.glow-capture` element and updates CSS variables to move the glow effect.

```javascript
/* main.js */

import "./style.css"

document.addEventListener("DOMContentLoaded", () => {
  const captures = document.querySelectorAll(".glow-capture")

  captures.forEach((capture) => {
    // Clone a child element. For example, we can clone the first child.
    const clonedChild = capture.children[0].cloneNode(true)
    const overlay = capture.querySelector(".glow-overlay")

    // Append the cloned child to the overlay.
    overlay.appendChild(clonedChild)

    capture.addEventListener("mousemove", (event) => {
      const x = event.pageX - capture.offsetLeft
      const y = event.pageY - capture.offsetTop

      overlay.style.setProperty("--glow-x", `${x}px`)
      overlay.style.setProperty("--glow-y", `${y}px`)
      overlay.style.setProperty("--glow-opacity", "1")
    })

    // Add mouseleave event to remove the glow effect
    capture.addEventListener("mouseleave", () => {
      overlay.style.setProperty("--glow-opacity", "0")
    })
  })
})
```

In my Vite project, a `main.js` file is the default entry point. I'm just chucking this code there. We do quite a few things in this file:

1. Listed first for the `DOMContentLoaded` event and then proceed
2. Find all elements with the `.glow-capture` class
3. Loop through each element with the `.glow-capture` class and clone it.
4. The overlay div added in our HTML gets a new child element which effectively doubles our original fish card.
5. On the individual card, we listen for both the `mousemove` and `mouseleave` events, setting custom CSS styles based on the mouse `x` and `y` position. If you leave the card with your mouse, we remove opacity, so you can't see the "glow” effect.

### Adding the new glow variant classes

Here’s where it gets fun. Because we introduced the new Tailwind CSS variant called `glow`, we can target elements within the card to change as we navigate the card with our mouse. You can apply the variants like any other Tailwind CSS variants.

```html
<!-- Fish 1 -->
    <div class="relative glow-capture">
      <div
        class="group bg-zinc-900/50 border-4 border-white/5 rounded-2xl p-10 shadow-lg shadow-black/80 flex md:flex-row flex-col flex-wrap md:items-start items-center md:justify-between justify-center gap-6 backdrop-blur-md glow glow:ring-1 glow:border-glow glow:ring-glow glow:bg-glow/[.15]">
        <div class="flex-1 md:order-1 order-2">
          <p class="opacity-50">Tropical fish</p>
          <h2 class="font-bold text-4xl tracking-tighter mb-3 glow:text-glow/[.15]">Banana Wrasse</h2>
          <div class="md:prose-base prose-lg prose-zinc prose-invert text-opacity-90">
            <p>The Banana Wrasse is known for its vibrant yellow color and elongated body, resembling a banana.</p>
            <p>This active and playful fish thrives in tropical reef environments, often seen darting among corals and
              rocks.</p>
          </div>

          <button
            class="font-semibold px-6 bg-zinc-950/50 backdrop-blur-md py-3 rounded-xl text-white/90 border-2 border-white/10 mt-6 glow:ring-1 glow:border-glow glow:ring-glow">Learn
            more</button>
        </div>

        <img src="fish-1.jpg" alt="Banana Wrasse"
          class="max-w-sm rounded-full object-cover w-40 h-40 border-4 border-white/5 md:order-2 order-1 glow glow:ring-1 glow:border-glow/[.5] glow:ring-glow shadow-inner" />
      </div>
      <div class="glow-overlay" style="--glow-color: #7c3aed"></div>
    </div>
```

Here I’ve applied it to the card, title, button, and fish image to produce a neat effect based on the `—glow-color` variable passed to the div with the class `glow-overlay` .

## Add more fish to the mix

Here’s my entire HTML file:

```html
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Create a Mouse Tracking Glow Effect with Tailwind CSS</title>
</head>

<body class="bg-zinc-950 text-zinc-50 antialiased h-screen">
  <div class="max-w-3xl mx-auto px-4 space-y-12 pb-32 pt-16 mt-10 mb-24">
    <!-- Fish 1 -->
    <div class="relative glow-capture">
      <div
        class="group bg-zinc-900/50 border-4 border-white/5 rounded-2xl p-10 shadow-lg shadow-black/80 flex md:flex-row flex-col flex-wrap md:items-start items-center md:justify-between justify-center gap-6 backdrop-blur-md glow glow:ring-1 glow:border-glow glow:ring-glow glow:bg-glow/[.15]">
        <div class="flex-1 md:order-1 order-2">
          <p class="opacity-50">Tropical fish</p>
          <h2 class="font-bold text-4xl tracking-tighter mb-3 glow:text-glow/[.15]">Banana Wrasse</h2>
          <div class="md:prose-base prose-lg prose-zinc prose-invert text-opacity-90">
            <p>The Banana Wrasse is known for its vibrant yellow color and elongated body, resembling a banana.</p>
            <p>This active and playful fish thrives in tropical reef environments, often seen darting among corals and
              rocks.</p>
          </div>

          <button
            class="font-semibold px-6 bg-zinc-950/50 backdrop-blur-md py-3 rounded-xl text-white/90 border-2 border-white/10 mt-6 glow:ring-1 glow:border-glow glow:ring-glow">Learn
            more</button>
        </div>

        <img src="fish-1.jpg" alt="Banana Wrasse"
          class="max-w-sm rounded-full object-cover w-40 h-40 border-4 border-white/5 md:order-2 order-1 glow glow:ring-1 glow:border-glow/[.5] glow:ring-glow shadow-inner" />
      </div>
      <div class="glow-overlay" style="--glow-color: #7c3aed"></div>
    </div>

    <!-- Fish 2 -->
    <div class="relative glow-capture">
      <div
        class="bg-zinc-900/50 border-4 border-white/5 rounded-2xl p-10 shadow-lg shadow-black/80 flex md:flex-row flex-col flex-wrap md:items-start items-center md:justify-between justify-center gap-6 backdrop-blur-md glow glow:ring-1 glow:border-glow glow:ring-glow glow:bg-glow/[.15]">
        <div class="flex-1 md:order-1 order-2">
          <p class="opacity-50">Tropical fish</p>
          <h2 class="font-bold text-4xl tracking-tighter mb-3 glow:text-glow/[.15]">Anthia</h2>
          <div class="md:prose-base prose-lg prose-zinc prose-invert text-opacity-90">
            <p>Anthias fish are renowned for their dazzling, multi-hued scales, ranging from pinks and purples to
              oranges
              and yellows.</p>
            <p>
              They form dynamic, shimmering schools in coral reefs, adding a burst of color and life to the underwater
              world.</p>
          </div>
          <button
            class="font-semibold px-6 bg-zinc-950/50 backdrop-blur-md py-3 rounded-xl text-white/90 border-2 border-white/10 mt-6 glow:ring-1 glow:border-glow glow:ring-glow">Learn
            more</button>
        </div>

        <img src="fish-2.jpg" alt="Banana Wrasse"
          class="max-w-sm rounded-full object-cover w-40 h-40 border-4 border-white/5 md:order-2 order-1 glow glow:ring-1 glow:border-glow/[.5] glow:ring-glow shadow-inner" />
      </div>
      <div class="glow-overlay" style="--glow-color: #f43f5e"></div>
    </div>

    <!-- Fish 3 -->
    <div class="relative glow-capture">
      <div
        class="bg-zinc-900/50 border-4 border-white/5 rounded-2xl p-10 shadow-lg shadow-black/80 flex md:flex-row flex-col flex-wrap md:items-start items-center md:justify-between justify-center gap-6 backdrop-blur-md glow glow:ring-1 glow:border-glow glow:ring-glow glow:bg-glow/[.15]">
        <div class="flex-1 md:order-1 order-2">
          <p class="opacity-50">Tropical fish</p>
          <h2 class="font-bold text-4xl tracking-tighter mb-3 glow:text-glow/[.15]">Lipstick Tang</h2>
          <div class="md:prose-base prose-lg prose-zinc prose-invert text-opacity-90">
            <p>The Lipstick Tang, distinct for its striking blue body and vivid red-orange lips, resembles a vibrant
              splash
              of lipstick
              in the ocean. </p>
            <p>This eye-catching fish is a favorite among reef enthusiasts, gracefully navigating through coral
              gardens
              with elegance.</p>
          </div>
          <button
            class="font-semibold px-6 bg-zinc-950/50 backdrop-blur-md py-3 rounded-xl text-white/90 border-2 border-white/10 mt-6 glow:ring-1 glow:border-glow glow:ring-glow">Learn
            more</button>
        </div>

        <img src="fish-3.jpg" alt="Banana Wrasse"
          class="max-w-sm rounded-full object-cover w-40 h-40 border-4 border-white/5 md:order-2 order-1 glow glow:ring-1 glow:border-glow/[.5] glow:ring-glow shadow-inner" />
      </div>
      <div class="glow-overlay" style="--glow-color: #0ea5e9"></div>
    </div>

    <div class="text-sm text-white/60 text-center">
      <a href="https://webcrunch.com" target="_blank">webcrunch.com</a>
    </div>
  </div>

  <script type="module" src="/main.js"></script>
</body>

</html>
```

## The end result

The end result is super cool! I love this effect. We’re tricking ourselves visually with the by cloning the cards and using more modern CSS to make a neat glow effect.

One limitation I discovered is the ability to do any major transition or transform effects. Because the element is cloned it looks way off if you attempt it.

From here you can experiment with different glow colors, sizes, and transition effects to personalize the glow effect for your own needs.

I hope you found this tutorial useful. If you enjoyed it be sure to share the link with your friends.

### You might also enjoy these articles

- [How I Create Tailwind CSS Plugins From Scratch](https://dev.to/justalever/how-i-create-tailwind-css-plugins-from-scratch-3dfm-temp-slug-1481899)
- [Code a mega menu with Tailwind CSS](https://webcrunch.com/posts/code-a-mega-menu-with-tailwind-css)
- [Re-create Airbnb's Home Page with Tailwind CSS](https://webcrunch.com/posts/re-create-airbnbs-home-page-with-tailwind-css)