Instantly share code, notes, and snippets.
Forked from davidwebca/custom-wp-nav-menu-classes.php
Created
December 8, 2023 17:15
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save prayas-sapkota/8e78f9e43a806dc7d8d06a42f4afa768 to your computer and use it in GitHub Desktop.
Allow adding custom classes to WordPress menu ul, li, a and at different depths. Perfect for TailwindCSS and AlpineJS usage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* WordPress filters to allow custom arguments to wp_nav_menu to, | |
* in turn, allow custom classes to every element of a menu. | |
* | |
* You can apply a class only to certain depth of your menu as well. | |
* | |
* The filters use the depth argument given by WordPress | |
* which is an index, thus starts with level 0 (zero). | |
* | |
* Custom Arguments supported : | |
* link_atts or link_atts_$depth -> Add any attribute to <a> elements | |
* a_class or a_class_$depth -> Add classes to <a> elements | |
* li_class or li_class_$depth -> Add classes to <li> elements | |
* submenu_class or submenu_class_$depth -> Add classes to submenu <ul> elements | |
* | |
* Ex.: add a "text-black" class to all links and "text-blue" class only to 3rd level links | |
* wp_nav_menu([ | |
* 'theme_location' => 'primary_navigation', | |
* 'a_class' => 'text-black', | |
* 'a_class_2' | |
* ... | |
* ]) | |
* | |
* Ex.: More complete example with some TailwindCSS classes and AlpineJS sugar | |
* wp_nav_menu([ | |
* 'theme_location' => 'primary_navigation', | |
* 'menu_class' => 'relative w-full z-10 pl-0 list-none flex', | |
* 'link_atts_0' => [ | |
* ":class" => "{ 'active': tab === 'foo' }", | |
* "@click" => "tab = 'foo'" | |
* ], | |
* 'li_class' => 'w-full', | |
* 'li_class_0' => 'mb-12', | |
* 'a_class' => 'text-sm xl:text-xl text-white border-b hover:border-white', | |
* 'a_class_0' => 'text-3xl xl:text-5xl relative dash-left js-stagger a-mask after:bg-primary', | |
* 'li_class_1' => 'js-stagger a-mask after:bg-primary hidden lg:block', | |
* 'a_class_1' => 'flex h-full items-center uppercase py-2 relative border-white border-opacity-40 hover:border-opacity-100', | |
* 'submenu_class' => 'list-none pl-0 grid grid-cols-1 lg:grid-cols-2 lg:gap-x-12 xl:gap-x-24 xxl:gap-x-32', | |
* 'container'=>false | |
* ]) | |
* | |
* @author davidwebca | |
* @link https://gist.github.com/davidwebca/a7b278bbb0c0ce1d1ec5620126e863bb | |
*/ | |
/** | |
* Add custom attributes or classes to links in wp_nav_menu | |
*/ | |
add_filter( 'nav_menu_link_attributes', function ( $atts, $item, $args, $depth ) { | |
if (property_exists($args, 'link_atts')) { | |
$atts = array_merge($atts, $args->link_atts); | |
} | |
if (property_exists($args, "link_atts_$depth")) { | |
$atts = array_merge($atts, $args->{"link_atts_$depth"}); | |
} | |
if(empty($atts['class'])) { | |
$atts['class'] = ''; | |
} | |
$classes = explode(' ', $atts['class']); | |
/** | |
* Fix for tailwindcss classes that include ":" (colon) | |
* Enter triple underscore hover___text-primary instaed of hover:text-primary | |
* | |
* Some filters provided so that you can customize your own replacements, | |
* passed directly to preg_replace so supports array replacements as well. | |
* | |
* WordPress trac following the issue of escaping CSS classes: | |
* @link https://core.trac.wordpress.org/ticket/33924 | |
*/ | |
$patterns = apply_filters( 'nav_menu_css_class_unescape_patterns', '/___/'); | |
$replacements = apply_filters( 'nav_menu_css_class_unescape_replacements', ':' ); | |
$classes = array_map(function($cssclass) use( $patterns, $replacements) { | |
return preg_replace($patterns, $replacements, $cssclass); | |
}, $classes); | |
if (property_exists($args, 'a_class')) { | |
$arr_classes = explode(' ', $args->a_class); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
if (property_exists($args, "a_class_$depth")) { | |
$arr_classes = explode(' ', $args->{"a_class_$depth"}); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
$atts['class'] = implode(' ', $classes); | |
return $atts; | |
}, 1, 4 ); | |
/** | |
* Add custom classes to lis in wp_nav_menu | |
*/ | |
add_filter( 'nav_menu_css_class', function ( $classes, $item, $args, $depth ) { | |
if (property_exists($args, 'li_class')) { | |
$arr_classes = explode(' ', $args->li_class); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
if (property_exists($args, "li_class_$depth")) { | |
$arr_classes = explode(' ', $args->{"li_class_$depth"}); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
return $classes; | |
}, 1, 4 ); | |
/** | |
* Add custom classes to ul.sub-menu in wp_nav_menu | |
*/ | |
add_filter('nav_menu_submenu_css_class', function( $classes, $args, $depth ) { | |
if (property_exists($args, 'submenu_class')) { | |
$arr_classes = explode(' ', $args->submenu_class); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
if (property_exists($args, "submenu_class_$depth")) { | |
$arr_classes = explode(' ', $args->{"submenu_class_$depth"}); | |
$classes = array_merge($classes, $arr_classes); | |
} | |
return $classes; | |
}, 1, 3); | |
/** | |
* Apply our new custom attributes to widgetized wp_nav_menus | |
*/ | |
add_filter('widget_nav_menu_args', function($nav_menu_args, $nav_menu, $args, $instance) { | |
// if($args['id'] == 'sidebar-footer') { | |
// $nav_menu_args['menu_class'] = 'mt-5 font-alt text-sm font-normal leading-7 opacity-60'; | |
// $nav_menu_args['a_class'] = 'text-gray-300 opacity-60 hover:opacity-100'; | |
// } | |
return $nav_menu_args; | |
}, 10, 4); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment