今天要解决的问题是,如何给Widget内容增加一个wrapper div,因为需要给内容增加一个样式。

描述一下问题,WordPress的widget html结构一般是这样

<aside class="widget widget_pages">
    <h3 class="widget-title">Title</h3>
    <p>The content of the widget</p>
</aside>

标题结束后立刻就是内容,不管内容是段落还是列表。由于内容没有wrapper div,想单独给内容增加一个背景而不影响到title就有些麻烦,因此想把widget html结构变成下面的样子

<aside class="widget widget_pages">
    <h3 class="widget-title">Title</h3>
    <div class="widget-content">
        <p>The content of the widget</p>
    </div>    
</aside>

用一个class为widget-content的div包围内容。

一个简单但不完美的方法

最简单的方法当然是注册widget的时候就加上这个div,先看代码

register_sidebar( array(
        'name' => __( 'Main Sidebar', TEXTDOMAIN),
        'id' => 'sidebar-1',
        'description' => __( 'Appears on posts and pages', TEXTDOMAIN ),
        'before_widget' => '<aside id="%1$s" class="widget %2$s">',
        'after_widget' => '</div></aside>',
        'before_title' => '<h3 class="widget-title">',
        'after_title' => '</h3><div class="widget-content">',
) );

通过给after_title参数增加<div class="widget-content">,就会在title之后输出一个div的开始标签;再给after_widget传递</div>,就在widget结束之前增加一个div的闭合标签。看起来很简单,很完美。

问题是…widget可以没有标题,当用户选择不输入标题时,after_widget的那个div开始标签就没了,但结束标签却会输出,多了一个结束标签,html结构就会出错,错成什么样,只有老天知道。

用这种方法的主题是有的,比如收费主题DirectoryPress(一款做目录网站的WordPress付费主题),当widget没有title时,对不起样式会出错,不能修改核心代码,只好在widget标题那里填一个空格占个位置。

一个复杂但不会出错的解决方法

上面的方法虽然有问题, 但还是需要的,所以先把上面的代码用上,接下来解决那个错误。

为了解决错误,就需要动态判断一下widget是否输出标题,如果没有输出标题,那就自动加上<div class="widget-content">保证标签配对,代码如下

// if no title then add widget content wrapper to before widget
add_filter( 'dynamic_sidebar_params', 'theme_check_sidebar_params' );
function theme_check_sidebar_params( $params ) {
    global $wp_registered_widgets;

    $settings_getter = $wp_registered_widgets[ $params[0]['widget_id'] ]['callback'][0];
    $settings = $settings_getter->get_settings();
    $settings = $settings[ $params[1]['number'] ];

    if ( isset( $settings[ 'title' ] ) && empty( $settings[ 'title' ] ) )
        $params[0][ 'before_widget' ] .= '<div class="widget-content">';
    return $params;
}

问题是…

WordPress自带的widget有默认标题,即使用户什么都不写,标题也会输出,但上面的程序会认为没有标题,导致多一个div的开始标签,怎么办?

恐怕很难完美,所以我选择的方式是去掉默认标题,如果你不填标题,不管什么widget都不会输出标题,代码如下。

//Remove default title
add_filter('widget_title', 'theme_remove_default_title',10, 2);
function theme_remove_default_title( $title, $instance){
   $title = $instance['title'];
   return $title;
}

把这三段代码都放进functions.php,这个给widget内容增加wrapper div的问题就解决了。

或者

也可以给所有没有标题的widget加一个标题,让标题内容是一个空格。所以,用方法一中的代码加上下面这段代码也是一种解决问题的手段。

add_filter('widget_title', 'theme_remove_default_title',10, 2);
function theme_remove_default_title( $title, $instance){
   $title = $instance['title'];
   if( empty($title) ) $title = "&nbsp";
   return $title;
}

参考资料

Adding a div to wrap widget content after the widget title

 

13条留言

  1. SOLA,请问以上的代码要在哪里添加呢?function.php吗?

      1. SOLA,我加了以上的代码了,但是没有启作用啊,到底要加多少的代码上去呢,都是在那个FUNCTION上面添加吗?

        1. 我不知道你具体怎么做的,也不知道什么不起作用,最少上面说了三种方法,有的设计到注册widget过程,有的不涉及。所以你最好注册一个新的widget,用firebug看一下结构确实生效了,再考虑下面的东西。

          1. SOLA,注册一个新的widget是不是在一个简单但不完美的方法下面的代码呢?
            还有把这三段代码都放进functions.php 里,你是指哪三段呢:我想要
            所有没有标题的widget加一个标题,让标题内容是一个空格的这种方案
            是不是这三段呢?如下
            1:
            register_sidebar( array(
            ‘name’ => __( ‘Main Sidebar’, TEXTDOMAIN),
            ‘id’ => ‘sidebar-1’,
            ‘description’ => __( ‘Appears on posts and pages’, TEXTDOMAIN ),
            ‘before_widget’ => ”,
            ‘after_widget’ => ”,
            ‘before_title’ => ”,
            ‘after_title’ => ”,
            ) );

            2:
            // if no title then add widget content wrapper to before widget
            add_filter( ‘dynamic_sidebar_params’, ‘theme_check_sidebar_params’ );
            function theme_check_sidebar_params( $params ) {
            global $wp_registered_widgets;
            $settings_getter = $wp_registered_widgets[ $params[0][‘widget_id’] ][‘callback’][0];
            $settings = $settings_getter->get_settings();
            $settings = $settings[ $params[1][‘number’] ];
            if ( isset( $settings[ ‘title’ ] ) && empty( $settings[ ‘title’ ] ) )
            $params[0][ ‘before_widget’ ] .= ”;
            return $params;
            }

            3:
            add_filter(‘widget_title’, ‘theme_remove_default_title’,10, 2);
            function theme_remove_default_title( $title, $instance){
            $title = $instance[‘title’];
            if( empty($title) ) $title = “&nbsp”;
            return $title;
            }

            把它们全部都写到function里面去是吗?

            但是添加后会报错:Warning: Missing argument 2 for theme_remove_default_title()

            请问怎么修改呢?

    1. function theme_remove_default_title你传了一个参数?
      我试过这代码,不会报错。
      第一段是注册widget,应该去你主题找,不要拷贝这里的。我用这方法是因为主题注册widget的时候多加了个div,你又是为何?

      1. 好的,是传参的问题,没有传第二个参数,就是要修改为自己的主题名,好象理解了,我再去试试

        1. 哎,还是搞不定,不知道在哪里修改,在主题哪里修改呢

      2. SOLA这个问题搞定了,谢谢

  2. 问题是…widget可以没有标题,当用户选择不输入标题时,after_widget的那个div开始标签就没了,但结束标签却会输出,多了一个结束标签,html结构就会出错,错成什么样,只有老天知道。
    ————
    after_widget的那个div开始标签就没了
    是title?

    1. 是after_title的div不输出了,被你发现了,哈哈,我写的东西真是给我自己看的

      1. 所以看评论是很重要的,不论对作者还是读者

        1. 那要有评论可看才行,我的评论一向比较少~~~~(>_<)~~~~

评论功能已关闭