How to create an author widget in WordPress Without Plugin

How to create an author widget in WordPress

How to create an author widget in WordPress Without Plugin

Let say you are a blogger and looking for a way for your audience to get to know who you are, and your blogging platform is WordPress the easiest way to achieve that is by using a plugin.

However, there is nothing wrong with using a plugin, although, that adds an extra plugin to your website with a slim chance of some unnecessary resources loaded and custom CSS code to ensure the out of the author plugin match your theme.

Nonetheless, in this blog post, I will be showing you how to create a custom How to create an author widget in WordPress Without Plugin so let get started. We will need to create two files named author-widget.php and author-fields.php I like to have a folder in my theme called includes or inc which contains all my includes files and include them in my widgets.php like the image below.

How to create an author widget in WordPress

In our author-widget.php we have to extend the WordPress Widget class and register our custom widget in our theme as we did below.

add_action('widgets_init', 'juliette_author_register');

function juliette_author_register() {

class Juliette_Author_Widget extends WP_Widget {

    public function __construct() {
                'Juliette_Author_Widget', esc_html__(' Juliette Author Box', 'juliette-wp'), array(
                'description' => esc_html__('Show Author Profile', 'juliette-wp')

We will then create a function that holds the fields for your author widget. Since our aim is to create an author widget the following are the fields will be creating author name, author description, author profile image, and four social media handle fields.

private function widget_fields() {
        $fields = array(
            'juliette_author_name' => array(
                'juliette_widgets_name' => 'juliette_author_name',
                'juliette_widgets_title' => esc_html__('Author Name', 'juliette-wp'),
                'juliette_widgets_field_type' => 'text',
            'juliette_author_desc' => array(
                'juliette_widgets_name' => 'juliette_author_desc',
                'juliette_widgets_title' => esc_html__('Author Description', 'juliette-wp'),
                'juliette_widgets_field_type' => 'textarea',
            'juliette_author_image' => array(
                'juliette_widgets_name' => 'juliette_author_image',
                'juliette_widgets_title' => esc_html__('Author Image', 'juliette-wp'),
                'juliette_widgets_field_type' => 'upload',
            'juliette_author_facebook' => array(
                'juliette_widgets_name' => 'juliette_author_facebook',
                'juliette_widgets_title' => esc_html__('Facebook Link', 'juliette-wp'),
                'juliette_widgets_field_type' => 'text',
            'juliette_author_twitter' => array(
                'juliette_widgets_name' => 'juliette_author_twitter',
                'juliette_widgets_title' => esc_html__('Twitter Link', 'juliette-wp'),
                'juliette_widgets_field_type' => 'text',
            'juliette_author_youtube' => array(
                'juliette_widgets_name' => 'juliette_author_youtube',
                'juliette_widgets_title' => esc_html__('Youtube Link', 'juliette-wp'),
                'juliette_widgets_field_type' => 'text',
            'juliette_author_instagram' => array(
                'juliette_widgets_name' => 'juliette_author_instagram',
                'juliette_widgets_title' => esc_html__('Instagram Link', 'juliette-wp'),
                'juliette_widgets_field_type' => 'text',

        return $fields;

displaying our author widget in the front-end of our website.

public function widget($args, $instance) {
        $juliette_author_name = apply_filters( 'widget_title', empty( $instance['juliette_author_name'] ) ? '' : $instance['juliette_author_name'], $instance, $this->id_base );       
        $juliette_author_desc = isset( $instance['juliette_author_desc'] ) ? $instance['juliette_author_desc'] : '' ;
        $juliette_author_image = isset( $instance['juliette_author_image'] ) ? $instance['juliette_author_image'] : '' ;
        $juliette_author_facebook = isset( $instance['juliette_author_facebook'] ) ? $instance['juliette_author_facebook'] : '' ;
        $juliette_author_twitter = isset( $instance['juliette_author_twitter'] ) ? $instance['juliette_author_twitter'] : '' ;
        $juliette_author_youtube = isset( $instance['juliette_author_youtube'] ) ? $instance['juliette_author_youtube'] : '' ;
        $juliette_author_instagram = isset( $instance['juliette_author_facebook'] ) ? $instance['juliette_author_instagram'] : '' ;
        echo $before_widget;

 <!-- replace the code below to match your widget author layout for your theme -->
             <div class="card rounded-0 border-0 bg-light mb-4 py-lg-4">
              <div class="card-body text-center">
                <?php if($juliette_author_name){ ?><h2 class="h3 mb-3"><?php echo esc_html($juliette_author_name); ?></h2> <?php } ?>

                <?php  if( $juliette_author_image ){ ?>
                <img class="rounded-circle mb-3" src="<?php echo esc_url( $juliette_author_image ); ?>" alt="<?php echo esc_html($juliette_author_name); ?>" width="100">
                <?php } ?>

            <?php if($juliette_author_desc){ ?><p class="text-small text-muted"><?php echo esc_html($juliette_author_desc); ?></p> <?php } ?>
                <ul class="list-inline small mb-0 text-dark">
                     <?php if( $juliette_author_facebook ){ ?>
                <li class="list-inline-item"><a class="reset-anchor" target="_blank" href="<?php echo esc_url( $juliette_author_facebook ); ?>">
                    <i class="fab fa-facebook-f"></i></a></li>
                   <?php } ?>

                   <?php if( $juliette_author_twitter ){ ?>
                  <li class="list-inline-item"><a class="reset-anchor" target="_blank" href="<?php echo esc_url( $juliette_author_twitter ); ?>"><i class="fab fa-twitter"></i></a></li>
                   <?php } ?>

                   <?php if( $juliette_author_instagram ){ ?>
                  <li class="list-inline-item"><a class="reset-anchor" target="_blank" href="<?php echo esc_url( $juliette_author_instagram ); ?>"><i class="fab fa-instagram"></i></a></li>
                   <?php } ?>
                  <?php if( $juliette_author_youtube ){ ?>
                  <li class="list-inline-item"><a class="reset-anchor" target="_blank" href="<?php echo esc_url( $juliette_author_youtube ); ?>"><i class="fab fa-youtube"></i></a></li>
                  <?php } ?>

        echo $after_widget;

Let sanitize widget form values as they are saved. to do this we will create a helper function named juliette_widgets_updated_field_value() to handle that for us in our author-fields.php

public function update($new_instance, $old_instance) {
        $instance = $old_instance;

        $widget_fields = $this->widget_fields();

        // Loop through fields
        foreach ($widget_fields as $widget_field) {


            // Use helper function to get updated field values
            $instance[$juliette_widgets_name] = juliette_widgets_updated_field_value($widget_field, $new_instance[$juliette_widgets_name]);

        return $instance;

Having sanitize widget form values let display the widget in our back-end of our theme.

public function form($instance) {
        $widget_fields = $this->widget_fields();
        // Loop through fields
        foreach ($widget_fields as $widget_field) {
            // Make array elements available as variables
            $juliette_widgets_field_value = !empty($instance[$juliette_widgets_name]) ? esc_attr($instance[$juliette_widgets_name]) : '';
            juliette_widgets_show_widget_field($this, $widget_field, $juliette_widgets_field_value);

Moving forward, that is our author-widget.php completed. now let open our author-fields.php file. We want to extract the fields we created in our author-fields.php and do that we need to create a function named juliette_widgets_show_widget_field() with three parameters.

function juliette_widgets_show_widget_field( $instance = '', $widget_field = '', $julie_field_value = '' ) {
	extract( $widget_field );
	switch( $juliette_widgets_field_type ) {
		// Standard text field
		case 'text' : ?>
				<label for="<?php echo esc_attr($instance->get_field_id( $juliette_widgets_name )); ?>"><?php echo esc_html($juliette_widgets_title); ?>:</label>
				<input class="widefat" id="<?php echo esc_attr($instance->get_field_id( $juliette_widgets_name )); ?>" name="<?php echo esc_attr($instance->get_field_name( $juliette_widgets_name )); ?>" type="text" value="<?php echo esc_attr($julie_field_value); ?>" />
				<?php if( isset( $juliette_widgets_description ) ) { ?>
				<br />
				<small><?php echo esc_html($juliette_widgets_description); ?></small>
				<?php } ?>

		// Textarea field
		case 'textarea' : ?>
				<label for="<?php echo esc_attr($instance->get_field_id( $juliette_widgets_name )); ?>"><?php echo esc_html($juliette_widgets_title); ?>:</label>
				<textarea class="widefat" rows="6" id="<?php echo esc_attr($instance->get_field_id( $juliette_widgets_name )); ?>" name="<?php echo esc_attr($instance->get_field_name( $juliette_widgets_name )); ?>"><?php echo esc_html($julie_field_value); ?></textarea>

		case 'upload' :

            $output = '';
            $id = esc_attr($instance->get_field_id($juliette_widgets_name));
            $class = '';
            $int = '';
            $value = esc_html($julie_field_value);
            $name = esc_attr($instance->get_field_name($juliette_widgets_name));

            if ($value) {
                $class = ' has-file';
            $output .= '<div style="padding: 20px 5px; border: solid 1px #dcdcdc; margin-top:10px;" class="sub-option widget-upload">';
            $output .= '<label for="' . esc_attr($instance->get_field_id($juliette_widgets_name)) . '">' . esc_attr($juliette_widgets_title) . '</label><br/>';
            if( isset( $juliette_widgets_description ) ) {
				$output .= '<br />';
				$output .=  '<small>'. esc_html($juliette_widgets_description).'</small>';
            $output .= '<input id="' . $id . '" class="upload' . $class . '" type="text" name="' . $name . '" value="' . $value . '" placeholder="' . esc_html__('No file chosen', 'juliette-wp') . '" />' . "\n";
            if (function_exists('wp_enqueue_media')) {
				$output .= '<input id="upload-' . $id . '" class="upload-button button" type="button" value="' . esc_html__('Upload', 'juliette-wp') . '" />' . "\n";

            } else {
                $output .= '<p><i>' . esc_html__('Upgrade your version of WordPress for full media support.', 'juliette-wp') . '</i></p>';

            $output .= '<div class="screenshot team-thumb" id="' . $id . '-image">' . "\n";

            if ($value != '') {
                $remove = '<a class="remove-image remove-screenshot">'.esc_html__('Does not look right? Remove ','juliette-wp').'</a>';
                $attachment_id = attachment_url_to_postid($value);

                $image_array = wp_get_attachment_image_src($attachment_id, 'medium');
                $image = preg_match('/(^.*\.jpg|jpeg|png|gif|ico*)/i', $value);
                if ( isset( $image_array[0] ) && $image_array[0] ) {
                    $output .= '<img src="' . esc_url($image_array[0]) . '" alt="" />' . $remove;
                } else {
                    $parts = explode("/", $value);
                    for ($i = 0; $i < sizeof($parts); ++$i) {
                        $title = $parts[$i];

                    // No output preview if it's not an image.
                    $output .= '';

                    // Standard generic output if it's not an image.
                    $title = esc_html__('View File', 'juliette-wp');
                    $output .= '<div class="no-image"><span class="file_link"><a href="' . $value . '" target="_blank" rel="external">' . $title . '</a></span></div>';
            $output .= '</div></div>' . "\n";
            echo $output;

In the above function we are using a switch statement to check if each fields has a value and also we are checking if its the right value provided by the user. We are also checking if user WordPress current WordPress version support full media support for image upload. However, as a rule of thumb we had to state what file support images can upload into our theme. we don’t want users uploading something different.

function juliette_widgets_updated_field_value( $widget_field, $new_field_value ) {
	extract( $widget_field );
    if ($juliette_widgets_field_type == 'text') {
         return sanitize_text_field($new_field_value);
    elseif( $juliette_widgets_field_type == 'textarea' ) {

		return sanitize_textarea_field( $new_field_value );	
    else {
		return strip_tags( $new_field_value );


The code above update the values passed in by the user and update our author widget. below is what our widget looks like.

However, we have to handle how our widget author image will be uploaded to the backend of our website. To do this we need to write some javascript code. I like to create a separate file so I created a file in my assets/js folder and named it widget.js since the file will one be loaded in the admin section of our website.

     $(document).on('click' , '.upload-button', function(e) {
        var $this = $(this);
    	var image ={ 
    		title: juliette_widget_date.uploadimage,
    		// mutiple: true if you want to upload multiple files at once
    		multiple: false
    	.on('select', function(e){
    		// This will return the selected image from the Media Uploader, the result is an object
    		var uploaded_image = image.state().get('selection').first();
    		// We convert uploaded_image to a JSON object to make accessing it easier
    		// Output to the console uploaded_image
    		var image_url = uploaded_image.toJSON().url;
    		// Let's assign the url value to the input field
            var img = "<img src='"+image_url+"' width='100px' /><a class='remove-image remove-screenshot'>"+juliette_widget_date.remove+"</a>";

    $(document).on('click' , '.remove-image', function(e) {

Now we have to include the file above into our theme and we can do that like so below:

function juliette_admin_enqueue(){

    $currentscreen = get_current_screen();
    if( $currentscreen->id == 'widgets' ){
    	wp_enqueue_script( 'juliette-widget', get_template_directory_uri() . '/assets/js/widget.js', array( 'jquery'), '1.0', true );
    	 $array = array(
	        'remove'     => esc_html__('Remove','juliette-wp'),
	        'uploadimage'     => esc_html__('Author Image','juliette-wp'),
	    wp_localize_script( 'juliette-widget', 'juliette_widget_date', $array );

author widget wordpress

Download Author Widget codes

That is how to create an author widget in WordPress Without Plugin. I do hope you enjoy the tutorial as much as I enjoy writing the code. Although, you can extend the code to show gravatar images instead of uploading a profile image instead and also you can add more fields to the author widgets as you need remember you can do that at the author-widgets.php and just add more validation in the authors-fields.php.

If you don’t like to play around with codes below are author plugins you can use to achieve the same output below.

Author Widget WordPress Plugin



I am a WordPress Developer and an amateur photographer. I love to use the best tools and gear to create the best possible projects. Since I am learning what the best tools are, I want to teach others how can increase the quality of their end results.

namecheap cheap domains
template monster theme

We will send you a free Wordpress Theme

when you subscribe to our newsletter