Set menu item class

Hello! I would like to give a mobile menu a class. But I don't know where to do this from. To be more specific I am talking about the "home" item. If you go to my site, you will see that the home item has an icon before it, when you reduce the window size, and click the hamburger, the menu item does not have an icon. I want to add a class to the menu item for mobile so that I can set an icon to display on mobile screens. Please help me find where I can set the class of the home item for the mobile menu.
I got the idea from here: https://premium.wpmudev.org/blog/add-icons-wordpress-menus/
Regards,
Mwale

  • Milan

    Hello Mwale

    Hope you are well today and thanks for asking us. :slight_smile:

    Here is selector for "Home" menu.

    li#sidr-id-menu-item-50

    now to apply rules for mobile, you'll need to use breakpoint for mobiles to target that responsiveness.

    You can know more about breakpoints here Mwale
    https://css-tricks.com/snippets/css/media-queries-for-standard-devices/

    Hope this helps you. :slight_smile:
    Best Regards,
    Milan

  • Andrea

    Hello again Mwale!

    It's actually pretty easy. have a look at this amazing tutorial from WPMUdev blog:
    https://premium.wpmudev.org/blog/add-icons-wordpress-menus/

    the trick is that if you look on the top right of the menu editor page, you can click "Screen Options" and then check "CSS classes" which will add a field to the menu items where you can set the class.

    then is all about tweaking a bit the css to make it inline, and that's it. :slight_smile:

  • Andrea

    Hello Mwale,
    I guess that sounds more like a css conflict or something like that. probably the -li- elements on mobiles are styled in a way which crashes the FA icons.
    I would have to see your page in action and explore its code with my browser web-tools.

    in any case, I've just wrote a function because I've remembered that if you use the other method, the class is added to the -li- element but it is obviously better to add it to the -a- link itself.
    but then I thought that it will be even better to actually substitute the Home label with the full FA snippet for displaying the icon, and leave untouched the -li- and -a-.

    as the Home icon is a very common need, I've wrote the function once and for all.
    here it is then:

    /**
     * USE .FA ICON INSTEAD OF HOME IN MENU
     *
     * you must have FontAwesome installed
     * the home tab in menu must be labelled Home
     * this code assumes that your menu has the slug main-menu (otherwise tweak the code accordingly)
     *
     * @param	$nav_menu	{string}	The HTML content for the navigation menu.
     * @param	$args		{object}	An object containing wp_nav_menu() arguments
     *
     * Author: Andrea Piccart
     * Author URI: http://bespokewebdeveloper.com
     */
    add_filter( 'wp_nav_menu', 'bwd_home_icon_in_menu', 10, 2 );
    function bwd_home_icon_in_menu( $nav_menu, $args ) {
    	// apply only on our menu
    	$menu_slug = $args->menu->slug;
    	if ( "main-menu" == $menu_slug ){
    		// substitute the Home label with the icon
    		// note that we ensure that the word Home is followed by the link tag closing, so we know it cannot be a class or whatever else
    		$nav_menu = str_replace( 'Home</a>', '<i class="fa fa-lg fa-home"></i></a>', $nav_menu );
    
    	}
    	// return the nav_menu wheter we changed it or not
    	return $nav_menu;
    
    }
    • Andrea

      Hi Mwale,
      you need to check which is the slug of your menu, and tweak the code accordingly.
      the code assumes that the menu is called main-menu and it makes a conditional to apply only to the menu with slug main-menu.
      so if your menu is called differently, you need to change the code.

      sorry I haven't specified it in the comment because I wrote it in the function description..

      p.s. looking at your website frontend code, I'd guess that the slug of your menu is "main", so you'd have to change "main-menu" in my function, and put only "main"

      p.p.s. then you also have to take off the classes added in the wp admin page. :wink:

    • Andrea

      hello,

      looking at the code of you website from my browser, it seems that your menu is still named "main". where exaclty have you changed it to "header"?

      anyways, when you create a menu you give it a name. you can see the name of your menu when you edit the menu from wp admin. it's written above the menu items..

      then you have to put that name into my code, where I put "main-menu".
      obviously it's a slug, so it have to be small caps and you have to put dashes instead of spaces, if the name has more than one word.
      but I guess your menu is called "main" so the slug will be "main".

  • Mwale

    Andrea I have changed the slug in the code you give me to "main", but nothing, would you like to have access? - its my test website :smiley: . This is my code now:

    add_filter( 'wp_nav_menu', 'bwd_home_icon_in_menu', 10, 2 );
    function bwd_home_icon_in_menu( $nav_menu, $args ) {
    	// apply only on our menu
    	$menu_slug = $args->menu->slug;
    	if ( "main" == $menu_slug ){
    		// substitute the Home label with the icon
    		// note that we ensure that the word Home is followed by the link tag closing, so we know it cannot be a class or whatever else
    		$nav_menu = str_replace( 'Home</a>', '<i class="fa fa-lg fa-home"></i></a>', $nav_menu );
    
    	}
    	// return the nav_menu wheter we changed it or not
    	return $nav_menu;
    
    }
  • Andrea

    wait, I forgot to specify that my filter function has to go in your theme's functions.php file. where are you putting it?

    also, the menu in the footer seem to have the slug "main-1" so if you put "main" in my code, it shouldn't apply to that..

    can you look which is the name for your header menu? when you go to edit it in the admin panel, you should see the name of the menu just above the drag&drop menu items.. what's the name in there?

  • Dimitris

    Hey there Mwale, Andrea,

    hope you're both doing good today! :slight_smile:

    The main issue here is that sidemenu is being generated from your theme by the main header menu.
    So, by using a add_filter( 'wp_nav_menu'....... it will change the main header menu, not the side one.
    I think it would be easier to use some jQuery like

    (function($) {
    $('li#sidr-id-menu-item-50 a').before('<i class="fa fa-lg fa-home"></i>');
    })( jQuery );

    In order to use this snippet, you can use a Custom JS type of plugin. You can find a vast variety in w.org repositories https://wordpress.org/plugins/search.php?q=custom+js

    The li#sidr-id-menu-item-50 ID can be found if you examine the sidemenu elements with Chrome's dev tools.

    Kind regards,
    Dimitris

    • Andrea

      Hi Dimitris,
      thanks for your help!

      I thought about that issue, but it actually depends on how the mobile menu is implemented..
      I mean that the filter could actually work for the mobile menu as well, because it seems retrieving the same wp_menu object, and just applying different classes.

      If I'm not missing something, in that case then the filter will kick in and change the "Home" word for any wp_nav_menu() which calls the menu with slug "main".

      I think it was worth trying, by the way, because the filter would be a cleaner solution in my opinion (in general I try to limit jquery tweaks because it's a bit difficult to keep track of them)

      cheers!

  • Mwale

    Hi Andrea , Dimitris ,
    I appreciate your help on this subject, I have since added the code that Dimitris suggested:

    /* Add your JavaScript code here.
    
    If you are using the jQuery library, then don't forget to wrap your code inside jQuery.ready() as follows:
    
    jQuery(document).ready(function( $ ){
        // Your code in here
    });
    
    End of comment */
    (function($) {
    $('li#sidr-id-menu-item-50 a').before('<i class="fa fa-lg fa-home"></i>');
    })( jQuery );

    I have inserted the code in custom js plugin. It looks like above.

    • Andrea

      Hi Mwale,
      doesn't seem to be working, does it?

      Before starting a debug of that method, could you please have a look at my previous message and see if you are implementing my code correctly? It's because I've tested it and I know it works, so we are just one step from understanding what you are doing wrong and I guess it worth to fix that rather than start over with the debugging of the jquery method..

      please ensure you are placing my code in the right place, and then look at the name of the header menu from wp admin (you can share a screenshot of the page where you edit the header menu if you're not sure where to see the name).

      if this thing of the menu slug is done properly, my code will work for sure on desktop, and is very likely to work on mobile menu too. I'd give a 98% chances that it works even on mobile. :wink:

    • Andrea

      ok thanks! :slight_smile:

      so it seems that the slug of your header menu is indeed "main", therefore the code should apply for it, and definitely don't apply for the footer which ha a different name "main-1"

      so you should have this code in your theme's functions.php

      add_filter( 'wp_nav_menu', 'bwd_home_icon_in_menu', 99, 2 );
      function bwd_home_icon_in_menu( $nav_menu, $args ) {
      	// apply only on our menu
      	$menu_slug = $args->menu->slug;
      	if ( "main" == $menu_slug ){
      		// substitute the Home label with the icon
      		// note that we ensure that the word Home is followed by the link tag closing, so we know it cannot be a class or whatever else
      		$nav_menu = str_replace( 'Home</a>', '<i class="fa fa-lg fa-home"></i></a>', $nav_menu );
      
      	}
      	// return the nav_menu whether we changed it or not
      	return $nav_menu;
      
      }

      then ensure that you have taken off any other leftover from the other attempts (such as classes or scripts). and the code should definitely work for the desktop menu.

      in any case I've set it to have a different priority, so that the filter will be executed later than others that you might have in your theme

      p.s. could you double check the name of your footer menu from the admin page? it should be "Main 1" or something like that..

  • Predrag Dubajic

    Hey guys,

    We don't usually advise giving out login details but since Andrea is long time member of ours I will leave the thread open, I'll just mark it internal so other users don't have access to it in case you want to share email address here, but please don't post WP login even if the thread is internal.

    Mwale please note that Andrea is not staff member so we can't give any guarantees here.

    We appreciate you jumping in here Andrea and if there's anything we can do from our end let us know :slight_smile:

    Best regards,
    Predrag

  • Andrea

    ok so, I've fixed it, and here is an explanation for the sake of history :slight_smile:

    basically the theme uses a single custom function to render both the desktop and the mobile menu at once, using the same menu_id

    this function is probably using some custom helpers and also changes the wp_menu object $args at some point, because they are passed in a structure which is different from the default one.
    therefore my filter wasn't able to retrieve the menu_slug correctly.
    I've managed to make it work by grabbing the menu_location from the $args and using that to target only the main menu (used for mobile and desktop).

    at that point we had another issue though..
    in desktop menu everything was ok but there was also some jquery which was tweaking all the classes of the mobile menu code, and adding a prefix sdir-class-
    so it was changing the classes of our icon and it didn't work anymore..

    So in order to tweak the classes back to the correct .fa format, I had to use a jquery on window.load (the other script was on document.ready).
    I know it's not good practice to add scripts to the wp_footer hook, but in this case I preferred to do it in this way, because it's a very small script and it is kinda of a dirty hack, and I think it's better if this hack is written just below my other function, so that we can always remember that we have added that hack and why we did it.
    also, I decided to don't target the menu-item ID, so that the hack would apply for any .fa element which is in the mobile menu.

    here is the complete code, by the way (which will work only for this very theme, obviously):

    add_filter( 'wp_nav_menu', 'bwd_home_icon_in_menu', 9999, 2 );
    function bwd_home_icon_in_menu( $nav_menu, $args ) {
    	// apply only on our menu
    	//print_r ($args);
    	$menu_location = $args->theme_location;
    	if ( "primary" == $menu_location ){
    		// substitute the Home label with the icon
    		// note that we ensure that the word Home is followed by the link tag closing, so we know it cannot be a class or whatever else
    		$nav_menu = str_replace( 'Home</a>', '<i class="fa fa-lg fa-home"></i></a>', $nav_menu );
    
    	}
    	// return the nav_menu whether we changed it or not
    	return $nav_menu;
    
    }
    /* Inject a jQuery script to tweak the classes which are added by some other jquery to the mobile menu elements
     * basically the theme js is adding prefixes to all the element, including our icon <i class="fa fa-lg fa-home"></i>
     * therefore the icon is not rendered because the classes are wrong.
     * this script loads as the very last thing, and will tweak the classes back to the correct ones
     */
    add_filter('wp_footer', 'bwd_tweak_mobile_home_classes') ;
    function bwd_tweak_mobile_home_classes($content) {
    	$script =<<<'EOT'
    <script>
    jQuery(window).load(function() {
      jQuery('.sidr-class-fa').removeClass( "sidr-class-fa sidr-class-fa-lg sidr-class-fa-home" ).addClass("fa fa-lg fa-home");
    });
    </script>
    EOT;
    	echo $script;
    }

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.