html - Making <a> active in menu when over div-element -
i'm trying make links active when i'm on elements scrolls to. i've tried every single line of code i've found 2 days. nothing working. i'm using cferdinandi's smoothscroll
script.
<div data-scroll-header id="menu"> <div id="menu-content"> <a data-scroll href="#weare">company</a> <a data-scroll href="#product">product</a> <a data-scroll href="#technical">technical specifications</a> <a data-scroll href="#footer">get in touch</a> </div> </div>
with "smooth-scroll" script.
<script> smoothscroll.init({ updateurl: true, }); </script>
update (the css):
#menu { background-color:white; position:fixed; top:0; left:0; height:90px; width:100%; z-index:99999; transition: top 0.2s ease-in-out; } #menu { will-change: transform; transition: transform 200ms linear; } .headroom--pinned { transform: translatey(0%); } .headroom--unpinned { transform: translatey(-100%); } .active { font-family:"aero bold", sans-serif; } #menu-logo { max-height:26px; display:block; margin:auto; position:absolute; top:20px; left:0; right:0; pointer-events: none; } #menu-content { position:absolute; width:75%; height:12px; line-height:12px; bottom:0; left:12.5%; right:12.5%; margin-bottom:20px; text-align:center; } #menu-content { padding:0 10px 0 10px; font-weight:thin; color:#03372b; color:#666666; text-decoration:none; font-size:12px; font-family:"aero book", helvetica, arial, sans-serif; } #menu-content a:hover { color:#03372b; transition:0.3s; }
update it's working, it's not working :o:
update (what fixed it):
#menu-content { position:absolute; width:75%; height:12px; line-height:12px; bottom:0; left:12.5%; right:12.5%; margin-bottom:20px; text-align:center; } .nav { padding:0 10px 0 10px; color:#666666; text-decoration:none; font-size:12px; font-family:"aero book", helvetica, arial, sans-serif; } .active { text-decoration:none; font-family: "aero bold", helvetica, arial, sans-serif; }
give links class of "nav" , add callback
here actual code:
window.onload=function() { smoothscroll.init({ updateurl: true, callback: function(anchor, toggle) { console.log(anchor); var link=document.queryselector("a[href='"+anchor+"']"); var links = document.queryselectorall("#menu-content .nav"); (var = 0; < links.length; i++) { links[i].classlist.toggle('active', 0); } link.classlist.toggle("active", toggle); } }); }
example (had copy in smoothscroll code)
(function (root, factory) { if ( typeof define === 'function' && define.amd ) { define([], factory(root)); } else if ( typeof exports === 'object' ) { module.exports = factory(root); } else { root.smoothscroll = factory(root); } })(typeof global !== 'undefined' ? global : this.window || this.global, function (root) { 'use strict'; // // variables // var smoothscroll = {}; // object public apis var supports = 'queryselector' in document && 'addeventlistener' in root; // feature test var settings, eventtimeout, fixedheader, headerheight, animationinterval; // default settings var defaults = { selector: '[data-scroll]', selectorheader: '[data-scroll-header]', speed: 500, easing: 'easeinoutcubic', offset: 0, updateurl: true, callback: function () {} }; // // methods // /** * merge 2 or more objects. returns new object. * @private * @param {boolean} deep if true, deep (or recursive) merge [optional] * @param {object} objects objects merge * @returns {object} merged values of defaults , options */ var extend = function () { // variables var extended = {}; var deep = false; var = 0; var length = arguments.length; // check if deep merge if ( object.prototype.tostring.call( arguments[0] ) === '[object boolean]' ) { deep = arguments[0]; i++; } // merge object extended object var merge = function (obj) { for ( var prop in obj ) { if ( object.prototype.hasownproperty.call( obj, prop ) ) { // if deep merge , property object, merge properties if ( deep && object.prototype.tostring.call(obj[prop]) === '[object object]' ) { extended[prop] = extend( true, extended[prop], obj[prop] ); } else { extended[prop] = obj[prop]; } } } }; // loop through each object , conduct merge for ( ; < length; i++ ) { var obj = arguments[i]; merge(obj); } return extended; }; /** * height of element. * @private * @param {node} elem element height of * @return {number} element's height in pixels */ var getheight = function ( elem ) { return math.max( elem.scrollheight, elem.offsetheight, elem.clientheight ); }; /** * closest matching element dom tree. * @private * @param {element} elem starting element * @param {string} selector selector match against (class, id, data attribute, or tag) * @return {boolean|element} returns null if not match found */ var getclosest = function ( elem, selector ) { // variables var firstchar = selector.charat(0); var supports = 'classlist' in document.documentelement; var attribute, value; // if selector data attribute, split attribute value if ( firstchar === '[' ) { selector = selector.substr(1, selector.length - 2); attribute = selector.split( '=' ); if ( attribute.length > 1 ) { value = true; attribute[1] = attribute[1].replace( /"/g, '' ).replace( /'/g, '' ); } } // closest match for ( ; elem && elem !== document && elem.nodetype === 1; elem = elem.parentnode ) { // if selector class if ( firstchar === '.' ) { if ( supports ) { if ( elem.classlist.contains( selector.substr(1) ) ) { return elem; } } else { if ( new regexp('(^|\\s)' + selector.substr(1) + '(\\s|$)').test( elem.classname ) ) { return elem; } } } // if selector id if ( firstchar === '#' ) { if ( elem.id === selector.substr(1) ) { return elem; } } // if selector data attribute if ( firstchar === '[' ) { if ( elem.hasattribute( attribute[0] ) ) { if ( value ) { if ( elem.getattribute( attribute[0] ) === attribute[1] ) { return elem; } } else { return elem; } } } // if selector tag if ( elem.tagname.tolowercase() === selector ) { return elem; } } return null; }; /** * escape special characters use queryselector * @public * @param {string} id anchor id escape * @author mathias bynens * @link https://github.com/mathiasbynens/css.escape */ smoothscroll.escapecharacters = function ( id ) { // remove leading hash if ( id.charat(0) === '#' ) { id = id.substr(1); } var string = string(id); var length = string.length; var index = -1; var codeunit; var result = ''; var firstcodeunit = string.charcodeat(0); while (++index < length) { codeunit = string.charcodeat(index); // note: there’s no need special-case astral symbols, surrogate // pairs, or lone surrogates. // if character null (u+0000), throw // `invalidcharactererror` exception , terminate these steps. if (codeunit === 0x0000) { throw new invalidcharactererror( 'invalid character: input contains u+0000.' ); } if ( // if character in range [\1-\1f] (u+0001 u+001f) or // u+007f, […] (codeunit >= 0x0001 && codeunit <= 0x001f) || codeunit == 0x007f || // if character first character , in range [0-9] // (u+0030 u+0039), […] (index === 0 && codeunit >= 0x0030 && codeunit <= 0x0039) || // if character second character , in range [0-9] // (u+0030 u+0039) , first character `-` (u+002d), […] ( index === 1 && codeunit >= 0x0030 && codeunit <= 0x0039 && firstcodeunit === 0x002d ) ) { // http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point result += '\\' + codeunit.tostring(16) + ' '; continue; } // if character not handled 1 of above rules , // greater or equal u+0080, `-` (u+002d) or `_` (u+005f), or // in 1 of ranges [0-9] (u+0030 u+0039), [a-z] (u+0041 // u+005a), or [a-z] (u+0061 u+007a), […] if ( codeunit >= 0x0080 || codeunit === 0x002d || codeunit === 0x005f || codeunit >= 0x0030 && codeunit <= 0x0039 || codeunit >= 0x0041 && codeunit <= 0x005a || codeunit >= 0x0061 && codeunit <= 0x007a ) { // character result += string.charat(index); continue; } // otherwise, escaped character. // http://dev.w3.org/csswg/cssom/#escape-a-character result += '\\' + string.charat(index); } return '#' + result; }; /** * calculate easing pattern * @private * @link https://gist.github.com/gre/1650294 * @param {string} type easing pattern * @param {number} time time animation should take complete * @returns {number} */ var easingpattern = function ( type, time ) { var pattern; if ( type === 'easeinquad' ) pattern = time * time; // accelerating 0 velocity if ( type === 'easeoutquad' ) pattern = time * (2 - time); // decelerating 0 velocity if ( type === 'easeinoutquad' ) pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, deceleration if ( type === 'easeincubic' ) pattern = time * time * time; // accelerating 0 velocity if ( type === 'easeoutcubic' ) pattern = (--time) * time * time + 1; // decelerating 0 velocity if ( type === 'easeinoutcubic' ) pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, deceleration if ( type === 'easeinquart' ) pattern = time * time * time * time; // accelerating 0 velocity if ( type === 'easeoutquart' ) pattern = 1 - (--time) * time * time * time; // decelerating 0 velocity if ( type === 'easeinoutquart' ) pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * (--time) * time * time * time; // acceleration until halfway, deceleration if ( type === 'easeinquint' ) pattern = time * time * time * time * time; // accelerating 0 velocity if ( type === 'easeoutquint' ) pattern = 1 + (--time) * time * time * time * time; // decelerating 0 velocity if ( type === 'easeinoutquint' ) pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * (--time) * time * time * time * time; // acceleration until halfway, deceleration return pattern || time; // no easing, no acceleration }; /** * calculate how far scroll * @private * @param {element} anchor anchor element scroll * @param {number} headerheight height of fixed header, if * @param {number} offset number of pixels offset scroll * @returns {number} */ var getendlocation = function ( anchor, headerheight, offset ) { var location = 0; if (anchor.offsetparent) { do { location += anchor.offsettop; anchor = anchor.offsetparent; } while (anchor); } location = math.max(location - headerheight - offset, 0); return math.min(location, getdocumentheight() - getviewportheight()); }; /** * determine viewport's height * @private * @returns {number} */ var getviewportheight = function() { return math.max(document.documentelement.clientheight, window.innerheight || 0); }; /** * determine document's height * @private * @returns {number} */ var getdocumentheight = function () { return math.max( root.document.body.scrollheight, root.document.documentelement.scrollheight, root.document.body.offsetheight, root.document.documentelement.offsetheight, root.document.body.clientheight, root.document.documentelement.clientheight ); }; /** * convert data-options attribute object of key/value pairs * @private * @param {string} options link-specific options data attribute string * @returns {object} */ var getdataoptions = function ( options ) { return !options || !(typeof json === 'object' && typeof json.parse === 'function') ? {} : json.parse( options ); }; /** * update url * @private * @param {element} anchor element scroll * @param {boolean} url whether or not update url history */ var updateurl = function ( anchor, url ) { if ( root.history.pushstate && (url || url === 'true') && root.location.protocol !== 'file:' ) { root.history.pushstate( null, null, [root.location.protocol, '//', root.location.host, root.location.pathname, root.location.search, anchor].join('') ); } }; var getheaderheight = function ( header ) { return header === null ? 0 : ( getheight( header ) + header.offsettop ); }; /** * start/stop scrolling animation * @public * @param {element} anchor element scroll * @param {element} toggle element toggled scroll event * @param {object} options */ smoothscroll.animatescroll = function ( anchor, toggle, options ) { // options , overrides var overrides = getdataoptions( toggle ? toggle.getattribute('data-options') : null ); var animatesettings = extend( settings || defaults, options || {}, overrides ); // merge user options defaults // selectors , variables var isnum = object.prototype.tostring.call( anchor ) === '[object number]' ? true : false; var hash = smoothscroll.escapecharacters( anchor ); var anchorelem = isnum ? null : ( hash === '#' ? root.document.documentelement : root.document.queryselector( hash ) ); if ( !isnum && !anchorelem ) return; var startlocation = root.pageyoffset; // current location on page if ( !fixedheader ) { fixedheader = root.document.queryselector( animatesettings.selectorheader ); } // fixed header if not set if ( !headerheight ) { headerheight = getheaderheight( fixedheader ); } // height of fixed header if 1 exists , not set var endlocation = isnum ? anchor : getendlocation( anchorelem, headerheight, parseint(animatesettings.offset, 10) ); // location scroll var distance = endlocation - startlocation; // distance travel var documentheight = getdocumentheight(); var timelapsed = 0; var percentage, position; // update url if ( !isnum ) { updateurl( anchor, animatesettings.updateurl ); } /** * stop scroll animation when reaches target (or bottom/top of page) * @private * @param {number} position current position on page * @param {number} endlocation scroll location * @param {number} animationinterval how scroll on loop */ var stopanimatescroll = function ( position, endlocation, animationinterval ) { var currentlocation = root.pageyoffset; if ( position == endlocation || currentlocation == endlocation || ( (root.innerheight + currentlocation) >= documentheight ) ) { clearinterval(animationinterval); // if scroll target anchor, bring focus if ( !isnum ) { anchorelem.focus(); if ( document.activeelement.id !== anchorelem.id ) { anchorelem.setattribute( 'tabindex', '-1' ); anchorelem.focus(); anchorelem.style.outline = 'none'; } } animatesettings.callback( anchor, toggle ); // run callbacks after animation complete } }; /** * loop scrolling animation * @private */ var loopanimatescroll = function () { timelapsed += 16; percentage = ( timelapsed / parseint(animatesettings.speed, 10) ); percentage = ( percentage > 1 ) ? 1 : percentage; position = startlocation + ( distance * easingpattern(animatesettings.easing, percentage) ); root.scrollto( 0, math.floor(position) ); stopanimatescroll(position, endlocation, animationinterval); }; /** * set interval timer * @private */ var startanimatescroll = function () { clearinterval(animationinterval); animationinterval = setinterval(loopanimatescroll, 16); }; /** * reset position fix weird ios bug * @link https://github.com/cferdinandi/smooth-scroll/issues/45 */ if ( root.pageyoffset === 0 ) { root.scrollto( 0, 0 ); } // start scrolling animation startanimatescroll(); }; /** * if smooth scroll element clicked, animate scroll * @private */ var eventhandler = function (event) { // don't run if right-click or command/control + click if ( event.button !== 0 || event.metakey || event.ctrlkey ) return; // if smooth scroll link, animate var toggle = getclosest( event.target, settings.selector ); if ( toggle && toggle.tagname.tolowercase() === 'a' ) { // check link anchor , points current page if ( toggle.hostname !== root.location.hostname || toggle.pathname !== root.location.pathname || !/#/.test(toggle.href) ) return; event.preventdefault(); // prevent default click event smoothscroll.animatescroll( toggle.hash, toggle, settings); // animate scroll } }; /** * on window scroll , resize, run events @ rate of 15fps better performance * @private * @param {function} eventtimeout timeout function * @param {object} settings */ var eventthrottler = function (event) { if ( !eventtimeout ) { eventtimeout = settimeout(function() { eventtimeout = null; // reset timeout headerheight = getheaderheight( fixedheader ); // height of fixed header if 1 exists }, 66); } }; /** * destroy current initialization. * @public */ smoothscroll.destroy = function () { // if plugin isn't initialized, stop if ( !settings ) return; // remove event listeners root.document.removeeventlistener( 'click', eventhandler, false ); root.removeeventlistener( 'resize', eventthrottler, false ); // reset varaibles settings = null; eventtimeout = null; fixedheader = null; headerheight = null; animationinterval = null; }; /** * initialize smooth scroll * @public * @param {object} options user settings */ smoothscroll.init = function ( options ) { // feature test if ( !supports ) return; // destroy existing initializations smoothscroll.destroy(); // selectors , variables settings = extend( defaults, options || {} ); // merge user options defaults fixedheader = root.document.queryselector( settings.selectorheader ); // fixed header headerheight = getheaderheight( fixedheader ); // when toggle clicked, run click handler root.document.addeventlistener('click', eventhandler, false ); if ( fixedheader ) { root.addeventlistener( 'resize', eventthrottler, false ); } }; // // public apis // return smoothscroll; }); window.onload=function() { smoothscroll.init({ updateurl: true, callback: function(anchor, toggle) { console.log(anchor); var link=document.queryselector("a[href='"+anchor+"']"); var links = document.queryselectorall("#menu-content .nav"); (var = 0; < links.length; i++) { links[i].classlist.toggle('active', 0); } link.classlist.toggle("active", toggle); } }); }
a { text-decoration:none; } .active { text-decoration:underline; font-family:"aero bold", sans-serif; }
<div data-scroll-header id="menu"> <div id="menu-content"> <a class="nav" data-scroll href="#weare">company</a> <a class="nav" data-scroll href="#product">product</a> <a class="nav" data-scroll href="#technical">technical specifications</a> <a class="nav" data-scroll href="#footer">get in touch</a> </div> </div> <hr /> <div id="weare">we what</div> <div id="product">product</div>
Comments
Post a Comment