News

Tailor your own WordPress theme pt 2

Part 2 of Design and develop your own WordPress theme from scratch looks at adding a sidebar, content, the style sheet and functions.php to finish up

WordPressLogo

THE WORDPRESS SIDEBAR

The sidebar.php template is really simple too. All we want it to contain is the necessary markup, so we need to position it where we want it, and the code for making the widget area will then appear. The actual registration of the widget area is done in functions.php, so in essence this is basically just a placeholder.
The code we’re using for sidebar.php is the #sidebar-container aside tag, and within it we have a ul. That is because we’ll construct our sidebar to be a unordered list, which is something you can choose to do when you create it in functions.php. This is the common way to do it, making each widget dropped into the widget area reside within a li, that belongs within the unordered list. However, some prefer divs or even a bunch of asides rather than the old method. Which way you go is up to you, but since widget areas tend to be lists of things, I think using lists makes sense.
Anyway, the template tag used to call up widget areas is called dynamic_sidebar() and all you have to do is to pass the name of the sidebar you want to display to it. In our case, that is primary-right-column, which also happens to be the only widget area we’ve got.

001 <aside id=”sidebar-container”>
002    <ul id=”sidebar-widgets”>
003        <?php dynamic_sidebar( ‘primary-
right-column’ ); ?>
004    </ul>
005 </aside>

CREATING THE FOOTER

Let’s move along with the footer. This template sometimes includes widget areas or other fancy stuff, but we’re keeping it simple. The important part with footer.php is that you really should make sure you have wp_footer() just before you close the body tag. This tells WordPress that we’re done with the page, and also gives developers a great opportunity to hook on to the bottom of the page for including or executing things, whatever it might be. Don’t forget wp_footer() is the important thing you need to take away from this.

01. The actual footer
The footer for this theme is simple enough, it is just a line of text with some links in it. You’ll remember home_url() from header.php perhaps, a template tag (that you need to echo to actually output) which points to the root of your WordPress site. If you need to get the root of the WordPress installation, which often is the same as your site but not always, you could use site_url() instead.

 001 < footer id=”footer-container”>
002 < p>
003 < a href=”< ?php echo home_url();  ?>” title=”< ?php bloginfo( ‘title’);  ?>”>< ?php bloginfo( ‘title’); ?> is 
powered by WordPress and 
Kihon by TDH>
004 < /p>
005 < /footer>

02. Wrapping up the footer
Finally, we’ll close all the necessary tags, the #outer-wrap and #inner-wrap divs from header.php, and then we’ll have wp_footer() just before closing the body tag as well. Like I said, we’re going to keep this one really simple, so that’s it!

001 < !-- #inner-wrap -->
002 
003 
004 < ?php wp_footer(); ?>
005 
006 < /body>
007 
008  < /html>

BUILDING THE INDEX PAGE

We’re getting close to a theme that will actually work now. The index.php template is the main fallback template for everything, so whenever there isn’t a dedicated template file for something, this will be used. Let’s dive right into it, shall we?

01. The top
The first thing we’ve got in this template, and just about any other template file that works with the actual content, is the inclusion of header.php with get_header().

 001 <  ?php
002 // index.php is the fallback template
003 
004 // Include header.php
005 get_header();
006 ?>
007 
008 < section id=”content-container”>

02. 404s
We don’t have a 404.php template, so index.php will handle that. By checking if have_posts() lack any posts we can figure out if a non-existent page is being accessed. Should that be the case, we’ll output a short message (that really should be a lot more helpful to the lost visitor) and fetch the search form with get_search_form(). You can have your own search form by creating a searchform.php template file with your form, or you can rely on the default one, which we’re doing here for now.

 001 <  ?php 
002 // 404 Page Not Found or empty archives etc.
003 if ( !have_posts() ) : ?>
004 < article id=”post-0” class=”post error404 not-found”>
005 < h1 class=”entry-title”>Not Found
006 < div class=”entry-content”>
007 < p>Sorry, there is nothing here. You might want to try and search for whatever it 
was you were looking for?>
008 < ?php get_search_form(); ?>
009 < /div>
010 < /article>
011 < ?php 
012 endif;

