# Directional List Hover

> List rows that reveal from the pointer’s entry edge — directional hover overlays for menus and content lists.

**Definition:** Directional List Hover is a hover UI animation from collections.html. It is built with HTML, CSS, JavaScript, and GSAP, ships with a live preview, and is free to copy into personal and commercial projects.

## Facts
- Category: Hover
- Stack: HTML, CSS, JavaScript, and GSAP
- Added: 2026-08-04
- Canonical page: https://html.bosconvertpro.com/collection/directional-list-hover
- Full-page preview: https://html.bosconvertpro.com/collection/directional-list-hover/full
- Live demo: https://html.bosconvertpro.com/demos/directional-list-hover/index.html
- Markdown mirror: https://html.bosconvertpro.com/collection/directional-list-hover/index.md
- License: https://html.bosconvertpro.com/terms

## How to use
1. Open https://html.bosconvertpro.com/collection/directional-list-hover/full to preview the animation in full screen.
2. Copy index.html, styles.css, and script.js from the code tabs on https://html.bosconvertpro.com/collection/directional-list-hover.
3. Paste the files into your project and adjust timing, easing, and content as needed.

## FAQ
### What is Directional List Hover?

Directional List Hover is a hover UI animation from collections.html. List rows that reveal from the pointer’s entry edge — directional hover overlays for menus and content lists.

### What is Directional List Hover built with?

Directional List Hover is built with HTML, CSS, JavaScript, and GSAP. The source for every file is shown on the animation page and can be copied straight into your project.

### How do I use Directional List Hover in my project?

Open the animation page (https://html.bosconvertpro.com/collection/directional-list-hover), preview it live, then copy index.html, styles.css, and script.js from the code tabs. Paste the files into your project and adjust timing, easing, and content as needed. A standalone demo runs at https://html.bosconvertpro.com/demos/directional-list-hover/index.html.

### Is Directional List Hover free to use?

Yes. The Directional List Hover demo code may be used in personal and commercial projects. You may not resell or redistribute the collection itself as a competing template pack. Full terms: https://html.bosconvertpro.com/terms.

## Source — index.html
````html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Directional List Hover</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <main class="page">
      <section class="showcase">
        <header class="showcase-header">
          <p class="showcase-eyebrow">Portfolio</p>
          <h1 class="showcase-title">Selected work</h1>
          <p class="showcase-subtitle">
            A curated set of brand, product, and digital experiences crafted
            with intention and precision.
          </p>
        </header>

        <div
          class="directional-list"
          data-directional-list
          data-axis="y"
          data-duration="0.5"
          data-ease="expo.out"
        >
          <div class="list-header">
            <div class="list-col list-col--project">
              <span class="list-label">Project</span>
            </div>
            <div class="list-col list-col--discipline">
              <span class="list-label">Discipline</span>
            </div>
            <div class="list-col list-col--year">
              <span class="list-label">Year</span>
            </div>
          </div>

          <div class="list-body">
            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Meridian Rebrand, Brand Identity, 2025"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Meridian Rebrand</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Brand Identity</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2025</p>
              </div>
            </a>

            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Northline Platform, Product Design, 2025"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Northline Platform</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Product Design</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2025</p>
              </div>
            </a>

            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Atelier Commerce, Digital Experience, 2024"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Atelier Commerce</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Digital Experience</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2024</p>
              </div>
            </a>

            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Lumen App Suite, Interface Design, 2024"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Lumen App Suite</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Interface Design</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2024</p>
              </div>
            </a>

            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Casa Editorial, Art Direction, 2023"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Casa Editorial</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Art Direction</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2023</p>
              </div>
            </a>

            <a
              class="list-row"
              data-list-row
              href="#"
              aria-label="Helix Motion Kit, Motion Design, 2023"
            >
              <div class="hover-tile" data-hover-tile></div>
              <div class="row-line row-line--top"></div>
              <div class="list-col list-col--project">
                <p class="row-text">Helix Motion Kit</p>
              </div>
              <div class="list-col list-col--discipline">
                <p class="row-text">Motion Design</p>
              </div>
              <div class="list-col list-col--year">
                <p class="row-text">2023</p>
              </div>
            </a>
          </div>

          <div class="list-footer-line"></div>
        </div>
      </section>
    </main>

    <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>
````

## Source — styles.css
````css
:root {
  --color-bg: #f4f1eb;
  --color-text: #1a1714;
  --color-text-soft: #5c564e;
  --color-text-muted: #9a9288;
  --color-tile: #ddd6cb;
  --color-border: rgba(26, 23, 20, 0.14);
  --color-accent: #a68b6a;
  --font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  --list-max-width: 72em;
  --page-pad-x: clamp(1.25rem, 4vw, 3rem);
  --page-pad-y: clamp(2.5rem, 8vh, 5rem);
  --tile-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --tile-duration: 0.5s;
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html,
body {
  width: 100%;
  min-height: 100%;
}

body {
  font-family: var(--font-family);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

.page {
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--page-pad-y) var(--page-pad-x);
  background:
    radial-gradient(ellipse 80% 60% at 50% 0%, rgba(255, 255, 255, 0.7), transparent 55%),
    radial-gradient(ellipse 50% 40% at 100% 100%, rgba(166, 139, 106, 0.08), transparent 50%),
    var(--color-bg);
}

.showcase {
  width: 100%;
  max-width: var(--list-max-width);
  display: flex;
  flex-direction: column;
  gap: clamp(2rem, 4vw, 3rem);
}

.showcase-header {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-width: 28rem;
}

.showcase-eyebrow {
  font-size: 0.75em;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent);
  line-height: 1;
}

.showcase-title {
  font-size: clamp(2rem, 4.5vw, 2.75rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--color-text);
}

.showcase-subtitle {
  font-size: 0.975rem;
  font-weight: 400;
  line-height: 1.55;
  color: var(--color-text-soft);
}

.directional-list {
  width: 100%;
  max-width: var(--list-max-width);
  display: flex;
  flex-flow: column;
  position: relative;
  color: var(--color-text);
}

.list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1em;
  width: 100%;
  padding: 0 1.5em 1.5em;
  position: relative;
}

