{"id":6038,"date":"2021-03-25T01:00:00","date_gmt":"2021-03-25T00:00:00","guid":{"rendered":"https:\/\/alvarotrigo.com\/epa\/create-a-slidebar-bullet-navigation-to-smoothly-snap-to-sections\/"},"modified":"2024-02-08T00:29:37","modified_gmt":"2024-02-07T23:29:37","slug":"create-a-slidebar-bullet-navigation-to-smoothly-snap-to-sections","status":"publish","type":"post","link":"https:\/\/alvarotrigo.com\/blog\/create-a-slidebar-bullet-navigation-to-smoothly-snap-to-sections\/","title":{"rendered":"Create a sidebar bullet navigation to smoothly snap to sections"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\" id=\"create-a-sidebar-bullet-navigation-to-smoothly-snap-to-sections\">Create a sidebar bullet navigation to smoothly snap to sections<\/h2>\n\n\n\n<p>Navigation is a fundamental requirement in many applications, whether it&#8217;s a web or mobile app. Businesses tend to put in a lot of effort and time to be unique or to stand out from the competition and this extends to their landing pages. A bullet-based sidebar navigation is one of the few quirky methods to do so.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"understanding-the-effect\">Understanding the effect<\/h2>\n\n\n\n<p>The primary component of this effect is the sidebar that is fixed to either left or right side of the viewport, preferably towards the center to attract the most of a user&#8217;s attention. This component when interacted with must allow users to navigate the page. It is also important to make the jump, as smooth as possible, for which we will use the concept of smooth-scrolling.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" data-src=\"..\/assets\/imgs\/sidebar-bullet-navigation-demo.gif\" alt=\"demonstration of the effect\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-up-the-html\">Setting up the HTML<\/h2>\n\n\n\n<p>For the sake of this tutorial, we will have 3 <code>section<\/code>s that will take up the full height of the viewport, each will of them will have an <code>id<\/code> attribute that will help us with navigating between <code>section<\/code>s and we will add in a few headings in the them, but you can replace the headings with what you want.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">charset<\/span>=<span class=\"hljs-string\">\"UTF-8\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"viewport\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Sidebar navigation<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"first\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Hello<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"second\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>How are you?<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"third\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Goodbye!<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, we will set up the sidebar, and we will use the semantic HTML tag <code>aside<\/code> that will contain an unordered list that will contain an anchor tag in each list item. To make things simple, we will use a bunch of small circles, but you can quite literally put anything inside the <code>a<\/code> tags, and you can style it however you want!<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-meta\">&lt;!DOCTYPE <span class=\"hljs-meta-keyword\">html<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- Collapsed --&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">aside<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"indicator active\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#first\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"indicator\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#second\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"indicator\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#third\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">aside<\/span>&gt;<\/span>\n      <span class=\"hljs-comment\">&lt;!-- Collapsed --&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"styling-things-up!\">Styling things up!<\/h2>\n\n\n\n<p>The styles will bring our markup and logic together nicely. Firstly, we enable smooth scroll using the <code>scroll-behavior<\/code> property.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">scroll-behavior<\/span>: smooth;\n}\n<span class=\"hljs-selector-tag\">body<\/span> {\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now we style the <code>aside<\/code> element. We have to make sure that the sidebar is accessible to the user no matter which section they are in, especially if the scroll bar has been disabled. <code>position: fixed<\/code> combined with <code>top: 50%<\/code> can achieve a certain degree of this but we need to use <code>transform<\/code> to make sure that the <code>aside<\/code> is <code>50%<\/code> from the top of the viewport.<\/p>\n\n\n\n<p>The <code>indicator<\/code> class will turn the ordinary anchor tag into a white circle with a <code>height<\/code> and <code>width<\/code> of <code>15px<\/code>. Because the <code>active<\/code> class increases the <code>scale<\/code> of these white dots, we make sure that the unordered list is always aligned properly using flexbox.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">aside<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: fixed;\n  <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">50%<\/span>;\n  <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">translate<\/span>(-<span class=\"hljs-number\">50%<\/span>, -<span class=\"hljs-number\">50%<\/span>);\n}\n<span class=\"hljs-selector-tag\">aside<\/span> <span class=\"hljs-selector-tag\">ul<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">flex-direction<\/span>: column;\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\n  <span class=\"hljs-attribute\">list-style-type<\/span>: none;\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n<span class=\"hljs-selector-tag\">aside<\/span> <span class=\"hljs-selector-tag\">ul<\/span> <span class=\"hljs-selector-tag\">li<\/span> <span class=\"hljs-selector-class\">.indicator<\/span> {\n  <span class=\"hljs-attribute\">cursor<\/span>: pointer;\n  <span class=\"hljs-attribute\">margin-top<\/span>: <span class=\"hljs-number\">1rem<\/span>;\n  <span class=\"hljs-attribute\">display<\/span>: block;\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">15px<\/span>;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">15px<\/span>;\n  <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">50%<\/span>;\n  <span class=\"hljs-attribute\">background-color<\/span>: white;\n}\n<span class=\"hljs-selector-tag\">aside<\/span> <span class=\"hljs-selector-tag\">ul<\/span> <span class=\"hljs-selector-tag\">li<\/span> <span class=\"hljs-selector-class\">.active<\/span> {\n  <span class=\"hljs-attribute\">transform<\/span>: <span class=\"hljs-built_in\">scale<\/span>(<span class=\"hljs-number\">1.7<\/span>);\n  <span class=\"hljs-attribute\">transition<\/span>: transform <span class=\"hljs-number\">200ms<\/span> ease-in-out;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, we make each section take the height of the viewport and give each odd and even section a different <code>background-color<\/code>. Lots of potentials to do some creative styling here!<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">section<\/span> {\n  <span class=\"hljs-attribute\">min-height<\/span>: <span class=\"hljs-number\">100vh<\/span>;\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">justify-content<\/span>: center;\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\n}\n<span class=\"hljs-selector-tag\">section<\/span><span class=\"hljs-selector-pseudo\">:nth-child(odd)<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#ffcc33<\/span>;\n}\n<span class=\"hljs-selector-tag\">section<\/span><span class=\"hljs-selector-pseudo\">:nth-child(even)<\/span> {\n  <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#ffb347<\/span>;\n}\n<span class=\"hljs-selector-tag\">section<\/span> <span class=\"hljs-selector-tag\">h1<\/span> {\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">font-family<\/span>: sans-serif;\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">4rem<\/span>;\n  <span class=\"hljs-attribute\">color<\/span>: white;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"highlighting-the-active-link\">Highlighting the active link<\/h2>\n\n\n\n<p>Remember the <code>active<\/code> class from before? The stylistic function for it was to help users to identify which of the anchor tags is mapped to the current section. Now we have to make sure that style is applied to the correct anchor tag. To do this get a list of all the anchor tags with the <code>indicator<\/code> class, then iterate the list each time applying a <code>click<\/code> event listener.<\/p>\n\n\n\n<p>This listener will first call <code>resetIndicators<\/code> to remove the <code>active<\/code> class from all the anchor tags with the <code>indicator<\/code> class and then safely add the <code>active<\/code> class.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> indicators = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">'a.indicator'<\/span>);\n<span class=\"hljs-keyword\">const<\/span> resetCurrentActiveIndicator = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> activeIndicator = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\".active\"<\/span>);\n  activeIndicator.classList.remove(<span class=\"hljs-string\">\"active\"<\/span>);\n};\nindicators.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">indicator<\/span>) =&gt;<\/span> {\n  indicator.addEventListener(<span class=\"hljs-string\">'click'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\"><\/span>) <\/span>{\n    resetCurrentActiveIndicator();\n    <span class=\"hljs-keyword\">this<\/span>.classList.add(<span class=\"hljs-string\">'active'<\/span>);\n  });\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>If you are also interested in menus on the side, check out these <a href=\"https:\/\/alvarotrigo.com\/blog\/slide-menus\/\">examples of great side menus<\/a> for your webpage!<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"activating-the-indicators-while-scrolling\">Activating the indicators while scrolling<\/h2>\n\n\n\n<p>If you just tested the code as it is right now, you might\u2019ve notice the awkwardness felt when the you scrolled using the scrollbar and the indicators didn\u2019t get activated. To do this, we can make use of the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Intersection_Observer_API\" target=\"_blank\" rel=\"noopener nofollow\"><code>IntersectionObserver<\/code><\/a> API.  The <code>IntersectionObserver<\/code> class accepts 2 arguments. The first is a callback, and the second is an options object which can be used to configure the behaviour of the observer. The callback will be called whenever the conditions described in the options object are met. For the sake of this tutorial, the only property of the options object that matters is <code>threshold<\/code>.<\/p>\n\n\n\n<p>The <code>threshold<\/code> property can be set to a value or an array, it describes at what percentage of the observed element\u2019s visibility in the viewport should the callback function be fire. The <code>onSectionLeavesViewport<\/code> function creates a <code>IntersectionObserver<\/code> instance that takes a function that contains the logic that will activate the respective indicator. This particular function receives as an input an array of objects <code>entries<\/code>, each object contains information on things like whether or not an intersection is happening.<\/p>\n\n\n\n<p>Finally, to make the <code>IntersectionObserver<\/code> target an element we will call the <code>observe()<\/code> method on <code>observer<\/code> which is a reference to the instance of <code>IntersectionObserver<\/code>.<\/p>\n\n\n\n<p>When about 75% (0.75 threshold) of the observed element (a section) has left the viewport, the callback will be called, and this is when we will reset the active indicator and find the indicator that has to be activated and then activate it. If you want to change when the callback is called, you should alter the <code>threshold<\/code> value.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> sections = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll(<span class=\"hljs-string\">\"section\"<\/span>);\n\n<span class=\"hljs-keyword\">const<\/span> onSectionLeavesViewport = <span class=\"hljs-function\">(<span class=\"hljs-params\">section<\/span>) =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> observer = <span class=\"hljs-keyword\">new<\/span> IntersectionObserver(\n    <span class=\"hljs-function\">(<span class=\"hljs-params\">entries<\/span>) =&gt;<\/span> {\n      entries.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">entry<\/span>) =&gt;<\/span> {\n        <span class=\"hljs-keyword\">if<\/span> (entry.isIntersecting) {\n          resetCurrentActiveIndicator();\n          <span class=\"hljs-keyword\">const<\/span> element = entry.target;\n          <span class=\"hljs-keyword\">const<\/span> indicator = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">`a&#91;href='#<span class=\"hljs-subst\">${element.id}<\/span>']`<\/span>);\n          indicator.classList.add(<span class=\"hljs-string\">\"active\"<\/span>);\n          <span class=\"hljs-keyword\">return<\/span>;\n        }\n      });\n    },\n    {\n      <span class=\"hljs-attr\">root<\/span>: <span class=\"hljs-literal\">null<\/span>,\n      <span class=\"hljs-attr\">rootMargin<\/span>: <span class=\"hljs-string\">\"0px\"<\/span>,\n      <span class=\"hljs-attr\">threshold<\/span>: <span class=\"hljs-number\">0.75<\/span>\n    }\n  );\n  observer.observe(section);\n};\n\nsections.forEach(onSectionLeavesViewport);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id=\"adding-a-fallback-for-old-browsers\">Adding a fallback for old browsers<\/h2>\n\n\n\n<p>Unfortunately, some of the older browsers do not support the <a href=\"https:\/\/caniuse.com\/?search=scroll-behavior\" target=\"_blank\" rel=\"noopener nofollow\"><code>scroll-behavior<\/code><\/a> CSS property. As such, if you wish to support older browsers we can make use of the <code>scrollIntoView<\/code> method. What happens here is we get the element with the <code>href<\/code> attribute that the current element has (which is an id) and then call the method on it.<\/p>\n\n\n\n<p>This isn&#8217;t a 100% solid method to support old browsers, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Element\/scrollIntoView#browser_compatibility\" target=\"_blank\" rel=\"noopener nofollow\"><code>scrollIntoViewOptions<\/code><\/a> for example isn&#8217;t supported in old IE browsers but the only other alternatives are using an external library for smooth scroll, adding a <a href=\"https:\/\/github.com\/iamdustan\/smoothscroll\" target=\"_blank\" rel=\"noopener nofollow\">polyfill<\/a>, or doing the smooth-scroll bit yourself.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-comment\">\/* Collapsed *\/<\/span>\nindicators.forEach(<span class=\"hljs-function\">(<span class=\"hljs-params\">indicator<\/span>) =&gt;<\/span> {\n  indicator.addEventListener(<span class=\"hljs-string\">'click'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\"><\/span>) <\/span>{\n    <span class=\"hljs-built_in\">document<\/span>\n      .querySelector(<span class=\"hljs-keyword\">this<\/span>.getAttribute(<span class=\"hljs-string\">'href'<\/span>))\n      .scrollIntoView({ <span class=\"hljs-attr\">behavior<\/span>: <span class=\"hljs-string\">'smooth'<\/span> });\n    <span class=\"hljs-comment\">\/* Collapsed *\/<\/span>\n  });\n});\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Take a look at the following codepen and see if everything works as expected! It can be a good reference link too, so you could potentially bookmark it for later.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_KKadxbM\" data-src=\"\/\/codepen.io\/anon\/embed\/KKadxbM?height=450&amp;theme-id=1&amp;slug-hash=KKadxbM&amp;default-tab=css,result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed KKadxbM\" title=\"CodePen Embed KKadxbM\" class=\"cp_embed_iframe lazyload\" style=\"width:100%;overflow:hidden\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" data-load-mode=\"1\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>If you are interested in effects like this and more you should take a look at <a href=\"https:\/\/alvarotrigo.com\/fullPage\/\">fullPage<\/a>. It is a JS library that takes care of a lot of the tricky bits for you (like browser support) and provides a more complete set of features like responsive modes, extensions, CSS conditional classes, callbacks etc, which makes it ideal for apps that go beyond the simple effect that we took a look at.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to implement navigation in a cool new way using Javascript and CSS.<\/p>\n","protected":false},"author":1,"featured_media":6037,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[108],"tags":[9,10],"class_list":["post-6038","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-sliders","tag-css","tag-javascript"],"acf":[],"_links":{"self":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6038","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/comments?post=6038"}],"version-history":[{"count":5,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6038\/revisions"}],"predecessor-version":[{"id":9560,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/posts\/6038\/revisions\/9560"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media\/6037"}],"wp:attachment":[{"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/media?parent=6038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/categories?post=6038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alvarotrigo.com\/blog\/wp-json\/wp\/v2\/tags?post=6038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}