03. Looping it
Content in WordPress is outputted using the loop. Here’s the most basic one, starting with while ( have_posts() ) : the_post(). You can create your own loops and do things different from this, but this is the basic one. As long as there are posts to loop, up to the amount you’ve set in Settings>Reading, the loop will loop out the posts.
Now, you’ll see two get_template_part() tags. The first is looking for content-index.php and the second wants nav-bottom.php. When using get_template_part(), the first parameter is the fallback, so should content-index.php not exist, it will revert to just content.php. The second parameter adds the index part in content-index.php. The same goes for nav-bottom.php – should it not exist, it will look for just nav.php. This is a very handy way of preparing a theme for dedicated template parts, but with fallbacks to make sure it actually works.
So, to recap: the loop is looping a number of posts, which will be dictated by the contents of content-index.php. This is something we’ll look closer at in the next section.

001 // The basic loop
002 while ( have_posts() ) : the_post(); 
003 
004 // Load the appropriate content template
005 get_template_part( ‘content’, ‘index’ );
006 
007 // End the loop
008 endwhile;
009 
010 // Navigation top
011 get_template_part( ‘nav’, ‘bottom’ );
012 ?>

04. Wrapping up index.php
To wrap up index.php, we’ll close the section element. However, we also want to include the sidebar.php template, which contains our right column, which we’ll do with get_sidebar(). Finally, we want to wrap up the whole page with footer.php, so we’ll call that with get_footer().

001 < /section>
002 
003 < ?php 
004 // Include sidebar.php
005 get_sidebar();
006 
007 // Include header.php
008 get_footer(); 
009 ?>

05. A look at nav-bottom.php
Before we move along, let’s have a quick look at the contents of nav-bottom.php. We called it in step 3, as I’m sure you remember. This code will only be interesting if the loop, here represented by calling $wp_query, has more than one page. So if the loop contains 15 results but you have set WordPress to only display ten per page, then you’ll get these navigational links. Pretty simple, and a nice example of when get_template_part() is useful, since the code within n
av-bottom.php is needed on just about any archive page.

001 < ?php 
002 // When possible, display navigation  at the bottom
003 if ( $wp_query->max_num_pages > 1 ) :?>
004 < div id=”nav-below” class=”navigation”>
005 < div class=”nav-previous”>
006 < ?php next_posts_link( ‘← Older posts’ 
); ?>
007 < /div>
008 < div class=”nav-next”>
009 < ?php previous_posts_link( ‘Newer posts →’ ); ?>
010 < /div>
011 < /div>
012 < ?php endif; ?>

THE CONTENT

By separating the content that you’ll output from every template file, it’ll be easier to reuse the code. In this theme, we use get_template_part() to fetch the appropriate content-X.php file, where X is the type of content we want. That means that single posts, controlled by the single.php template, will look for content-single.php, and pages will want content-page.php. Should they not exist, they’ll revert to content.php. Much like index.php is the main fallback template file, content.php is the fallback file for all content. So, let’s go ahead and take a look at that.
Before we dive in, it is important to remember that content can either be in a list, or all by itself on a dedicated page (like a post, for example). Since content.php needs to be able to handle both, we take that into account.

01. The content header
We place all content in an article tag which has a post_class() template tag within. This is to make sure that WordPress is able to apply the necessary styles.
Moving on, the title of the content sits in a header tag, which will either output an h1 or an h2, depending if this is a post or page, or some sort of archive listing. The is_singular() conditional tag tells us this, because it will only return true if the page in question is meant for only one piece of content.
We use the_permalink() to get the link to the post should we need it, the_title() to output the post title, and the_title_attribute() to get a suitable title for the title tag. Lots of titles there.

001 <article id=”post-<?php the_ID(); ??>”
<?php post_class(); ??>?>
002 <?php if ( is_singular() ) { ??>
003 <header class=”entry-header”?>
004 <h1 class=”entry-title”?>
005 <?php the_title(); ??>
006 </h1?>
007 <?php } else { ??>
008 <h2 class=”entry-title”?>
009 <a href=”<?php the_permalink();
??>” title=”<?php the_title_attribute(); ??>”
rel=”bookmark”?>
010 <?php the_title(); ??>
011 </a?>
012 </h2?>
013 <?php } ??>
014 </header?>

