A Not Very Long Introduction to WordPress Shortcodes

What’s a shortcode?

WordPress shortcodes are custom, WordPress-specific tags that, when entered into the editor, can modify content, insert additional markup around existing content, or even pull in new content from elsewhere (recent posts, uploaded photos, etc). WordPress comes with a number of useful shortcodes built in.

But sometimes it can be useful to define your own. If you’re routinely posting the same complicated markup into blog posts, it might be easier to set up a shortcode. Imagine turning something like


<div class="module">
<h2 class="header">Important Note</h2>
<div class="module_content">
		<img class="note-icon" src="/images/someIcon.gif" alt="">
Announcement content goes here
</div>
</div>

into


[module header="Important Note" icon="someIcon.gif"]
Announcement content goes here
[/module]

Nice and clean, right? It’s not that hard to build.

Why we wrote one

When we first launched this blog, we were using the SyntaxHighlighter Evolved plugin. It did the job, but there were a few things about it that we didn’t really like:

  • In general, we didn’t want scripts wrapped in WordPress plugins. In fact, we didn’t want to use any more plugins than we needed to—plugins add complexity and potential security holes. We thought it would be simpler to install the script separately from the plugin.
  • SyntaxHighlighter was considerably larger than Prism, the other highlighter we were considering.
  • SyntaxHighlighter’s default theme was kind of clunky.
  • We had trouble getting highlighted code to wrap. The way SyntaxHighlighter formatted code, long lines would extend out of the code block and generate a horizontal scroller, which we thought was awkward to work with. There didn’t seem to be any way of turning this off.

One complication of going plugin-less, however, is that HTML markup has to be converted to entities before syntax highlighting is applied—otherwise, it’ll be rendered by the browser. This is where the convenience of SyntaxHighlighter came in: wrapping HTML in the SyntaxHighlighter shortcode automatically converted the markup to entities. I wanted the shortcode without the plugin, and when I looked up WordPress’s shortcode API, writing one seemed pretty straightforward. The whole thing took about ten minutes.

Try it yourself

Here’s the code. You can drop this into your functions file and—assuming you’ve installed Prism—it will work.


function codetag_func($atts, $content) {
	$atts = shortcode_atts( array('language' => 'markup', 'wrap' => true), $atts, 'codetag' );
	$language = $atts['language'];
	$wrap = $atts['wrap'];
	$content = str_replace("", "", $content);
	$wrapping = "wrap";
	if ($wrap === "false") $wrapping = "wrap--none";
	return '
<pre><code class="language-'.$language.' '.$wrapping.'">'.htmlentities($content).'</code></pre>
';
}
add_shortcode( 'code', 'codetag_func' );

You will also need the following CSS:


.wrap {
	white-space:pre-wrap;
	white-space:-moz-pre-wrap;
	white-space:-pre-wrap;
	white-space:-o-pre-wrap;
	word-wrap:break-word;
}

The syntax is:


[code language="css"]
// code goes here
[/code]

Note: The “code” shortcode might conflict with existing plugins (and it will definitely conflict if you’ve got SyntaxHighlighter installed) but you can change it to anything.

Explained

Basic WordPress shortcodes aren’t hard to write at all. All of this will be pretty elementary to WordPress pros, but it might be useful to someone who’s still getting used to the idea of shortcodes.

First define the handler function.

codetag_func($atts, $content) {

This is the code that receives whatever content is passed to it, whether that is content enclosed by the shortcode ([shortcode]content[/shortcode] or content specified in shortcode parameters ([shortcode attribute="true"]). In our example, that’s codetag_func. The shortcode handler function has as parameters the attributes of the shortcode ($atts) and—if the shortcode encloses markup—the content contained between the start and end tags ($content).

To access the attributes, we need the $atts variable. The first thing we have to do is set up $atts using the shortcode_atts() function. 1


$atts = shortcode_atts(
	array('language' => 'markup', 'wrap' => true),
	$atts,
	'codetag'
);

shortcode_atts() takes as parameters the following:

  • The attributes you want your shortcode to support (“language”, “wrap”, etc), as well as their default values. This, as you can see, is an array.
  • The attributes entered into the shortcode by anyone invoking it in the editor. This is also an array, and it’s structurally identical to the previous one. If your shortcode is named [code], and a user enters [code language="CSS" wrap="false"] into the editor, $atts will contain [language] => css [wrap] => 0. (You can look inside any array with PHP’s print_r() function.)
  • The shortcode’s filter. This is a value that other code—third-party plugins, or maybe other functions you’ve written—can use to access your shortcode parameters 2. It’s optional, but the WordPress authors recommend including it anyway. (It’s very new—since WordPress 3.6—so it doesn’t appear in older tutorials.)

Note: When naming your shortcode and attributes, use only lower-case names, per the WordPress API guidelines.

At this point, we have an array—$atts—and it contains all the attributes the user has entered for the shortcode. The next two lines grab the values assigned to specific attributes:


$language = $atts['language'];
$wrap = $atts['wrap'];

$content—the markup enclosed by the shortcode—exists just as it is, and we can refer to it directly.


$content = str_replace("", "", $content);

This line eliminates any break tags that WordPress automatically inserts. We don’t need them because the shortcode will wrap the code we’re formatting in a <pre> tag (which, as Prism points out on its site, is the W3C-recommended way of marking up code anyway).

Wrap or don’t wrap? Unwrapped code, if it’s long enough, will generate a horizontal scroll bar on the code block, which can be clumsy to deal with if it involves a lot of back-and-forth scrolling. Wrapping code, however, can disrupt the structure and make it harder to read. Since the best option depends on how much code there is, I’ve included wrapping as a user-configurable option, and set the code to wrap by default (remember 'wrap' => true in shortcode_atts?).


$wrapping = "wrap";
if ($wrap === "false") $wrapping = "wrap--none";

$wrapping is a variable that contains the classname applied to the code block. If the wrap attribute is set to false, $wrapping is reset to wrap--none. (We’re using the BEM naming convention—name the classes however you want.) If not, $wrapping remains set to wrap, and the above CSS will be applied to the final code block.


return '
<pre><code class="language-'.$language.' '.$wrapping.'">'.htmlentities($content).'</code></pre>
'

And here’s where it all comes together: the specified language is specified via a Prism-specific class, the user’s choice of wrapping is also specified as a class, and the content—with break tags removed—is converted to HTML entities.

(Note: Prism needs the language class to follow the “language-[languageName]” convention in order to apply the proper syntax coloring—don’t change that class.)


add_shortcode( 'code', 'codetag_func' );

This final line adds the new shortcode to WordPress. That’s it—you’ve got yourself a handy shortcode for wrapping code snippets in.

Non-color visual distinction for links as a Best Practice

As a functional component of a web page, a link should look like a link—and obviously so. On some of our sites, color alone is used to indicate a link, but, according to WCAG 2.0 (Web Content Accessibility Guidelines), color isn’t sufficient for a link to be accessible. For general usability, when WCAG are applied, our sites become easier to use for everyone. I’d like to suggest using underlines on links as a best practice and here’s why: More