Silex icon indicating copy to clipboard operation
Silex copied to clipboard

Active menu for 1 page websites

Open lexoyo opened this issue 8 years ago • 6 comments

About the active menu widget

This is an active menu. It is a set of links linking to anchors:

  • click on a link to scroll to an anchor
  • when you scroll and reach an anchor, the link style changes
  • when the page is loaded and the anchor name is in the URL (e.g. mysite.com#anchor1), then scroll to the anhor

Setup an active menu in your site

Add the widget script to your website

Paste this Javascript code into Silex "JS scripts editor"


/*
 * active menu widget for Silex
 * create an element which links to an anchor, e.g. an element with a link to #anchor1
 * add the css class "anchor-link" to this element
 * create an element which is the anchor, e.g. an element with the css class "anchor1"
 * when the user clicks on the link, the scroll slides until the element is visible
 * when the user slides and the element is visible, the link gets a css class "active-menu"
 */
$(function() {
    // Cache selectors
    var lastId,
        // All list items
        menuItems = $(".anchor-link"),
        // Anchors corresponding to menu items
        // find the name of the elements which are anchors
        scrollItems = menuItems.map(function(){
            // the names are in the href attribute of the anchor links
            var attr = $(this).attr("data-silex-href") || $(this).attr("href");
            // case of a link in text field or an external link after publish
            $(this).find("[href]").each(function() {
                attr = $(this).attr("href");
            });
            // case of an "external link" before publish
            $(this).find("[data-silex-href]").each(function() {
                attr = $(this).attr("href");
            });
            // the links to anchors are expected to start with #
            if(attr && attr.indexOf("#") === 0) {
                var name = attr.substring(attr.lastIndexOf("#") + 1);
                // exclude page names (#!page-)
                if(name.indexOf("!page") !== 0) {
                    var item = $("." + name);
                    // check if there is a hash in the URL to scroll to the anchor at start
                    if(window.location.hash.indexOf("#" + name) > 0) {
                        var offsetTop = item.offset().top;
                        $('html, body').stop().animate({
                            scrollTop: offsetTop
                        }, 300);
                    }
                    // now find the element itself, which has the name as a css class
                    if (item.length) { 
                        return {
                            "link": this,
                            "item": item.get(0)
                        };
                    }
                }
            }
        });
    // Bind click handler to menu items
    // so we can get a fancy scroll animation
    scrollItems.each(function() {
        var link = this.link;
        var item = this.item;
        $(link).click(function(e){
            // leave time for the page to open
            // and then scroll
            setTimeout(function() {
              var offsetTop = $(item).offset().top;
              $('html, body').stop().animate({
                  scrollTop: offsetTop
              }, 300);
              e.preventDefault();
            }, 100);
        });
    })

    // Bind to scroll
    $(window).scroll(function(){
       // Get container scroll position
       var fromTop = $(this).scrollTop();
       // Get id of current scroll item
       var cur = scrollItems.map(function(){
         if ($(this.item).offset().top <= fromTop)
           return this;
       });
       // add the css class on the current menu item
       $(".active-menu").removeClass("active-menu");
       if(cur.length > 0) {
           cur = cur[cur.length-1];
           $(cur.link).addClass("active-menu");
       }
    });
});

Add a link to an anchor

Create an element, for example a text field. And add a link to it: in the properties, select "external link" and type #anchor1.

screenshot from 2016-05-15 23-24-57

Also add the CSS class anchor-link to this element (switch to advanced mode, and paste "anchor-link" in the text field "CSS classes".

Open the CSS styles editor in Silex and add style for the "active" state of the link. For example:

.active-menu {
    background-color: red;
}

screenshot from 2016-05-15 23-25-17

Add an anchor to your site

Create an element which is the anchor, for example a container, and add the css class anchor1 to it.

screenshot from 2016-05-16 00-04-36

Test your active menu

You will probably want to make the main container of your website very high to test this widget, so select the main container and type 10000 in the "height" property.

Also, since you want to see your menu change while scrolling, you should put your link element in a container with a CSS class like "static-element", and this CSS in the CSS style editor

.static-element {
    border-top: 3px solid #333;
}

Save your site and preview it, then click on the link or scroll and see the link change.

  • when the user clicks on the link, the scroll slides until the element is visible
  • when the user slides and the element is visible, the link gets a css class "active-menu"

screenshot from 2016-05-16 00-00-05 screenshot from 2016-05-15 23-49-33

Related widgets

lexoyo avatar May 15 '16 22:05 lexoyo

Thanks. 2 questions :

  • my menu is 50px high : how to shift the position of the anchor1 (usually i put the anchors on the titles)
  • it's not working with my menu
<ul>
    <li><a href="#anchor0">Home</a></li>
    <li><a href="#anchor1">What we do</a></li>
    <li><a href="#anchor2">What we are</a></li>
    <li><a href="#anchor3">Contact</a></li>
</ul>

because it's not an external link?

ceubri avatar May 17 '16 11:05 ceubri

in your case you should set anchor-link in the CSS class of each <a>:

<a href="#anchor0" class="anchor-link">Home</a>

lexoyo avatar May 17 '16 12:05 lexoyo

Great it works !

ceubri avatar May 17 '16 15:05 ceubri

Is there a way to make an active menu on a multi page website? I have tried adding an html element, but the links do not work properly and take me to the home page. I have also tried this code here but again does the same thing and takes me to the home page.

Hizar avatar Oct 22 '16 03:10 Hizar

Hi Can you share your experiment? I will figure out what you want to do and test what is happening

lexoyo avatar Oct 22 '16 09:10 lexoyo

@lexoyo

Impossible à mettre en place, ne fonctionne pas ou plus ?

Voici un lien:

https://keen-pie-1a41ac.netlify.app/

BaguetteAgile avatar Jul 07 '22 14:07 BaguetteAgile