现在的位置: 首页 > wordpress > 正文

改进你的WordPress导航菜单 —— 输出标题描述

2015年05月30日 wordpress ⁄ 共 7809字 ⁄ 字号 暂无评论

在WordPress 3.0中增加了自定义菜单功能,如果你在WordPress后台(外观>菜单)创建一个菜单,你可以在主题中使用wp_nav_menu()函数来显示这些菜单。但是像图中这种带描述的导航菜单还无法简单实现,本文将教你改变WordPress默认的菜单输出结构,打造个性的导航菜单。

首先我们先看下默认的输出结构:

<ul id="menu-main">
    <li><a href="#">首页</a></li>
    <li><a href="#">关于</a></li>
    <li><a href="#">联系</a></li>
    <li><a href="#">博客</a></li>
</ul>

默认的结构根本不可能输出我们想要的效果,所以我们需要改变输出的结果:

<ul id="menu-main">
     <li><a href="#"><strong>首页</strong><span>Home</span></a></li>
     <li><a href="#"><strong>关于</strong><span>About</span></a></li>
     <li><a href="#"><strong>联系</strong><span>Contact</span></a></li>
     <li><a href="#"><strong>博客</strong><span>Blog</span></a></li>
</ul>

准备工作

我们要做的第一件事就是到菜单页面,你会发现每个菜单项都有一个“标题属性”,了解网页都知道这是用来显示鼠标移到链接上后的提示性文字,首先把你希望显示的文字先填上~
编辑标题属性

自定义walker类编辑输出结构

WordPress使用一个特殊的“Walker”类来遍历数据记录并显示出来。幸运的是,我们可以很轻松的创建属于我们自己的“Walker”类从而改变菜单的输出结构。
打开你主题文件中的function.php文件,并添加如下代码:

class description_walker extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth, $args) {
        global $wp_query;
        $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
    
        $class_names = $value = '';
    
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;
    
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $class_names = ' class="' . esc_attr( $class_names ) . '"';
    
        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';
    
        $output .= $indent . '';
        
        $prepend = '';
        $append = '';
        $description  = ! empty( $item->attr_title ) ? '' . esc_attr( $item->attr_title ) . '' : '';

        if($depth != 0) {
            $description = $append = $prepend = "";
            $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
        }
        $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
        $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
    
