In the Basics of the Shortcode API, we briefly covered shortcode attributes and the shortcode_atts() function. Now it is time to dive deep into setting up attributes for shortcodes and learn a few tricks can that be exceptionally helpful when building shortcodes in your plugins or when modifying the shortcodes of other plugins.

Shortcode attributes are the “settings” that users can specify in the shortcode when using it on a post or page. In the following example, “color” is the attribute and “blue” is the value of the attribute:

[pw101_box color="blue"]

Shortcodes can have more than one attribute:

[pw101_box color="green" border="none" icon="alert"]

These attributes can be used to control what your shortcode outputs, but in order to do that, we need to have a way retrieve the values of each attribute specified. That’s where the shortcode_atts() function comes in.

The function is quite simple. It has three parameters:

  • $pairs – a array of key => value pairs that defines the default values of all attributes
  • $atts – the attributes supplied by the user
  • $shortcode – the shortcode tag (pw101_box)

Take the following example.

function pw101_box_shortcode( $atts, $content = null ) {

	$atts = shortcode_atts( array(
		'color'  > 'blue',
		'icon'   > '',
		'border' > '2px'
	), $atts, 'pw101_box' );

	return $box;
}
add_shortcode( 'pw101_box', 'pw101_box_shortcode' );

First, $atts is initially setup by WordPress since it is the first parameter available in our add_shortcode() callback. This $atts will contain all attributes that the user has included in the shortcode.

Second, we create a new $atts variable and use shortcode_atts() to setup its value. What does this do? It takes the user-supplied attributes and combines them with our default attributes. The first parameter passed to the shortcode_atts() function is an array of defaults. We have set the defaults to:

  • color: blue
  • icon: (none)
  • border: 2px

If no attributes are supplied by the user, these are the three values our shortcode will use. If only the color attribute is specified, and it is set to “red”, the following values will be used:

  • color: red
  • icon: (none)
  • border: 2px

The shortcode_atts() function is exceptionally useful because it lets us easily define the standard values for our shortcode attributes without having to setup our own logic processing for them.

The third parameter to the shortcode_atts() function is extremely valuable but often under utilized. It allows you to define the name of the filter that your shortcode attributes go through before being returned by shortcode_atts(). WordPress returns the attributes through a filter called shortcode_atts_$shortcode, so in our example, the filter would be shortcode_atts_pw101_box. This filter allows the attributes to be modified from other places in your plugin or even entirely separate plugins.

I’d suggest looking at the source code of the filter in WordPress core.

I recently used this filter in an extension for Easy Digital Downloads. EDD has a shortcode called [downloads] that takes a lot of attributes. For my extension to work properly, I had to force one of the attributes to always be a specific value, so I used the shortcode_atts_downloads filter to modify the attribute before it is returned, therefor ensuring that it was always the value I needed it to be.

Once you have the shortcode attributes setup, you can easily use this inside of your shortcode to modify the final output. Earlier we used this example:

function pw101_box_shortcode( $atts, $content = null ) {

	$atts = shortcode_atts( array(
		'color'  => 'blue',
		'icon'   => '',
		'border' => '2px'
	), $atts, 'pw101_box' );

	$box = '<div class="pw-box ' . esc_attr( $atts['color'] ) . ">';
		$box .= $content;
	$box .= '</div>';

	return $box;
}

Here you can see the class attribute of the DIV tag being set based on the value of color attribute in our shortcode.

Since we have an icon attribute, let’s go ahead and set that up too:

function pw101_box_shortcode( $atts, $content = null ) {

	$atts = shortcode_atts( array(
		'color'  => 'blue',
		'icon'   => '',
		'border' => '2px'
	), $atts, 'pw101_box' );

	$box = '<div class="pw-box ' . esc_attr( $atts['color'] ) . ">';
		
		if( ! empty( $atts['icon'] ) ) {
			$box .= '<span class="icon icon-' . esc_attr( $atts['icon'] ) . '"></span>';
		}

		$box .= $content;
	$box .= '</div>';

	return $box;
}

If the icon attribute is specified, we simply output a simple SPAN tag with a class that can then be styled in our CSS.

We can do the same thing with the border attribute:

function pw101_box_shortcode( $atts, $content = null ) {

	$atts = shortcode_atts( array(
		'color'  => 'blue',
		'icon'   => '',
		'border' => '2px'
	), $atts, 'pw101_box' );

	$box = '<div class="pw-box ' . esc_attr( $atts['color'] ) . " style="border-width: ' . esc_attr( $atts['border'] ) . ';">';
		
		if( ! empty( $atts['icon'] ) ) {
			$box .= '<span class="icon icon-' . esc_attr( $atts['icon'] ) . '"></span>';
		}

		$box .= $content;
	$box .= '</div>';

	return $box;
}
  1. dj

    Pippin…. I have enjoyed reading this blog for years. And I have no issue with you turning it into basically a paid site – although that is not for me. However, I find the issue of not being able to identify which of your posts listed on the front page basically leads to nowhere (for me) annoying. If you cannot figure out a way to identify your paid versus “regular” posts up front so I don’t waste time clicking on something I’m not going to follow, I’ll need to delete the blog from those that I follow – perhaps no big deal – just sayin’.

    • Pippin

      Thank you for the feedback. With the launch of the new site a couple of days ago, this has been dramatically improved.

  2. Mika Kaltoft

    Hey 😀

    I have two questions!

    1. Is there a certain reason why you don’t use the native PHP extract function to make the values variables like many other developers? 🙂

    2. Wouldn’t it be hard to use the shortcode_atts_$shortcode filter to add an extra value (with key) to an existing shortcode since the new value wouldn’t be present and available in the html markup of the existing shortcode.

    Looking forward hearing back from you! 😀
    Sincerely,
    Mika

    • Decotra

      Thanks fot sharing. i need that information for my job. thanks you