02. For archives
Next, we differentiate how we output the main content depending on wether it is an archive of some sort, or a single post. Here we have several conditional tags, like is_archive() and is_search() – all pretty self explanatory. With the_excerpt(), we’ll only get a 55 word excerpt from our posts, or whatever’s been filled in to the excerpt field on the Edit Post screen in the admin interface.

001 <?php
002 // For archives and search results, use
the_excerpt()
003 if ( is_home() || is_front_page() ||
is_archive() || is_search() ) : ??>
004 <div class=”entry-summary”?>
005 <?php the_excerpt(); ??>
006 <div class=”read-more”?>
007 <?php
008 // If the comments are open
we’ll need the comments template
009 if (comments_open()) { ??>
010 <span class=”comments-link”?>
011 <?php comments_popup_link(
‘Leave a comment’, ‘1 comment’, ‘% comments’
); ??>
012 </span?> •
013 <?php } ??>
014 <a href=”<?php the_permalink();
??>” title=”<?php the_title_attribute(); ??>”
rel=”bookmark”?>
015 Continue reading →
016 </a?>
017 </div?>
018 </div?>

03. For single posts and pages
Everything that isn’t an archive is obviously a single view of some sort. Here we use
the_content() instead of the_excerpt() to fetch the content, which means we’ll get all the main content. Sometimes that can be split up into several pages (although it is a nasty habit that should be avoided), so we have wp_link_pages() to manage that.

001 <?php
002 // For everything else
003 else : ??>
004 <div class=”entry-content”?>
005 <?php the_content(); ??>
006 <?php wp_link_pages( array(
007 ‘before’ =?> ‘<div class=”page-
link”?>Pages:’,
008 ‘after’ =?> ‘</div?>’
009 )
010 ); ??>
011 </div?>
012 <?php endif;

04. Comments only on singulars
Finally, single posts and pages might have comments that we want to show off. The
is_singular() conditional tag will only output the comments_template() if it returns true, so that way we can make sure that comments won’t show up on any archives.

001 // Comments only on single posts
002 if ( is_singular() ) {
003 comments_template( ‘’, true );
004 }
005 ??>
006 </article?>

STYLE

Every theme needs a style.css file, and it is important that the top of it is formatted in a way that WordPress can understand. This is where the theme information goes, the part that you’ll see when visiting Appearance>
Themes in the admin interface. Some themes have more information than others, the Tags: line is only for the wordpress.org themes repository, for example.
Below is the theme header in style.css for our theme. I’ve named it Kihon, which is Japanese and means ‘foundation’, as this is meant to be something of a foundation for curious web developers who want to step into WordPress theming. Kind of nice, don’t you think?
The theme header is the only thing that is dictated by WordPress when it comes to style.css. Once you get below it you can happily CSS away in any which way you want. There are a bunch of classes that you should support though, for images and the like, so you might want to refer to this page and make sure your stylesheet is able to manage all situations:
codex.wordpress.org/CSS#WordPress_Generated_Classes.

001 /*
002 Theme Name: Kihon
003 Theme URI: http://tdh.me/wordpress/
kihon/
004 Author: Thord Daniel Hedengren
005 Author URI: http://tdh.me
006 Description: A simple theme meant 
as a foundation for your adventures in 
the WordPress world.
007 Version: 1.0
008 License: GNU General Public License v2 or later
009 License URI: http://www.gnu.org/
licenses/gpl-2.0.html
010 Tags: light, two-columns, right-
sidebar, fixed-width, custom-background, custom-header, custom-menu, sticky-post
*/

ADDING FUNCTIONS

The functions.php file is meant for activating features and adding additional functionality. It is a very powerful tool, and you can do almost anything with it. We’ll only touch on it briefly here, because frankly it is a huge topic that deserves an article of its own.
Some thin
gs that we’re doing here in the functions file connects to things we’ve done before, like the header image and menu in header.php, and the widget area in sidebar.php. You might want to refer to these sections.

01. Setting up the theme
The first thing we need to do is set up the theme, which is to say we create a function with features that we want the theme to have, and then we hook that to after_setup_theme with add_action().
Within the function, kihon_setup(), you’ll find the features we’re adding. Here you’ll find the header image, with a bunch of settings such as flexible width and height (but recommended sizes), as well as the menu, register_nav_menu(), which creates the menu we called in header.php. The custom background feature will let us be able to detect RSS feeds.

