18

I would like to remove or hide the Biography input field from the profile page. How do you do this? I already removed some contact methods from this page, but I'm not sure how to get rid of the biography.

5 Answers 5

22

There is no dedicated hook – user management is a low priority in WordPress. You have to use output buffering (yes, not nice).

Here is a simple demonstration how this could be done:

add_action( 'personal_options', array ( 'T5_Hide_Profile_Bio_Box', 'start' ) );

/**
 * Captures the part with the biobox in an output buffer and removes it.
 */
class T5_Hide_Profile_Bio_Box
{
    /**
     * Called on 'personal_options'.
     *
     * @return void
     */
    public static function start()
    {
        $action = ( IS_PROFILE_PAGE ? 'show' : 'edit' ) . '_user_profile';
        add_action( $action, array ( __CLASS__, 'stop' ) );
        ob_start();
    }

    /**
     * Strips the bio box from the buffered content.
     *
     * @return void
     */
    public static function stop()
    {
        $html = ob_get_contents();
        ob_end_clean();

        // remove the headline
        $headline = __( IS_PROFILE_PAGE ? 'About Yourself' : 'About the user' );
        $html = str_replace( '<h2>' . $headline . '</h2>', '', $html );

        // remove the table row
        $html = preg_replace( '~<tr>\s*<th><label for="description".*</tr>~imsUu', '', $html );
        print $html;
    }
}

You can download the code as a standalone plugin: Plugin Remove Bio Box.

The password fields are now under Contact Info … if you don’t like that, add a headline in stop() – and take care for I18n. ;)

5
  • This is very useful to me, and just what I was after. Thank you!
    – Marc
    Jan 16, 2012 at 8:45
  • 1
    Nice. Haven't known about the IS_PROFILE_PAGE constant :)
    – Anh Tran
    Jan 19, 2012 at 9:31
  • This does not work with 4.6.1
    – realtebo
    Nov 15, 2016 at 14:09
  • @realtebo Yes, the <h3> is a <h2> now. I've fixed the code.
    – fuxia
    Nov 15, 2016 at 22:17
  • This seems like a very heavy-handed way to deal with this as it adds a performance hit. My css based answer below is a much more simple and effective solution without any notable performance hit. Apr 27, 2021 at 11:12
8

The simplest and most lightweight solution is to use CSS to just hide it from view.

.user-description-wrap {
   display: none;
}
7

Since the recent class change this works:

add_action( 'personal_options', array ( 'T5_Hide_Profile_Bio_Box', 'start' ) );

/**
 * Captures the part with the biobox in an output buffer and removes it.
 *
 * @author Thomas Scholz, <[email protected]>
 *
 */
class T5_Hide_Profile_Bio_Box
{
    /**
     * Called on 'personal_options'.
     *
     * @return void
     */
    public static function start()
    {
        $action = ( IS_PROFILE_PAGE ? 'show' : 'edit' ) . '_user_profile';
        add_action( $action, array ( __CLASS__, 'stop' ) );
        ob_start();
    }

    /**
     * Strips the bio box from the buffered content.
     *
     * @return void
     */
    public static function stop()
    {
        $html = ob_get_contents();
        ob_end_clean();

        // remove the headline
        $headline = __( IS_PROFILE_PAGE ? 'About Yourself' : 'About the user' );
        $html = str_replace( '<h3>' . $headline . '</h3>', '', $html );

        // remove the table row
        $html = preg_replace( '~<tr class="user-description-wrap">\s*<th><label for="description".*</tr>~imsUu', '', $html );
        print $html;
    }
}
3
  • 1
    I just suggest to change this $headline = __( IS_PROFILE_PAGE ? 'About Yourself' : 'About the user' ) into this $headline = ( IS_PROFILE_PAGE ? __('About Yourself') : __('About the user' ));
    – realtebo
    Nov 15, 2016 at 14:13
  • Also: the headline is now into an <h2> tag
    – realtebo
    Nov 15, 2016 at 14:15
  • This seems like a very heavy-handed way to deal with this as it adds a performance hit. My css based answer below is a much more simple and effective solution without any notable performance hit Apr 27, 2021 at 11:12
2

Building on the previous answers, here is what I'm using to remove the parts of the User page I don't want:

$pagesToAffect = [
    '/wp-admin/user-edit.php',
    '/wp-admin/profile.php'
];

if (isset($PHP_SELF) && in_array($PHP_SELF, $pagesToAffect)) {
    add_action('admin_head', [UserProfileCleaner::class, 'start']);
    add_action('admin_footer', [UserProfileCleaner::class, 'finish']);
    add_filter('user_contactmethods',[UserProfileCleaner::class, 'hideInstantMessaging'],10000,1);
}

