Pages

July 5, 2017

Custom responsive site nav menu for Avicia theme

Objective


We picked Avicia theme for SharePoint 2013 to implement a custom portal site. The goal is to have a heavily customized responsive site, with a lot of custom client-side components but still inherit the OOB SharePoint layout and maintainability.
On top of that we wanted to add more css styling to the page that will force all nav menus to be horizontal. The challenge was to keep the horizontal top level menu items but enforce vertical 2nd level menu items. Then we wanted to have a custom dynamic anchor ‘arrow’ on top of each 2nd level menu.

On the left: navigation using Avicia theme. On the right: after applying custom script & styles.


What is Avicia?
  • A custom theme for SharePoint 2013 on-Premises & Office 365
  • Responsive columnar site theme using HTML5 & CSS2/CSS3
  • Top dynamic navigation
  • Suitable for SharePoint 2013 Publishing sites
For details check these sources:


Procedure

1)  Create new file "NavDropdownMenuScript.js"
To control top position of 2nd level menu: Change ‘top’ property inside ul.dynamic class (Ex: “47px”). To control position of anchor: Change ‘top’ property inside dropdown-anchor class (Ex: “27px”). Also change this property: $FirstLevelMenuItem.children[0].style.left = "5px";
/* Script for nav dropdown menu */
/* Developed by Ibraheem I.     */
/* v3.2 2017                    */


$(document).ready(function () {
    insertAnchorForLevel2Items();
});
   
function insertAnchorForLevel2Items() {
    var FirstLevelMenu;
    var $FirstLevelMenuItem;
    $FirstLevelMenu = $("ul[id$='RootAspMenu']").children().children("ul");

    $FirstLevelMenu.children().each(function () {
        $FirstLevelMenuItem = $(this); // <li>
        $FirstLevelMenuItem.attr('NavMenuLevel', '1');

        // create hidden anchor for each target 2nd level menu 
        $anchor = $('<div class="dropdown-anchor"></div>');
        $FirstLevelMenuItem.prepend($anchor);// insert anchor right before <ul>

        // force 2nd level menu to show in vertical fashion
        $SecondLevelMenu = $FirstLevelMenuItem.find("ul");
        $SecondLevelMenu.attr('style', 'display: block !important; background-color: #707070;');

        // set class for each 2nd level menu item <li>
        $SecondLevelMenu.children().each(function () {
            $SecondLevelMenuItem = $(this);
            $SecondLevelMenuItem.addClass("secondlevelmenuitem");
        });

        // show anchor when isVisible added , otherwise hide it
        $FirstLevelMenuItem.on("DOMAttrModified", function (e) {
            attrName = e.originalEvent.attrName.toLowerCase();
            if (attrName == "isvisible") {
                $FirstLevelMenuItem = e.originalEvent.srcElement; // for IE
                if ($FirstLevelMenuItem == undefined) {
                    $FirstLevelMenuItem = e.originalEvent.target; // for Firefox
                }
                if ($FirstLevelMenuItem.tagName.toLowerCase() == "li") {
                    switch (e.originalEvent.attrChange) {
                        case MutationEvent.ADDITION:
                            $FirstLevelMenuItem.children[0].style.left = "5px"; // show anchor
                            break;
                        case MutationEvent.REMOVAL:
                            $FirstLevelMenuItem.children[0].style.left = "-9999px"; // hide anchor
                            break;
                    };
                }

            }
        });

    });

}
 



2) Create new file "NavDropDownMenuStyles.css"
To control top position of 2nd level menu: change ‘top’ property inside ul.dynamic class (Ex: “47px”)

/* Styles for nav dropdown menu */
/* Developed by Ibraheem I.     */
/* v2.3 2017                    */


/* overwrite some classes from Avicia.css */
nav ul, nav.menu1 {
                        max-height: none;
}

.dynamic li {
                        margin-top: 0px;
                        text-align:left;
                        vertical-align:middle;
                        padding: 5px 10px 5px 10px;
    /*margin: 5px 10px 5px 10px;*/
}

nav a:hover span {
                        color:White;
}

.ms-navedit-flyoutArrow span {
                        vertical-align:middle;
}

.menu-item-text span {
                        vertical-align:middle;
}

/******************************************/
li.static{
    min-height: 47px;
}

.secondlevelmenuitem {
    float: none;
    white-space: nowrap;
    margin-bottom:auto;
}

/* to remove the arrow icon next to SharePoint nav item */
.ms-core-listMenu-horizontalBox .additional-background.dynamic-children {
                        background-image: none;
}

.dynamic li:hover {
                        background-color: #333333;
}

ul.dynamic {
                        padding: 0px;
                        margin: 0px;
                        top: 61px !important;
    width: auto !important;
}

.dropdown-anchor {
                        position:relative;
                        border:10px solid; /*will increase width of "People" <li> by (border x 2) */
                        border-top-color:transparent;
                        border-right-color:transparent;
                        border-left-color:transparent;
                        border-bottom-color:#707070;
                        z-index: 1500;
                      left: -9999px;
                      top: 39px;
                        max-width: 0px;
}




3) Upload the 2 files and publish each one to major version if possible:

/SiteAssets/NavDropdownMenu/NavDropDownMenuStyles.css
/SiteAssets/NavDropdownMenu/NavDropdownMenuScript.js


4) Edit Avicia.css to fix height issue with the 2nd level drop down menu for mobile view. Remove height property applied to "nav ul" in following styles:
  • @media only screen and (max-width: 767px)
  • @media only screen and (min-width: 480px) and (max-width: 767px)
  • @media only screen and (max-width: 479p)


5) Edit Avicia.master to add the following lines under <body> tag:

<script type="text/javascript" src="{SiteUrl}/SiteAssets/NavDropdownMenu/NavDropdownMenuScript.js?rev=1"></script>
<link rel="stylesheet" type="text/css" href="/{SiteUrl}/SiteAssets/NavDropdownMenu/NavDropDownMenuStyles.css?rev=1" />

Note: Alternatively you can add those lines to script editor web part for testing.

Also, you have to inject jquery library to Avicia.master if it does not include it already:
<script type="text/javascript" src="/_layouts/15/jquery-1.11.2.min.js"></script>


6) Publish both Avicia.master & Avicia.css to major versions.


That's it! Now when user hover on nav items, the custom menu anchor shows quickly alongside the dropdown menu.