woshizilong / vue-use-fixed-header

:fire: Turn your boring fixed header into a smart, animated one with one line of code.

Home Page:https://vue-use-fixed-header.netlify.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

npm dependency-count GitHub Workflow Status GitHub Workflow Status GitHub Workflow Status

Vue Use Fixed Header

Turn your boring fixed header into a smart one with one line of code.


Demo: WebsiteExamples: Vue 3 - Nuxt 3


Features

  • Dead simple - Call a function and you're done whether you're SSR'ing or not
  • Lightweight - Just over 1kb without any dependency
  • Enjoyable - When scrolling down, the header is hidden, when scrolling up, the header is shown.
  • Powerful - Uses acceleration delta for both hiding and showing instead of fixed thresholds
  • User-centric - Behaves as your users expect on page load, scroll restoration, hovering, dropdown navigation, on top reached.
  • Smart - Functionalities are automatically enabled/disabled if your header turns from fixed/sticky to something else or it is hidden at different viewports
  • Flexible - Works with any scrolling container and with your own transition styles

Installation

pnpm add vue-use-fixed-header

Usage

Pass your header's template ref to useFixedHeader. Then style it as you normally would. That's it.

<script setup>
import { ref } from 'vue'
import { useFixedHeader } from 'vue-use-fixed-header'

const headerRef = ref(null)

useFixedHeader(headerRef)
</script>

<template>
   <header class="Header" ref="headerRef">
      <!-- Your content -->
   </header>
</template>

<style scoped>
.Header {
   position: fixed; /* or sticky */
   top: 0;
   /* Other styles... */
}
</style>

As long as your header position is set to fixed/sticky, it will behave as described in the features section.

⚠️ There's only one rule to respect: Do not apply any transition-related property since they're handled internally. See below how to customize them.


Automatic behavior toggling

On resize, useFixedHeader checks your header's position and display properties to determine whether its functionalities should be enabled or not.

Disabled means that the header will behave as you're not using the composable at all: no event listeners are attached and no additional styles are applied.

Different viewports

If at different viewports your header position is not fixed/sticky (or it is hidden), functionalities are automatically toggled when needed.

So feel free to have code like this:

.Header {
   position: fixed;
}

@media (max-width: 768px) {
   .Header {
      position: relative;
   }
}

@media (max-width: 375px) {
   .Header {
      display: none;
   }
}

It will just work as expected.

Advanced scenarios

Let's suppose your header in some pages is not fixed/sticky and you're using some reactive logic to style the position property.

You can pass a reactive source to the watch property of useFixedHeader to perform a check everytime the value changes:

<script setup>
const route = useRoute()

const headerRef = ref(null)

const isPricingPage = computed(() => route.name === 'Pricing')

useFixedHeader(headerRef, {
   watch: isPricingPage, // Will perform a check everytime the value changes
})
</script>

<template>
   <header ref="headerRef" :style="{ position: isPricingPage ? 'relative' : 'fixed' }">
      <!-- Your content -->
   </header>
</template>

useFixedHeader will automatically toggle functionalities when navigating to/from the Pricing page.

You can pass either a ref or a computed (without .value).


Customization

useFixedHeader(headerRef, {
   /**
    * Use `null` if content is scrolled by the window,
    * otherwise pass a custom scrolling container template ref */
   root: null,
   /**
    * ref or computed to watch for automatic behavior toggling */
   watch: () => null,
   /**
    * Minimum acceleration delta required to show the header */
   enterDelta: 0.5,
   /**
    * Minimum acceleration delta required to hide the header */
   leaveDelta: 0.15,
   /**
    * Custom enter transition styles */
   enterStyles: {
      transition: `transform 0.3s ease-out`,
      transform: 'translateY(0px)',
   },
   /**
    * Custom leave transition styles */
   leaveStyles: {
      transition: `transform 0.5s ease-out`,
      transform: 'translateY(-100%)',
   },
})

Accessibility - Reduced Motion

This is not done for you and must be implemented manually using prefers-reduced-motion media query:

@media (prefers-reduced-motion: reduce) {
   .Header {
      transition-duration: 0s;
      transition-delay: 0s;
   }
}

License

MIT Licensed - Simone Mastromattei © 2023

About

:fire: Turn your boring fixed header into a smart, animated one with one line of code.

https://vue-use-fixed-header.netlify.app


Languages

Language:TypeScript 83.7%Language:Vue 12.9%Language:HTML 3.1%Language:CSS 0.3%