1

When we add a class to a menu item through dashboard, the css class is added to "li" tag of that item. Is there a way to add these css classes to "a" tag of that item, instead of "li" tag?

enter image description here

As you can see in the picture, I want to have this effect :

<li id="menu-item-290">
    <a  class="my-class" href="http://localhost/en-wptuts/">home</a>
</li> 

instead of this one:

<li id="menu-item-290" class="my-class">
    <a href="http://localhost/en-wptuts/">home</a>
</li>

So is it possible? Thank you in advance.

  • Could you not change your CSS selector from .my-class to .my-class > a? – Tom J Nowell Jun 8 '15 at 14:48
  • I'm actually trying to add font-awesome icons to my anchor elements using dashboard css custom class box and unfortunately that box, adds icons to li tag and not to a tags. – pershianix Jun 8 '15 at 15:30
2

Here are three approaches:

I - Plugin for the a-class- prefix:

We can target the <a> tags with the a-class-... class prefix.

So in your case the way to get:

<li id="menu-item-290" class="blue yellow ...">
    <a class="red pink" href="http://localhost/en-wptuts/">home</a>
</li> 

is to use the following menu classes:

blue yellow a-class-red a-class-pink

We support this with the following plugin:

<?php
/**
 * Plugin Name: Menu Link Classes (I)
 * Description: Target menu link classes with the "a-class-" class prefix.
 * Author:      Birgir Erlendsson (birgire)
 * Plugin URI:  http://wordpress.stackexchange.com/a/190844/26350
 * Version:     0.0.1
 */

/**
 * Remove menu classes with the "a-class-" prefix
 */
add_filter( 'nav_menu_css_class', function( $classes )
{
    return array_filter( 
        $classes, 
        function( $val )
        {
            return 'a-class-' !== substr( $val, 0, strlen( 'a-class-' ) );
        } 
    );
} );

/**
 * Add only "a-class-" prefixed classes to the menu link attribute
 */
add_filter( 'nav_menu_link_attributes', function( $atts, $item )
{
    if( isset( $item->classes ) )
    {
        $atts['class'] = str_replace( 
            'a-class-',
            '',
            join( 
                ' ', 
                array_filter(
                    $item->classes, 
                    function( $val )
                    {
                        return 'a-class-' === substr( $val, 0, strlen( 'a-class-' ) );
                    } 
                ) 
            )
        );
    }
    return $atts;
}, 10, 2 );

II - Plugin for the li-class- prefix:

We can also use the li-class-... class prefix to target the <li> tags instead.

So in your case the way to get:

<li id="menu-item-290" class="blue yellow">
    <a class="red pink" href="http://localhost/en-wptuts/">home</a>
</li> 

is to use the following menu classes:

li-class-blue li-class-yellow red pink

Note that this will move <li> classes to <a> that do not have this prefix.

Here's the plugin to support this:

<?php 
/**
 * Plugin Name: Menu Link Classes (II) 
 * Description: Add classes prefixed with "li-class-" to the li tag, else add it to the a tag.
 * Author:      Birgir Erlendsson (birgire)
 * Plugin URI:  http://wordpress.stackexchange.com/a/190844/26350
 * Version:     0.0.1
 */

/**
 * Only allow li classess that are prefixed with "li-class-"
 */
add_filter( 'nav_menu_css_class', function( $classes )
{
    $newclasses = [];
    foreach( (array) $classes as $class )
    {
        if( 'li-class-' === substr( $class, 0, strlen( 'li-class-' ) ) )
            $newclasses[] = str_replace( 'li-class-', '', $class );
    }
    return $newclasses;

} );

/**
 * Add all classess that aren't prefixed with "a-class-" to the <a> tag
 */
add_filter( 'nav_menu_link_attributes', function( $atts, $item )
{
    if( isset( $item->classes ) )
    {
        $atts['class'] = join( 
            ' ', 
            array_filter(
                $item->classes, 
                function( $val )
                {
                    return 'li-class-' !== substr( $val, 0, strlen( 'li-class-' ) );
                } 
            ) 
        );
    }
    return $atts;
}, 10, 2 );