.list-label {
  font-size: 0.75em;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent);
  line-height: 1;
}

.list-body {
  display: flex;
  flex-direction: column;
  width: 100%;
}

.list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1em;
  width: 100%;
  margin-top: -1px;
  padding: 2.25em 1.5em;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  color: inherit;
  text-decoration: none;
}

.list-col {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
}

.list-col--project {
  min-width: 30%;
  position: relative;
}

.list-col--discipline {
  flex: 1;
  position: relative;
}

.list-col--year {
  flex: none;
  min-width: 3em;
  position: relative;
  justify-content: flex-end;
}

.row-text {
  margin-bottom: 0;
  font-size: 1em;
  font-weight: 500;
  line-height: 1;
  color: var(--color-text);
  position: relative;
  z-index: 2;
}

.hover-tile {
  background-color: var(--color-tile);
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  pointer-events: none;
  will-change: transform;
  transform: translateY(-100%);
  transition: transform var(--tile-duration) var(--tile-ease);
}

.row-line {
  z-index: 2;
  opacity: 0.3;
  background-color: currentColor;
  width: 100%;
  height: 1px;
  position: absolute;
  left: 0;
  pointer-events: none;
}

.row-line--top {
  top: 0;
  bottom: auto;
}

.list-footer-line {
  z-index: 2;
  opacity: 0.3;
  background-color: currentColor;
  width: 100%;
  height: 1px;
  position: relative;
}

.list-row:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
  z-index: 4;
}

@media (max-width: 640px) {
  .list-header {
    padding: 0 1em 1em;
  }

  .list-row {
    padding: 1.75em 1em;
    gap: 0.75em;
  }

  .list-col--project {
    min-width: 42%;
  }

  .list-col--discipline {
    display: none;
  }

  .list-header .list-col--discipline {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hover-tile {
    transition-duration: 0.01ms !important;
  }
}
````

## Source — script.js
````javascript
(function () {
  "use strict";

  const DIRECTION_MAP = {
    top: "translateY(-100%)",
    bottom: "translateY(100%)",
    left: "translateX(-100%)",
    right: "translateX(100%)",
  };

  function getDirection(event, element, axis) {
    const rect = element.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;
    const width = rect.width;
    const height = rect.height;

    if (axis === "y") {
      return y < height / 2 ? "top" : "bottom";
    }

    if (axis === "x") {
      return x < width / 2 ? "left" : "right";
    }

    const distances = {
      top: y,
      right: width - x,
      bottom: height - y,
      left: x,
    };

    return Object.entries(distances).reduce(function (closest, current) {
      return current[1] < closest[1] ? current : closest;
    })[0];
  }

  function initDirectionalList(container) {
    const axis = container.getAttribute("data-axis") || "y";
    const rows = container.querySelectorAll("[data-list-row]");

    rows.forEach(function (row) {
      const tile = row.querySelector("[data-hover-tile]");

      if (!tile) return;

      row.addEventListener("mouseenter", function (event) {
        const direction = getDirection(event, row, axis);

        tile.style.transition = "none";
        tile.style.transform = DIRECTION_MAP[direction] || DIRECTION_MAP.top;
        void tile.offsetHeight;
        tile.style.transition = "";
        tile.style.transform = "translate(0%, 0%)";

        row.setAttribute("data-status", "enter-" + direction);
      });

      row.addEventListener("mouseleave", function (event) {
        const direction = getDirection(event, row, axis);

        row.setAttribute("data-status", "leave-" + direction);
        tile.style.transform = DIRECTION_MAP[direction] || DIRECTION_MAP.top;
      });

      row.addEventListener("focus", function () {
        tile.style.transition = "none";
        tile.style.transform = DIRECTION_MAP.top;
        void tile.offsetHeight;
        tile.style.transition = "";
        tile.style.transform = "translate(0%, 0%)";

        row.setAttribute("data-status", "enter-top");
      });

      row.addEventListener("blur", function () {
        row.setAttribute("data-status", "leave-top");
        tile.style.transform = DIRECTION_MAP.top;
      });
    });
  }

  function boot() {
    document.querySelectorAll("[data-directional-list]").forEach(initDirectionalList);
  }

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", boot);
  } else {
    boot();
  }
})();
````
