eddiemf / vue-scrollactive Goto Github PK
View Code? Open in Web Editor NEWLightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.
License: MIT License
Lightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.
License: MIT License
On page load the last item that has a binding receives the active class, which is wrong. When I scroll for just 1px it will be fixed. What's the problem?
<scrollactive v-if="showNavText" active-class="router-link-exact-active" :offset="80" :duration="600">
<a class="navigation-text-desktop scrollactive-item" href="#home">News</a>
<a class="navigation-text-desktop scrollactive-item" href="#links">Links</a>
<a class="navigation-text-desktop scrollactive-item" href="#community">Community</a>
</scrollactive>
<scrollactive :offset="50" tag="div" :alwaysTrack="true" :modifyUrl="false" :exact="true">
<span data-section-selector="#subsection-1" class="scrollactive-item">test1</span>
<span data-section-selector="#subsection-2" class="scrollactive-item">test2</span>
<span data-section-selector="#subsection-3" class="scrollactive-item">test3</span>
</scrollactive>
<div id="subsection-1">
<h2>subsection-1</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Ab, aperiam atque consequuntur culpa cum dolorem doloribus earum error fuga laborum
molestias neque nesciunt quaerat quas rem veniam voluptatum! Minus, vel?</p>
</div>
<div id="subsection-2">
<h2>subsection-2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Ab, aperiam atque consequuntur culpa cum dolorem doloribus earum error fuga laborum
molestias neque nesciunt quaerat quas rem veniam voluptatum! Minus, vel?</p>
</div>
<div id="subsection-3">
<h2>subsection-3</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Ab, aperiam atque consequuntur culpa cum dolorem doloribus earum error fuga laborum
molestias neque nesciunt quaerat quas rem veniam voluptatum! Minus, vel?</p>
</div>
My problem is that when I enter anchored position on page, eg. /#contact, it always renders at the top, not in the given position, when I disable scrollactive the problem ends.
Hi,
Im getting an error when I import local;
import VueScrollactive from 'vue-scrollactive'; export default { components: { Scrollactive: VueScrollactive, }, }
[Vue warn]: Failed to mount component: template or render function not defined.
Is there a solution ? Thank you
At: https://github.com/eddiemf/vue-scrollactive/blob/master/src/scrollactive.vue#L196
const target = document.getElementById(item.hash.substr(1));
item.hash may urlencode the href attribute, so when i use it with some unicode word like this:
<scrollactive class="my-nav">
<a href="#home-家" class="scrollactive-item">Home</a>
...
</scrollactive>
it may urlencode it, try to find the element with a id home-%E5%AE%B6
>_<#@!
Hi!
Since the latest release the plugin stopped working if there is no scrollContainer
provided. The issue is here:
06dfcb3#diff-4959140d7c2bf6ca765de6d9c393a83cR363
Since this.scrollContainer
is always set (it's a computed property, and it's either the one set in props, otherwise window
), we try to get the offsetTop
of window
. Since window
does not have such property, it returns undefined
. Some number (yPosition
) minus undefined
is NaN
. So our script breaks.
Because there might be a few other elements without offsetTop
properties, I would not suggest checking for whether the container is window
or not, rather check for the availability of offsetTop
.
Something like this would probably work fine:
if (this.scrollContainer && typeof this.scrollContainer.offsetTop === 'number') {
return yPosition - this.scrollContainer.offsetTop;
}
emm, its got my router like #/ApiPage as selector,how can I solve it?thank u
I have a use case where I need a different :offset
depending on which link is clicked. I've tried dynamically setting a data
property depending on currentTarget
but it doesn't seem to work. Is there a way to do this I'm unaware of? If not this would be a really helpful implementation.
Hello. I noticed that scrollspy functional doesn't work on iOS. Is this wanted behavior?
Hi. This was exactly what I was looking for, but I'm working on a project that uses SSR. I'm new to Vue, but I assume since this uses window
that SSR won't work out of the box. I know there is a way that fakes window to make most Vue plugins to work on the server side, but I'd like to avoid this, if possible. I noticed vue-scrollto
plugin got it working with this simple fix. They just changed
if (window.Vue)
... to if (typeof window !== "undefined" && window.Vue)
...
Could something like that be easily applied to this project?
If the item in menu point to the same link, only the last item got the is-active
class when page scroll to that section.
E.g.
<div class="submenu-links">
<a href="#highlights" class="scrollactive-item submenu-item" v-if="preset.data.infoHighlights && preset.data.infoHighlights.length">Highlights</a>
<a href="#itinerary" class="scrollactive-item submenu-item">Itinerary</a>
<a href="#priceinfo" class="scrollactive-item submenu-item">Pricing info</a>
<a href="#priceinfo" class="scrollactive-item submenu-item">Pricing info 2</a>
<a href="#tripinfo" class="scrollactive-item submenu-item">Trip info</a>
</div>
Only Pricing info 2
got is-active
class.
Expected Behavior:
Both Pricing info
and Pricing info 2
should got is-active
class.
When using prerender-spa-plugin I get error:
TypeError: undefined is not a constructor (evaluating 't.forEach')
https://vuejs.org/v2/style-guide/#Priority-A-Rules-Essential-Error-Prevention
<scrollactive></scrollactive>
<scroll-active></scroll-active>
Some editors (Such as VSCode) will see this as an invalid element. If the component follows the naming convention of having a hyphen, it will just be seen as a custom element ready to be picked up by some javascript.
Specifically with my editor, I had a problem with two nav elements being rendered. Turns out, I had forgotten to put a slash in the end tag, resolving in the next element being included in a secondary nav tag like so:
<scrollactive>
<a href="...">...</a>
<a href="...">...</a>
<a href="...">...</a>
<scrollactive>
<a href="...">...</a>
Result:
<nav class="scrollactive-nav">
<a href="..." class="scrollactive-item">...</a>
<a href="..." class="scrollactive-item">...</a>
<a href="..." class="scrollactive-item">...</a>
<a href="..." class="scrollactive-item">...</a>
<a href="..." class="scrollactive-item">...</a>
<nav class="scrollactive-nav">
<a href="..." class="none-scroll-item">...</a>
</nav>
</nav>
Edit: Added link to style guide documentation
container is always window
container = document.querySelector(containerSelector);
container = document.querySelector(this.scrollContainerSelector);
Hello,
I have more a question than issue. I would like to listen "currenItem" on the itemchanged function. I just don't know how to pass the element...
This is more or less what I have in mind: v-on:itemchanged="update(currenItem)"
Sorry for my noobie question.
Thanks
Hi,
Is there any way you could programmatically add a previous and next button so a user could navigate to the previous en next element?
Hi!
My site have overflowed 100vh container and I need set it to scrollContainerSelector globaly but it is not working.
This work only in component prop : scrollactive( scrollContainerSelector='#appScroll').
I trying do that just like that
Vue.use(VueScrollactive, {
scrollContainerSelector: '#appScroll',
});
I use vue-scrollactive for vue-affix navigation.
It works correct until i try to open the page from the link with anchor (f.e. http://localhost:8081/#section2).
On first page load from the link with an anchor it seems that :offset prop of <scrollactive>
in not applying.
After first load :offset is working correct.
repo to reproduce bug:
https://github.com/pkarev/demo/tree/demo/vue-affix-position-bug
npm install
npm run dev
vue-scrollactive do not work in Firefox 55 (Mac OS Sierra, Windows10 ) and IE11.
In Chrome, Safari, Edge it works perfectly.
itemChanged
seems only be dispatched in onScroll(event)
.
When user scroll, itemChanged
fired.
But if user click the '.scrollactive-item'
, itemChanged
won't be fired.
only change the hash by click
Hi, I'm new to VueJS.
I tried to use it but it gives me Error: You must give your menu items a class of 'scrollactive-item' in order to track them.
But I already gave the class name to the <a>
tag,
I tried to call the dynamicItemsFunction
after but the same error persists.
When the link is clicked, I get this error
Cannot read property 'substr' of undefined
from:
var targetDistanceFromTop = this.getOffsetTop(document.getElementById(event.target.hash.substr(1)));
below is my html code,
Thank you for your help!
<div class="menu-wrapper" :style="{marginTop: 0.117 * bodyWidth + 'px'}">
<div class="catalogue">
<scrollactive ref="scrollactive" :offset="offset" :always-track="alwaysTrack" :duration="duration" :click-to-scroll="clickToScroll" :bezier-easing-value="easing">
<a v-for="aCat in cataArr" v-bind:key="aCat" class="scrollactive-item" href="'#' + aCat.substr(0, 10)">
<div class="each-cat">
{{aCat}}
</div>
</a>
</scrollactive>
</div>
<div class="items-wrapper">
<div class="each-cat-item" v-if="formatCats.length>0" v-for="aCat in formatCats" v-bind:key="aCat" :id="aCat.substr(0, 10)">
{{aCat}}
<div class="each-item" v-for="anItem in posts[aCat]" v-bind:key="anItem">
<div class="item-img" v-if="anItem.photos && anItem.photos.length > 0" @click="jump(anItem)">
</div>
</div>
</div>
</div>
</div>
Hi there. Awesome plugin, but unfortunately I found out that it has issue, if I am trying to use multiple scrollactive
on single page. For example, I have 2 navigations, main and mobile. I want scrollactive
on both. If I try that, then I have glitches. For example if you set :duration="1000"
then scrollbar will jerk. Or, even :duration="100"
will not work at all (small values).
Is there's a way to fix it?
Hi, I'm having an issue where the active-class
is applied on page-load but I only want it applied after the user clicks the link. I've tried :highlightFirstItem="false"
, even though this is the default setting, but it didn't work. Am I wrong in thinking this is the setting for it? Is there a way around this issue I'm not aware of?
Here's the code I'm using:
<scrollactive
active-class="nav-selected"
:offset="0"
:duration="1000"
bezier-easing-value=".5,0,.35,1"
:modifyUrl="false"
>
<a href="#smooth-scroll" class="scrollactive-item"
>Smooth Scroll</a
>
</scrollactive>
.nav-selected {
font-weight: bold;
}
The text is bold on page-load, if I scroll at all, the active class is removed and doesn't respond to any scrolling (how I want it) but then works as it should on click:
Hi @eddiemf, is there any option to "active" the item in menu only if the trackable sections are really in viewport?
Example: I have 5 sections in sequence, but I'd like to activate menu items only when the scroll reaches the sections 1, 3 and 5. So, if I reach section 2 or 4, no items in menu should be active.
Thanks and congrat for the very nice plugin.
Hello! I need menu like this:
https://excelsiorer.github.io/portfolio/instalations.html
This i make on vanila js. Now i try make it on vue, and use this library.
I use this markdown:
`
<li>
<a href="#project-2" class="scrollactive-item"> Project 2 </a>
<scrollactive active-class="submenu--active" tag="ul">
<li>
<a href="#submenu-2-1" class="scrollactive-item"> Submenu 2-1 </a>
</li>
<li>
<a href="#submenu-2-2" class="scrollactive-item"> Submenu 2-2 </a>
</li>
<li>
<a href="#submenu-2-3" class="scrollactive-item"> Submenu 2-3 </a>
</li>
<li>
<a href="#submenu-2-4" class="scrollactive-item"> Submenu 2-4 </a>
</li>
</scrollactive>
</li>
</scrollactive>`
but both classes add only on second scrollactive tag.
How i can change it?
When used with lazy loading of components I get this error
Cannot read property 'offsetHeight' of null
I get
DOMException: Failed to execute 'querySelector' on 'Document': '#/en/scrolltest/' is not a valid selector.
when vue-router is in hash mode. Works perfectly in history mode
Hello, after doing the installation of the package using npm, and configure it as explained in the documentation. I try to use it and it throws me this error:
vue.esm.js?efeb:610 [Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option. found in
---> at src/views/Home.vue
at src/App.vue
If I have a section that isn't the full page height, is it still possible to trigger vue-scrollactive when it's in view?
(btw if there is a better location to ask these questions let me know)
Hi !
Thanks for your project. I use it for my work but i found a problem about the active class navigation.
To reproduce it :
<scrollactive id="nav-items" class="my-nav" active-class="active" v-on:itemchanged="onItemChanged" :offset="90" :duration="500" :modify-url="false"> </scrollactive>
My navigation looks like :
<nav class="scrollactive-nav my-nav" id="nav-items"><a href="#introduction" class="scrollactive-item">Introduction</a><a href="#factsDemandsProcedure" class="scrollactive-item">factsDemandsProcedure</a><a href="#motifs" class="scrollactive-item">motifs</a><a href="#dispositif" class="scrollactive-item">dispositif</a><a href="#signature" class="scrollactive-item active">signature</a></nav>
Each sections have the following template :
<section id="introduction" class="part"><p>My content ...</p></section>
Each section has different height. And it's the problem because dispositif
and signature
section have a little height and place at the end of the document.
Case reproduction :
signature
signature
have always active classmotifs
has active classI bind the itemchanged
methods to debug then i noticed something. My console.log not appears when i click on the last section probably because the last section can not be reached by the window's offset.
Thanks for your answer.
Hi,
Thanks for the plugin!
An error I encountered: I use scrollActive on an element which is in a tab. When I switch tabs and scroll, I get the following error:
vue-scrollactive.js?ce7a:1088 Uncaught TypeError: Cannot read property 'offsetHeight' of null
at eval (vue-scrollactive.js?ce7a:1088)
which is this line:
var isScreenBeforeSectionEnd = window.pageYOffset < _this.getOffsetTop(target) - _this.offset + target.offsetHeight;
I guess the inactive tab is detached by the framework I use (Quasar) but not destroyed (because I use the keep-alive property of tabs, which keeps the rendered HTML in memory), so scrollActive is still listening to events and doing things. Not sure if you can fix it without me worrying about it, or if I should call some method to put it on hold while the tab is inactive?
Thank you.
IE11 isn't supported. IE message -> SCRIPT5009 - Object promise not defined.
Btw good work. Nice plugin. :)
Hi, is it possible to use your component on nuxt?
Great plugin for Vue, but i have trouble with matching URL
I have a page with section
#about
#prices
URL must be /courses/1/#about
but after clicking on item i have only /#about
Nuxt with dynamic routring
When installing the plugin as described in the readme, it seems like vue-scrollactive is stuck on v0.9.1, which doesn't support the new feature added in v0.9.2.
When comparing the minified file between the two releases,git diff v0.9.1 v0.9.2 dist/vue-scrollactive.min.js
, we can see that there is no difference between these two releases.
Related problems:
dist/vue-scrollactive.min.js
. This could be replaced with src/index.js
without any problems, as the file will (usually, in most setups) be minified by the build setup using the plugin. This will also allow the user (in this case, me) to see the source easier while debugging the code.dist/vue-scrollactive.min.js
semi-readable does not make sure we have actually built dist/vue-scrollactive.min.js
from the latest sources before committing.Is it possible to target scroll a container instead of body? ✌️
how to make li active instead of a?
<ul><li class="active"><a href="#home">Home</a></li><ul>
Hi guys
I have a page with a few different sections (all of these have a vue-scrollactive linking). When clicking on an item (let's say from #team
), a detailpage opens (= route navigated, #/team/sandrooco
).
Then, when clicking on a back button, this.$router.go(-1);
executes. The problem: Vue will not recognize #team
as route (because it doesn't exist...) and the user will be lost (no navigation possible).
I hope you understand it, it's quite complicated.
I use vue-scrollactive 0.5.1
and vue 2.5.2
.
I'm having this issue and I'm not able to make vue-scrollactive to work here on my project. After some research I read that, somehow, the component is "acting" before the DOM is loaded, so, that's why it can't find the element with the anchor id.
If someone have a solution for this, please help me! Thank you all!
Can I do it not just by hash, but also by className. For example, set data-*
<scrollactive class="my-nav">
<span data-class="a" class="scrollactive-item">Home</span>
<span data-class="b" class="scrollactive-item">About Us</span>
<span data-class="c" class="scrollactive-item">Portfolio</span>
</scrollactive>
<div class="container">
<p class="a">a</p>
<p class="b">b</p>
<p class="c">c</p>
</div>
See below screenshot from online demo, You should recreate the issue with below steps:
Fix:
onScroll(event) {
this.currentItem = this.getItemInsideWindow();
if (this.currentItem !== this.lastActiveItem && this.currentItem) {
this.removeActiveClass();
this.$emit('itemchanged', event, this.currentItem, this.lastActiveItem);
this.lastActiveItem = this.currentItem;
}
// Current item might be null if not inside any section
if (this.currentItem) {
this.removeActiveClass();
this.currentItem.classList.add(this.activeClass);
}
},
I also added an empty check on line 3 because sometimes, i found the currentItem is undefined but the itemchanged even still triggered.
show my code
<scrollactive
:modify-url="false"
:always-track="true"
:duration="800"
bezier-easing-value=".5,0,.35,1"
>
<h-navbar
:slider="{
width: 50,
height: 4,
color: '#FF4A83',
}"
:tabs="tabs"
>
<a :slot="`tab${index}`" :href="`#floor${index + 1}`" v-for="(item, index) in tabs" :key="index">{{item}}</a>
</h-navbar>
</scrollactive>
as i set props modifyUrl to false
but i find noting happend
the url is also be modifyed,
like: http://localhost:8080/#/course/courseList?courseId=COURSEID
to http://localhost:8080/#/floor1
i do something error?
As per the title. It would be fantastic to accommodate for a changing navbar height – for situations where precise positioning is needed.
This could be easily done with a callback or if the offset prop listened for changes on a data value – would that be efficient?
I’m trying to set :offset="offset"
with:
getNavHeight() {
let navHeight = document.getElementById('header').offsetHeight + document.getElementById('subheader').offsetHeight
this.offset = navHeight * 1;
}
but not having any luck
hi, i am trying to use vue-scrollactive inside a viutify dialog / modal but it doesn't work. I think it doesn't iterate over the dialogue.
try scrollContainerSelector but it doesn't work either.
I want to clarify that if it works for me outside the dialog / modal
also when I click on an it doesn't work either
could you help me please? thanks!
I already add section for every link. but it doesn't work.
In Nuxt.js it gives TypeError: Cannot read property 'substr' of undefined on render
Nice package! Thank you for writing it - it has saved me some time and trouble from writing my own.
I'm hoping my feedback is constructive. I'd like to discuss a couple of things I ran into when implementing this in a new client site. I added a CodePen example to follow along with here: https://codepen.io/markadrake/pen/xWebxQ
Meaning, once section two has scrolled into view then "two" should highlight in the menu. This too could benefit from an offset so that we can say "once this element is at least 100px visible, time to switch the active class".
There's already an offset parameter, and it works well when clicking a link and scrolling to the desired element on the page. But I need control over when highlighting occurs and quite possibly, an offset value of its own.
Currently the offset isn't just a number value - it's a specific number of pixels. However, in implementation I may want more control over this value especially when considering the design changes that can occur between breakpoints, and the user's zoom level. It would be nice to provide different values such as:
Or even take a targe element, calculate it's height, and use that as the value or part of the calculation of the value. This would have to subscribe to the window resize event to keep it in check.
Click on "Six" and you should see it jump back to five. After a while of testing, you may notice other items in the menu will start to behave this way - but "Six" does it everytime.
Although I couldn't replicate it any more here, in a site I'm building and using this on it's even more pronounced as all of the menu items scroll to the right place, set the appropriate highlight, but after the scroll animation is complete it will highlight the previous entry instead.
Hi, I'd like to be able to apply the active class to the first element in the nav when none of the sections are in the viewport, is this possible?
At the moment I'm adding the active class in my markup but when the component is mounted it removes all instances of the class.
Here's an example of what is happening right now (I'd like "popular" to be active before a sections is scrolled into view):
Would you consider adding this via an option? Something like firstItemActive
?
I'm happy to submit a pull request.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.