III - Plugin that moves all optional classes to the <a> tag:

If we use the following optional CSS classes:

blue yellow red pink

then all will be moved to the <a> tag:

<li id="menu-item-290" class="...">
    <a class="blue yellow red pink" href="http://localhost/en-wptuts/">home</a>
</li> 

Note that non-optional classes in <li> are not moved to <a>, so that's why we keep the ... notation in the HTML example above.

Support by the following plugin:

<?php
/**
 * Plugin Name: Menu Link Classes (III)
 * Description: Move all optional classes from the li tag to the a tag.
 * Author:      Birgir Erlendsson (birgire)
 * Plugin URI:  http://wordpress.stackexchange.com/a/190844/26350
 * Version:     0.0.1
 */

/**
 * Only allow li classess that are prefixed with "li-class-"
 */
add_filter( 'nav_menu_css_class', function( $classes, $item )
{
    return array_filter( $classes, function( $val ) use ( $item )
    {
        return ! in_array( $val, (array) $item->wpse_classes ) ;
    } );
}, 10, 2 );

add_filter( 'wp_get_nav_menu_items',  function( $items, $menu, $args )
{
    foreach( $items as $item )
        $item->wpse_classes = $item->classes;

    return $items;
}, 10, 3 );

/**
 * Add all classess that aren't prefixed with "a-class-" to the <a> tag
 */
add_filter( 'nav_menu_link_attributes', function( $atts, $item )
{
    if( isset( $item->wpse_classes ) )
    {
        $atts['class'] = join( 
            ' ', 
            array_filter(
                $item->wpse_classes, 
                function( $val )
                {
                    return 'li-class-' !== substr( $val, 0, strlen( 'li-class-' ) );
                } 
            ) 
        );
    }
    return $atts;
}, 10, 2 );
  • Thank you, but I don't think this is what I wanted. I want to move a class that is specified in dashboard custom css menu class to the anchor tag (instead of li tag). So let's say the admin goes to dashboard and adds a css class to an item and that class is a font-awesome icon (like fa fa-pinterest-p). I want this icon to be added to anchor element of that item and not the li element of that item. – pershianix Jun 8 '15 at 15:38
  • So you don't want to move an optional CSS class from the <li> tag to the <a> tag ? That's what the plugin does. Didn't know you were trying to use font-awesome, but With the above solution you would use a-class-fa a-class-fa-pinterest to target the <a> tag. Note that the plugin removes the a-class- prefix before it's printed to the class attribute in the <a> tag, so it would display as fa fa-pinterest @pershianix – birgire Jun 8 '15 at 16:37
  • Thank you. you're solution is great for situations that I know exactly what font icon I want to use, but I'm looking for a way to just paste a font-awesome icon class to the custom css class field and that class goes to anchor tags. – pershianix Jun 8 '15 at 19:07
  • ok, most likely I'm misunderstanding your explanation regarding the setup ;-) One can paste any class into the custom css field, we just have to prefix it to control where it will show up: <li> or <a>. We could also do this vice-versa (with a little bit of code modification) to use a li-class- prefix instead of the a-class- prefix. Then we will only have to prefix classes that go into the <li> tag and the rest of the classes would show up in the <a> tag. @pershianix – birgire Jun 8 '15 at 19:52
  • Thank you. I think with a custom walker it would be easier but I'm not good at working with walker class. could you help me with that? – pershianix Jun 8 '15 at 20:05
0
add_filter ( 'nav_menu_css_class', 'so_37823371_menu_item_class', 10, 4 );

function so_37823371_menu_item_class ( $classes, $item, $args, $depth ){
  $classes[] = 'nav-item';

  return $classes;
}
function add_link_atts($atts) {
  $atts['class'] = "nav-link";
  return $atts;
}
add_filter( 'nav_menu_link_attributes', 'add_link_atts');
  • 1
    Please edit your answer, and add an explanation: why could that solve the problem? – fuxia Mar 15 '18 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.