02. Creating the widget area
Next we have the widget area. This also sits within a function, called kihon_widgets_init(), and we hook it onto widgets_init with add_action(). Widget areas, or sidebars, are registered with register_sidebar(), which takes a number of things within an array. Name, ID, what goes before every widget and what comes after it, and so on. This is where you can see that widgets sits in li tags, which we talked about previously.

001 // REGISTER SIDEBARS
002 function kihon_widgets_init() {
003
004 // Primary right column
005 register_sidebar( array(
006 ‘name’ =?> ‘Primary Right Column’,
007 ‘id’ =?> ‘primary-right-column’,
008 ‘description’ =?> ‘The primary right column.’,
009 ‘before_widget’ =?> ‘< li id=”%1$s”
class=”widget-container %2$s”?>’,
010 ‘after_widget’ =?> ‘< /li?>’,
011 ‘before_title’ =?> ‘< h3
class=”widget-title”?>’,
012 ‘after_title’ =?> ‘< /h3?>’
013 ) );
014
015 }
016 add_action( ‘widgets_init’, ‘kihon_
widgets_init’ );

03. Comment callback
Now we’ve got the comment callback part. This is trickier, and as we don’t have room to delve into the comments.php template, we’ll just breeze it. kihon_comment() is called by wp_list_comments() in comments.php to control how comments are displayed. Refer to comments.php in the theme and you’ll see how it connects.
Finally, as we started with a < ?php tag, we need to close it. And that’s it for our functions.php file.

 001 // COMMENT CALLBACK
002 function kihon_comment($comment, $args, $depth) {
003 $GLOBALS[‘comment’] = $comment; ??>
004 < li < ?php comment_class(); ??> id=”li-
comment-< ?php comment_ID() ??>”?>
005 < div id=”comment-< ?php comment_
ID(); ??>” class=”comment-body”?>
006 < div class=”comment-author vcard”?>
007 < ?php echo get_avatar($comment,
$size=’32’,$default=’< path_to_url?>’ ); ??>
008 < ?php printf(__
(‘< cite class=”fn”?>%s< /cite?> < span
class=”says”?>says:< /span?>’), get_comment_
author_link()) ??>
009 < /div?>
010 < ?php if ($comment-?>comment_
approved == ‘0’) : ??>
011 < em?>< ?php _e(‘Your comment is
awaiting moderation.’) ??>< /em?>
012 < br /?>
013 < ?php endif; ??>
014
015 < div class=”comment-meta
commentmetadata”?>< a href=”< ?php echo
htmlspecialchars( get_comment_link(
$comment-?>comment_ID ) ) ??>”?>< ?php printf(__
(‘%1$s at %2$s’), get_comment_date(), get_
comment_time()) ??>< /a?>< ?php edit_comment_
link(__(‘(Edit)’),’ ‘,’’) ??>< /div?>
016
017 < ?php comment_text() ??>
018
019 < div class=”reply”?>
020 < ?php comment_reply_link(array_
merge( $args, array(‘depth’ =?> $depth, ‘max_
depth’ =?> $args[‘max_depth’]))) ??>
021 < /div?>
022 < /div?>
023 < ?php }
024
025 ??>

THE FINISHED THEME

That’s it – Kihon is done!
No, wait, it isn’t. Themes are almost never done, they are merely works in progress. This theme might be in working order right now, but it isn’t done. When browsing through the theme files, you’ll no doubt note that there are more files there than we went through here. Most notably, single.php and content-single.php, as well as page.php and its content-page.php, not to mention comments.php. By now you should have enough knowledge to be more than able to wade your way through these files and start making changes on your own.
There are features to be added to Kihon that we couldn’t fit this time, such as featured images for posts, for example. The theme should also be responsive, so there’s that to take into account, and don’t you think you should have more flexible sidebars? Also, this theme would do well with support for at least some Post Format.
There are always things to do, as I’m sure you know as a web developer, but when it comes to WordPress it is ridiculously true. Just you wait – a future version of the platform will no doubt add additional features that you’ll want to use with your own creations.
I urge you to dive into the Kihon code, learn what you can and take what you like for your own projects. I also recommend looking at the default themes that come with WordPress. They adhere to WordPress coding standards and are a great way to learn more.

×