        $item_output = $args->before;
        $item_output .= '';
        $item_output .= $args->link_before . $prepend . apply_filters( 'the_title', $item->title, $item->ID ) . $append;
        $item_output .= $description . $args->link_after;
        $item_output .= '';
        $item_output .= $args->after;
    
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

那么这个类做了什么呢?这个类在WordPress默认的walker代码(位于wp-includes/nav-menu-template.php)基础上添加了几行代码。现在这个walker会检测是否是顶级菜单,如果是就会输出带有描述的菜单结构。

添加回调函数

现在我们创建了一个自定义的walker类,我们还要做的就是告诉WordPress去使用我们的walker替代默认的。这步非常简单,只要为 wp_nav_menu() 添加walker参数即可:

<?php wp_nav_menu( array('walker' => new description_walker())); ?>

好了,最后为你的菜单添加CSS样式,一起来制作个性的导航菜单吧~

参考文章http://www.kriesi.at/archives/improve-your-wordpress-navigation-menu-output

WordPress 3 has gone gold and ships with an amazing new menu manager that can be used to control the navigation menus of your website. This tutorial will teach you how to change the default output of this manager, since getting a custom output can heavily improve the style of your themes. So first of all here is an example of the wordpress menu we want to build.

How to display the content of the wordpress menu description field

As you can see, instead of a simple list we got the menu item name and below that name is a small description of that menu item. This is currently a rather popular style that unfortunatley can’t be done out of the box by wordpress.

As you may already know, once you have created a menu at your wordpress backend at Appearance > Menus you can use a wordpress function called wp_nav_menu() within your template files to display those menus.

The problem is, the basic output would look something like this:

<ul id="menu-main">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
    <li><a href="#">Blog</a></li>
</ul>

With a basic unordered list like that its almost impossible to create such a menu. So we need to change the output to get this:

<ul id="menu-main">
     <li><a href="#"><strong>Home</strong><span>Starting the journey</span></a></li>
     <li><a href="#"><strong>About</strong><span>What to expect</span></a></li>
     <li><a href="#"><strong>Contact</strong><span>Get in touch!</span></a></li>
     <li><a href="#"><strong>Blog</strong><span> Latest storys</span></a></li>
</ul>

The <strong> tags wrap arround the title whereas the description is put into the <span> tags. Those can be styled easily with CSS later on to create this special menu style.

Preparing the backend

The first thing we need to do is to setup the menu properly in our backend. WordPress already comes with the option to add a description to each menu item, but it is hidden by default.

When you are at the Appearance > Menus Site you need to look at the top right and you will notice a “Screen Option” tab. Click it and you will get the option to display several other input fields for each menu item, among them a checkbox to show the description.

Once that is done,  if you start editing your items you will notice that you can now enter a description for each menu item.

By default wordpress adds a rather long description to menu items that are created by pages, I would recommend to just delete those enourmous novels and just add a few words just like I did.

Now that we have setup the data to display in our backend, its time to prepare the frontend to show that data.

Editing the output by using a custom walker

WordPress uses a special “Walker” class that iterates over each data record and then displays this record accordingly. The cool thing about that is that we can simply create our own custom walker extending that PHP class. That way we dont need to care about fetching the stuff from the database or preparing the data arrays. We only need to extend the part of the wordpress code that outputs the list. So open your functions.php file and add the following code:

class description_walker extends Walker_Nav_Menu
{
      function start_el(&$output, $item, $depth, $args)
      {
           global $wp_query;
           $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';

           $class_names = $value = '';

           $classes = empty( $item->classes ) ? array() : (array) $item->classes;

           $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
           $class_names = ' class="'. esc_attr( $class_names ) . '"';

           $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';

           $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
           $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
           $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
           $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';

           $prepend = '<strong>';
           $append = '</strong>';
           $description  = ! empty( $item->description ) ? '<span>'.esc_attr( $item->description ).'</span>' : '';

           if($depth != 0)
           {
                     $description = $append = $prepend = "";
           }

            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before .$prepend.apply_filters( 'the_title', $item->title, $item->ID ).$append;
            $item_output .= $description.$args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;

            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
            }
}

So what does this Class do? This is basically the walker that wordpress is using (I just copied the source code) and added a few lines in the lower third for a better output: The walker now checks if a description is set, and if thats the case it wraps the description into a span tag and appends it to the navigation title.

The walker also checks if we are currently iterating over a sub menu item or a top level item, since our sub menu items do not need to display a description.

The Function Call

Now that we have created a custom walker we only need to tell wordpress that it should use our walker instead of its own. This can be easily done by calling the wp_nav_menu() with the walker parameter set:

wp_nav_menu( array(
 'container' =>false,
 'menu_class' => 'nav',
 'echo' => true,
 'before' => '',
 'after' => '',
 'link_before' => '',
 'link_after' => '',
 'depth' => 0,
 'walker' => new description_walker())
 );

Thats it. Once that is done your menu will be output with a completly different code structure that you can easily style with CSS to fit your needs. Here is a short snippet to get you startet:

.nav{
height:50px;
padding-left:13px;
margin:0;
padding:0;
list-style-type:none;
list-style-position:outside;
position:relative;
}

.nav a{
display:block;
float:left;
line-height:18px;
outline:medium none;
padding:2px 10px;
text-decoration:none;
width:95px;
min-height: 35px;
}

.nav li a strong {
display:block;
font-size:14px;
font-weight:normal;
}

.nav li a span {
display:block;
font-size:10px;
line-height:14px;
}

I hope you can utilize this knowledge to push the boundaries of beautiful wordpress generated menus ;)

博客主机

博客主机

给我留言

您必须 [ 登录 ] 才能发表留言!

×