class UserProfileCleaner {
    public static function start() {
        ob_start(function($buffer) {
            // Personal Options
            if (!IS_PROFILE_PAGE) {
                $startHeading = 'Personal Options';
                $pattern = "@<(h[0-9]) ?[^>]*?>".preg_quote(_x($startHeading))."</\\1 ?>@is";
                preg_match($pattern, $buffer, $start, PREG_OFFSET_CAPTURE);

                $endHeading = 'Name';
                $pattern = "@<(h[0-9]) ?[^>]*?>".preg_quote(_x($endHeading))."</\\1 ?>@is";
                preg_match($pattern, $buffer, $end, PREG_OFFSET_CAPTURE);

                if (isset($start[0][1]) && isset($end[0][1]) && $start[0][1]<$end[0][1]) {
                    $buffer = substr($buffer, 0, $start[0][1]).substr($buffer,$end[0][1]);
                }
            }

            $buffer = self::removeSectionHeading($buffer, 'Name');
            $buffer = self::removeSectionHeading($buffer, 'Contact Info');

            $buffer = self::removeSectionHeading($buffer, 'Additional Capabilities');
            $buffer = self::removeSectionRow($buffer, 'Capabilities');

            $buffer = self::removeSectionHeading($buffer, 'Forums');

            // About / Bio
            $heading = IS_PROFILE_PAGE ? 'About Yourself' : 'About the user';
            $buffer = self::removeStandardSection($buffer, $heading);

            // Yoast
            $heading = 'Yoast SEO Settings';
            $buffer = self::removeStandardSection($buffer, $heading);

            $heading = 'Memberships';
            $pattern = "@<(h[0-9]) ?[^>]*?>".preg_quote(_x($heading))."</\\1 ?>.*?</p>@is";
            $buffer = preg_replace($pattern, "", $buffer, 1);

            return $buffer;
        });
    }

    private static function removeStandardSection($buffer, $heading) {
        $pattern = "@<(h[0-9]) ?[^>]*?>".preg_quote(_x($heading))."</\\1 ?>.*?</table>@is";
        return preg_replace($pattern, "", $buffer, 1);
    }

    private static function removeSectionHeading($buffer, $heading) {
        $pattern = "@<(h[0-9]) ?[^>]*?>".preg_quote(_x($heading))."</\\1 ?>@is";
        return preg_replace($pattern, "", $buffer, 1);
    }

    function removeSectionRow($buffer, $heading) {
        $pattern = "@<tr ?[^>]*?>[^<]*?<th ?[^>]*?>[^<]*?".preg_quote(_x($heading))."[^<]*?</th ?[^>]*?>.*?</tr ?>@is";
        return preg_replace($pattern, "", $buffer, 1);
    }

    public static function finish() {
        ob_end_flush();
    }

    public static function hideInstantMessaging( $contactmethods ) {
        unset($contactmethods['googleplus']);
        unset($contactmethods['twitter']);
        unset($contactmethods['facebook']);
        return $contactmethods;
    }
}

It's still reliant on the structure of the HTML, but it works for me.

2
  • How can I remove website from user-new.php? I added the page to $pagesToAffect and removed website as a row, but it's still there.
    – Jason
    Sep 24, 2017 at 9:55
  • This seems like a very heavy-handed way to deal with this as it adds a performance hit. My css based answer is a much more simple and effective solution without any notable performance hit Apr 27, 2021 at 11:12
0

If you add the below code to your functions.php file, it will remove the bio section for all languages of a multi-language site:

//remove the bio
function remove_plain_bio($buffer) {
    $titles = array('#<h3>'._x('About Yourself').'</h3>#','#<h3>'._x('About the user').'</h3>#');
    $buffer=preg_replace($titles,'<h3>'._x('Password').'</h3>',$buffer,1);
    $biotable='#<h3>'._x('Password').'</h3>.+?<table.+?/tr>#s';
    $buffer=preg_replace($biotable,'<h3>'._x('Password').'</h3> <table class="form-table">',$buffer,1);
    return $buffer;
}
function profile_admin_buffer_start() { ob_start("remove_plain_bio"); }
function profile_admin_buffer_end() { ob_end_flush(); }
add_action('admin_head', 'profile_admin_buffer_start');
add_action('admin_footer', 'profile_admin_buffer_end');
1
  • This seems like a very heavy-handed way to deal with this as it adds a performance hit. My css based answer is a much more simple and effective solution without any notable performance hit Apr 27, 2021 at 11:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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