0

In my Vue application, I have a navigation drawer that contains a sticky header and content underneath it.
The content is quite long and I'd like to display a divider or a border between the header and the content.
I know a border-bottom on the "sticky-header" div would do it but I want to apply a bottom border to the header only when it becomes stuck (fixed at the top) not when the header is in the default form (relative position).

Below is my code-

<v-navigation-drawer
  v-if="drawerNodeData"
  class="nav-drawer"
  width="408px"
  dark
  color=#212121
  v-model="drawerNode"
  absolute
  temporary
>
  <div class="node-drawer">
    <div class="sticky_header">
      <div class="close-actor-panel">
        <span></span> <!-- To stick the close icon to the right -->
        <v-btn icon size="0.8em" @click.stop="drawerNode = false">
          <v-icon>mdi-close</v-icon>
        </v-btn>
      </div>
      <v-list-item class="title-and-nb-of-news">
        <span v-if="this.drawerNodeData" class="node-title">{{
          this.drawerNodeData.id.replaceAll("_", " ")
        }}</span>

        <div class="chip-for-news">
          <DrawerNewsModale
            :actorName.sync="actorName"
            :filteredNews.sync="filteredNews"
          ></DrawerNewsModale>
        </div>
      </v-list-item>
    </div>
    <div class="content"></div>
  </div>
</v-navigation-drawer>

Any idea how to detect if element is sticky or not so I can toggle the border accordingly?

Neha Soni
  • 3,935
  • 2
  • 10
  • 32
Quentin
  • 65
  • 9

1 Answers1

0

The IntersectionObserver interface of the Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.

So, A few lines of IntersectionObserver in JavaScript and tricky usage of top: -1px in the CSS could help to achieve this.

The Below code is containing a header and some content. When the page will be scrolled and the header will be stuck at the top, a bottom border will be applied to the header and when the header is not sticky anymore, the border class will be removed.

const el = document.querySelector(".sticky-element")
const observer = new IntersectionObserver( 
  ([e]) => e.target.classList.toggle("threshold-reached", e.intersectionRatio < 1),
  { threshold: [1] }
);

observer.observe(el);
#parent { 
  height: 2000px; 
}

.sticky-element {
  position: sticky;
  top: -1px;
  z-index: 1;
  background: yellow;
}

/* styles for when the header is in sticky mode */
.sticky-element.threshold-reached {
  border-bottom: 1px solid black;
}
<div id="parent">
  
  <br />
  <div class="sticky-element">Header</div>
  <div>Content</div>
  <div>Content</div>
  <div>Content</div>
  <div>Content</div>
  <div>Content</div>
  <div>Content</div>
  <div>Content</div>

</div>

Important- Read more about how this intersection API works.

Neha Soni
  • 3,935
  • 2
  • 10
  • 32