Brug wp_nav_menu i WordPress-temaer

Tilpas mark-up af WordPress-menuer - så bliver det nemmere at lave styling til flere forskellige menuer på samme site.

Den helt enkle måde at bruge WordPress' menuer i et tema er at placere wp_nav_menu() i en tema-fil - så vises enten

  • den første menu der er oprettet via Kontrolpanel > Udseende > Menuer, eller (hvis man ikke har defineret en menu)
  • en menu indeholdende alle sider (men ikke kategorier).

Kontrolpanel > Udseende > Menuer

Hvis menuen er defineret som vist ovenfor, genererer wp_nav_menu() følgende markup:

<div class="menu-menu-container">
  <ul id="menu-menu" class="menu">
    <li id="menu-item-1" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1">
      <a href="http://stickleback.dk/">Forside</a>
    </li>
    <li id="menu-item-2" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2">
      <a href="http://stickleback.dk/category/nyheder/">Nyheder</a>
   </li>
  </ul>
</div>

og så får man diverse css-classes forærende som man kan style på:

.menu-menu-container {}
.menu {}
.menu-item {}
.menu-item a {}

Dette er fint hvis man bare har en enkelt menu på sit site. Har man flere menuer der skal se forskellige ud, eller hvis man vil bruge et framework som f.eks. Bootstrap eller Foundation, er der brug for yderligere tilpasning.

Definér menuer og tema­områder

Hvis man skal have flere menuer på et website på et website, så skal man kunne oprette dem via kontrolpanelet og tilknytte dem til et temaområde.

I vores tilfælde vil vi gerne have en header- og en sidebar-menu. Vi starter med at definere menu-/temaområder i functions.php:

function register_my_menus() {
  register_nav_menus(
    array(
      'header-menu' => 'Header Menu',
      'sidebar-menu' => 'Sidebar Menu'
    )
  );
}
add_action( 'init', 'register_my_menus' );

og derefter skal hver af menuerne placeres i den rigtige temafil, f.eks. header-menuen i header.php:

wp_nav_menu( array( 'theme_location' => 'header-menu' ) );

Tilpas header-menuen

I stedet for at bruge WordPress' default-indstillinger, kan man tilpasse header-menuen så man selv kan bestemme hvilken markup der bliver genereret:

  $defaults = array(
  	'theme_location'  => 'header-menu',
	  'container'       => 'nav',
	  'container_class' => 'main-navigation',
	  'menu_class'      => 'inline-list',
	  'fallback_cb'     => false,
	  'items_wrap'      => '<ul class="%2$s">%3$s</ul>'
);
wp_nav_menu( $defaults );

I dette eksempel er theme_location temaområdet som vi definerede ovenfor. Container-elementet som menuen bliver placeret i er en <nav class="main-navigation"> og menupunkterne bliver placeret i en <ul class="inline-list">.

Hvis en menu som er tilknyttet et temaområde alligevel ikke skal bruges og derfor deaktiveres i kontrolpanelet, så vil WordPress som default i stedet danne en menu bestående af alle websitets sider, hvilket normalt ikke er ønskeligt. For at undgå dette tilføjes 'fallback_cb' => false.

Bemærk at 'items_wrap' ikke må være tom. Default er:

'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',

%1$s svarer til 'menu_id'
%2$s svarer til 'menu_class'
%3$s svarer til linket i menuen

Som minimum skal der stå: 'items_wrap' => '%3$s' Uden dette vil menuen ikke virke.

Markup:

<nav class="main-navigation">
  <ul class="inline-list">
    <li id="menu-item-1" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1">
      <a href="http://stickleback.dk/">Forsiden</a>
    </li>
    <li id="menu-item-2" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2">
      <a href="http://stickleback.dk/category/nyheder/">Nyheder</a>
    </li>
  </ul>
</nav>

css:

 .main-navigation {}
 .inline-list {}
 .menu-item {}
 .main-navigation a {}

Tilpas sidebar-menuen

$defaults = array(
    'theme_location'  => 'sidebar-menu',
	'container'       => 'div',
	'container_class' => 'sidebar-menu',
	'menu_class'      => 'no-bullet',
	'fallback_cb'     => false,
	'items_wrap'      => '<ul class="%2$s">%3$s</ul>',
	'depth'           => 1
);
wp_nav_menu( $defaults );

Denne menu er placeret i en <div> og ul-elementet har fået "no-bullet"-class. 'depth' => 1 betyder at evt. undermenupunkter ikke vil blive vist.

Markup:

<div class="sidebar-menu">
  <ul class="no-bullet">
    <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-1">
      <a href="http://stickleback.dk/">Forsiden</a>
    </li>
    <li class="menu-item menu-item-type-post_type menu-item-object-post current-menu-item menu-item-2">
      <a href="http://stickleback.dk/hej-verden/">Hej Verden!</a>
    </li>
  </ul>
</div>

css:

.sidebar-menu {}
.no-bullet {}
.menu-item {}
.sidebar-menu a {}

Bemærk at man ikke umiddelbart kan tilføje en css-class til selectorne <li> eller <a>.

'current' eller 'active'?

WordPress tilføjer automatisk class="current" til menuen, når man navigerer rundt på siden. Hvis man foretrækker en anden class kan den ændres således, i functions.php:

add_filter('nav_menu_css_class', 'special_nav_class', 10 , 2);
function special_nav_class($classes, $item) {
  if ($item->current == 1 ||$item->current_item_ancestor == true) {
    $classes[] = 'active';
  }
return $classes;
}

Dette er f.eks. nødvendigt i Foundation, der forventer class="active" på det aktive menpunkt.

Læs mere:

Function Reference/wp nav menu - tilpas menuer, se eksempler
WordPress-menu CSS - til styling af WordPress-menuer