Skip to content

Instantly share code, notes, and snippets.

@JamieCurnow
Created October 28, 2021 12:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JamieCurnow/ebd7f4991f9434824f3a1d5eb62b503e to your computer and use it in GitHub Desktop.
Save JamieCurnow/ebd7f4991f9434824f3a1d5eb62b503e to your computer and use it in GitHub Desktop.
Tailwind vue header with nice transitions
<template>
<div id="header" :class="headerClasses" class="z-40 w-full">
<div class="sticky top-0 inset-0 z-40">
<div class="max-w-7xl mx-auto flex justify-between items-center px-4 py-5 sm:px-6 sm:py-4 lg:px-8 md:justify-start md:space-x-10">
<div class="flex-1 flex flex-row items-center justify-between">
<nav class="flex flex-col sm:flex-row sm:space-x-10">
<a id="whyIsItNeeded" href="#joinTheMovement" v-smooth-scroll class="text-base font-medium">
Why is it needed?
</a>
<a id="faqs" href="#questions" v-smooth-scroll class="text-base font-medium">
FAQs
</a>
</nav>
<div class="flex items-center md:ml-12">
<button type="button" id="goCarbonFree1" class="hoverLinkButton text-base font-medium w-full sm:w-56 px-8 py-3 rounded-md bg-secondary-600 text-primary-800 hover:text-primary-700 flex justify-between items-center shadow-md" aria-label="Go Carbon Free - Opens Newsletter Sign-Up Modal" @click="$nuxt.$emit('showMailChimpForm')">
Go carbon-free
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data: () => ({
// the window scroll position
scrollY: 0,
// the about of change needed before toggling slide-down/up nav bar
buffer: 100,
// height of the nav
navHeight: 80,
// the current direction of scroll
currentDirection: 'down',
// the scroll position on direction change
scrollYBeforeDirectionChange: 0,
// nav toggle
navState: 'transparent' // 'slide-down' || 'slide-up' || 'initial-up'
}),
computed: {
headerClasses() {
const { navState } = this
// transparent top state
if (navState === 'transparent') {
return ['absolute bg-transparent text-white transition duration-300 ease-in-out']
}
// shared slide-up/down state
const shared = ['transform', 'fixed', 'bg-white', 'text-primary-500']
const sharedTransitions = ['transition duration-300 ease-in-out ']
// initial up state
if(navState === 'initial-up') {
return ['transition-none', ...shared, '-translate-y-20']
}
// slide up
if (navState === 'slide-up') {
return [...sharedTransitions, ...shared, '-translate-y-20']
}
// slide down
if (navState === 'slide-down') {
return [...sharedTransitions, ...shared, 'translate-y-0']
}
}
},
watch: {
navState(v, old) {
console.log({v, old})
},
scrollY(v, old) {
if(v === 0) return (this.navState = 'transparent')
const { currentDirection, buffer } = this
const newDirection = v > old ? 'down' : 'up'
if(currentDirection !== newDirection) this.scrollYBeforeDirectionChange = v
this.currentDirection = newDirection
const { navState, scrollYBeforeDirectionChange } = this
if (scrollYBeforeDirectionChange - v > buffer) {
this.navState = 'slide-down'
}
if (v - scrollYBeforeDirectionChange > buffer) {
this.navState = navState === 'transparent' ? 'initial-up' : 'slide-up'
}
}
},
mounted() {
this.onScroll()
window.addEventListener('scroll', this.onScroll)
},
unmounted() {
window.removeEventListener('scroll', this.onScroll)
},
methods: {
onScroll() {
this.scrollY = window.scrollY
}
}
}
</script>
<style>
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment