Modern WordPress Themeing
2011 Edition
Follow along at RachelNabors.com/wordpress-themeing-2011
Follow me at RachelNabors.com and @Crowchick
The Story
This is Lisa*. She's your good friend and a quasi-professional photographer. She took photos of you at your last wedding/promotional event/shindig. You owe her one.
She has a blog. A WordPress blog. She'd like to add a gallery of her photography to it without terribly changing how the whole site looks. (So a new theme or overhaul is out of the question.)
Your mission, should you choose to accept it
Extend Lisa's current theme to allow her to post and showcase her art without using a third-party plugin.
The IA
First of all, visualize how you want to store the data in relation to other data types on the blog.
In this case, you want to store the art separately from the blog posts. They will have separate archives, separate RSS feeds, separate beds.
Making a Child Theme
Making a child theme is very simple. Create a directory, put a properly formatted style.css file in it, and you have a child theme! ...child themes are the recommended way of making modifications to a theme.
WordPress Codex: Child Themes
- All you need is a
style.css - All other files, like
index.php,search.php,functions.php, etc. are optional. - Each file overwrites the parent theme's file i.e.,
child-theme/index.php>parent-theme/index.php
A word about functions.php
Unlike other template files, functions.php does not overwrite the parent theme's functions.php. It merely lays on top of it.
Formatting the child theme's style.css
Making a child theme is easy as making a stylesheet. Just put this at the top of it.
/* Theme Name: Name of Child Theme Theme URI: http://example.com/ Description: Child theme for foobar theme Author: Your name here Author URI: http://example.com/about/ Template: twentyten Version: 0.1.0 */
Import Your Parent Theme's Styles
Just like all the other files in the child theme, style.css will overwrite the parent theme's stylesheet. If you want to keep your parent theme's css, use an @import first thing in your child theme's stylesheet! Do not put any rules above the @import rule.
@import url("../parent-theme/style.css");
Post Formats
A Post Format is a piece of meta information that can be used by a theme to customize its presentation of a post. ...(A) blogger can change how each post looks by choosing a Post Format from a radio-button list. WordPress Codex: Post Formats
- There are a set number of different post formats you can enable: aside, chat, gallery, image, link, quote, status, video, audio
- You cannot define new post formats at this time.
- Do not mistake for custom post/content types!
Enabling Post Formats
add_theme_support('post-formats', array('aside', 'chat', 'gallery', 'image', 'link', 'quote', 'status', 'video', 'audio'));
Add this code to your child theme's functions.php.
IA Revisited
With mere post types, the different types of posts are still blog posts. They still show in the blog's RSS and in blog archives.
Lisa wants to keep her work separate from her ramblings, so let's look for another solution.
Custom Post Types
Add this code to your functions.php (replace "books" with your own values).
add_action( 'init', 'namespace_create_post_type' );
function namespace_create_post_type() {
register_post_type( 'acme_product',
array(
'labels' => array(
'name' => __( 'Products' ),
'singular_name' => __( 'Product' )
),
'description' => 'A short description of this post type.',
'public' => true,
'has_archive' => true,
'rewrite' => array(
'slug' => 'products',
'with_front' => false // if your permalink structure is /blog/, then your links will be: false->/news/, true->/blog/news/) - defaults to true
),
'hierarchical' => false, // set to true to "nest" like pages
'menu_position' => null, // where on the menu it should appear; 5 = below posts, 10 = below media, etc
'supports' => array('title','editor','author','thumbnail','excerpt','comments')
)
);
}
- Namespace your post types.
- If you get a 404 on a custom content page, just re-save your permalinks to regenerate the URL :)
- Custom post types in many ways behave more like "pages" than blog posts. You can nest them, for instance.
- According to Nacin, there are no server penalties for excluding date from permalink structure as there are with blog posts (that's a good thing). (Update: As of WordPress 3.3, there are no server penalties for a dateless permalink structure, period!)
Custom Taxonomies
In WordPress, a "taxonomy" is a grouping mechanism for some posts (or links or custom post types). WordPress Codex: Taxonomies
- Categories, tags, and link categories are all taxonomies WordPress comes with out of the box
- Categories are "hierarchical" whereas tags are not.
//hook into the init action and call create_book_taxonomies when it fires
add_action( 'init', 'create_book_taxonomies', 0 );
//create two taxonomies, genres and writers for the post type "book"
function create_book_taxonomies()
{
// Add new taxonomy
$labels = array(
'name' => _x( 'Writers', 'taxonomy general name' ),
'singular_name' => _x( 'Writer', 'taxonomy singular name' ),
'search_items' => __( 'Search Writers' ),
'popular_items' => __( 'Popular Writers' ),
'all_items' => __( 'All Writers' ),
'parent_item' => null, //null for non-hierarchical, defaults to "Parent Category" otherwise
'parent_item_colon' => null, // same as above, but with a colon! Like "Parent Category:"
'edit_item' => __( 'Edit Writer' ),
'update_item' => __( 'Update Writer' ),
'add_new_item' => __( 'Add New Writer' ),
'new_item_name' => __( 'New Writer Name' ),
'separate_items_with_commas' => __( 'Separate writers with commas' ),
'add_or_remove_items' => __( 'Add or remove writers' ),
'choose_from_most_used' => __( 'Choose from the most used writers' ),
'menu_name' => __( 'Writers' )
);
register_taxonomy('writer','book',array( // 'book' here is the name of your custom post type you want to associate this with
'hierarchical' => false, // creates tag-like taxonomy. Set to true for category-like taxonomy
'labels' => $labels,
'show_ui' => true,
'update_count_callback' => '_update_post_term_count', //only necessary for non-hierarchicals
'query_var' => true,
'rewrite' => array( 'slug' => 'writer' ) //this is used in the archive and page URLs!
));
//repeat the above for genres, only use hierarchical options
}
Don't Forget!
If you want to ensure that your custom taxonomy behaves like a tag, you must add the option 'update_count_callback' => '_update_post_term_count'. Not doing so will result in multiple comma-separated items added at once being saved as a single value, not as separate values. This can cause undue stress when using get_the_term_list and other term display functions.
WordPress Codex: Register Taxonomy
Custom Post Type and Taxonomy Templates
- You create a new kind of archive for every custom post type and taxonomy you generate.
- Custom post type pages can be targeted with
single-postype.php, and archived witharchive-posttype.php. - Otherwise custom post types will use
single.phpandarchive.phpjust like blog posts. - Taxonomy archives will also use
archive.phpby default. - But you can get more granular with them, too:
taxonomy.php<taxonomy-taxonomy.php<taxonomy-taxonomy-term.php
Listing your Taxonomy Terms
<?php get_the_term_list( $id, $taxonomy, $before, $sep, $after ); ?>
An example:
<?php echo get_the_term_list( $post->ID, 'people', 'People: ', ' ', '' ); ?>
Post Thumbnails
Activating Post Thumbnails in Older WordPress Themes
Add this snippet to your functions.php.
add_theme_support( 'post-thumbnails' ); set_post_thumbnail_size( 200, 200 ); //add a default size
Adding Post Thumbnails to WordPress Templates
To add the default thumbnail size to your WordPress theme templates, just pop in this code.
<?php the_post_thumbnail(); ?>
Regenerate Those Thumbnails
From this point onward, you will most likely want to install the regenerate thumbnails plugin. WordPress does not generate new thumbnails when you change your thumbnail settings in functions.php. The new settings are only applied to new image uploads. To retroactively apply the new settings, you'll need to force WordPress to regenerate all its thumbnails with this plugin.
Defining Thumbnail Dimensions
add_image_size( 'koi_art_full', 500, 9000, false );
To define a thumbnail type with special dimensions, use this snippet in your functions.php.
The values work like this: add_image_size( 'unique_identifier', width, height, cropping ); So the above gives us images that are scaled up or down to be 500 pixels wide and no more than 9000 pixels tall (the image is always scaled to meet the lowest value).
You can also use the default size that you set in Settings > Media, thumbnail, medium, large, and even full.
<?php the_post_thumbnail('medium'); ?>
Wrapping your Post Thumbnails in Permalinks
<?php if ( has_post_thumbnail()) : ?> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>" > <?php the_post_thumbnail(); ?> </a> <?php endif; ?>
To wrap your post thumbnail in a permalink, pop this into your template file.
add_filter( 'post_thumbnail_html', 'my_post_image_html', 10, 3 );
function my_post_image_html( $html, $post_id, $post_image_id ) {
$html = '<a href="' . get_permalink( $post_id ) . '" title="' . esc_attr( get_post_field( 'post_title', $post_id ) ) . '">' . $html . '</a>';
return $html;
}
Or to link all post thumbnails to their permalinks, site-wide, use the following in your functions.php:
Adding a class to Post Thumbnails
<?php the_post_thumbnail('thumbnail', array('class' => 'gallery-tn')); ?>
Adding a class to thumbnails is also pretty easy with an array.
Widgetized Areas
You can put widgetized areas anywhere in your template files. Anywhere.
This code was 100% lifted from Digging into WordPress: How to Widgetize Your WordPress Theme in 2 Steps. Credit where credit is due!
First, add this to functions.php.
if (function_exists('register_sidebar')) {
register_sidebar(array(
'name' => 'Widgetized Area', //the name of this area, as used in the WP admin
'id' => 'widgetized-area', //a unique identifier for your widgetized area
'description' => 'This is a widgetized area.',
'before_widget' => '<div id="%1$s" class="widget %2$s">',
'after_widget' => '</div>',
'before_title' => '<h4>', //note, titles sit outside of widgets
'after_title' => '</h4>'
));
}
Then add this to your theme's template files.
<?php if (function_exists('dynamic_sidebar') && dynamic_sidebar('widgetized-area')) : else : ?>
<h4>Widgetized Area</h4>
<div class="widget">
<p>This panel is active and ready for you to add some widgets via the WP Admin</p>
</div>
<?php endif; ?>
Reminding admins to edit things
Sometimes, you want to remind an admin that a section of the site is widgetized or otherwise editable, but you don't want normal visitors to see the reminder. In which case, use this.
<?php if (current_user_can('edit_theme_options') ) : ?>
Menus
Add this to your functions.php.
if ( function_exists( 'register_nav_menu' ) ) {
register_nav_menu( 'koi-art_menu', 'Arty Menu' );
}
Then pop this wherever you want a shiny menu in your templates.
<?php wp_nav_menu( array( 'theme_location' => 'koi-art_menu' ) ); ?>
Gross
The default is ugly. By default, if you don't tell WordPress what pages to put in a menu, it will use them all. That's why your site looks messed up now.
RSS for your Custom Content Types
Custom Content Types generate an RSS feed of their own.
You can combine it with your site's blog post feed.
Add this code gleened from WP Beginner to your functions.php.
function myfeed_request($qv) {
if (isset($qv['feed']))
$qv['post_type'] = get_post_types();
return $qv;
}
add_filter('request', 'myfeed_request');
Individual feeds for custom content types and taxonomies
But if you want to use just your Custom Content Type's individual RSS feed, you need no extra code.
Just use this URL structure.
http://www.yoursite.com/feed/?post_type=book
And it works with taxonomies, too!
http://www.yoursite.com/feed/?post_type=book&genre=romance
Sidebars, dynamic and otherwise
There are two "sidebars" in WordPress:
- Dynamic Sidebars which are just widgetized areas. You met them already above. Let's move on.
- Sidebar Includes which are include files that you can put static as well as dynamic code in.
Rule of Thumb
If you need lots of extra markup with your widgetized area or you plan to use the same sidebar code in more than one template file, consider putting it in a sidebar template.
Adding a sidebar to your theme templates
Your theme probably already has a sidebar.php. You can also make additional sidebars like sidebar-primary.php or sidebar-awesome.php.
Call sidebars in your templates with this code.
<?php get_sidebar( 'primary' ); ?>
Resources
- Sidebars in WordPress by Justin Tadlock
- WordPress Codex: Function Reference/dynamic_sidebar
Bonus: Putting it in a Plugin
A WordPress Plugin is a program, or a set of one or more functions, written in the PHP scripting language, that adds a specific set of features or services to the WordPress weblog WordPress Codex: Writing a Plugin
If you can put it in your functions.php, you can make a plugin with it!
Making a plugin isn't that hard. Like when making a child theme, you only need one file with one header, and it only requires one line of code, its name.
Initiating a plugin
So make a new PHP file, named for your plugin, pop this code into it, and stick it in your plugins folder.
Keep things tidy
It's usually a good idea to put your plugin files in a folder rather than directly into your plugin directory. You'll inevitably want to add a readme file or other supplementary files, and you don't want them knocking about all over the place.
<?php /* Plugin Name: Name Of The Plugin Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates Description: A brief description of the Plugin. Version: The Plugin's Version Number, e.g.: 1.0 Author: Name Of The Plugin Author Author URI: http://URI_Of_The_Plugin_Author License: A "Slug" license name e.g. GPL2 */ ?>
Here's the ridiculously easy part. Grab all the functions from your functions.php that you want to put in your plugin, and put them in your new plugin file. Seriously. That's it.
Congratulations. You are now a plugin author. Have some chocolate or a beer or something, and pat yourself on the back.
It's been fun!
Further Reading
This is only the tip of the iceberg. If you're excited and can't wait to do more, check out these fine resources and people. They're Rachel-approved™.
- The WordPress Codex: Go here before sniffing around at WordPress "tips and tricks" sites, as the information in the Codex is tended better and kept current.
- Digging into WordPress, the site and the book. This is my favorite book on WordPress. Chris Coyier and Jeff Starr update it regularly with new chapters for every new WordPress release, and you get the updates digitally for free.
- Michael Fields, plugin developer with an excellent blog on plugin and theme development
- Yoast.com, run by Joost de Valk. Covers the minutia of how search engines crawl your site and gives sound WordPress advice. Also on the WordPress Podcast.