WordPress Theme from Scratch – Day 3: HTML to WordPress

written by aext on January 8, 2010 in PHP and Popular and WordPress with 49 comments

This tutorial is in the series of “WordPress Theme from Scratch” that helps you build a WordPress theme by yourself from nothing. Previous tutorial in this series helped we convert a mockup in PSD to HTML and today, we will continue to go to last tutorial: build WordPress theme from the HTML file.

The most difference between WordPress and other blog platforms in theme development is WordPress theme more easier than others for development. In basic, the elements of wordpress theme likes blocks and building WordPress theme likes we build these blocks to make them to fit together.

In WordPress template, some file we will use to display it in all page on our website such as: header, footer, sidebar … and other file we have to customize it to fit our requirements under specific conditions. If you are going to build a WordPress theme, I recommend to take a look at “Using_Themes section in WordPress Codex” to understand how a theme built.

Prepare files for theme


In this tutorial, I will help you build your first WordPress theme that works. That means I’m gonna build some important files that WordPress requires to run without errors. My FrozenFlirt WordPress theme should contains these files:

--FrozenFlirt
-----header.php
-----index.php (Homepage display)
-----single.php (Post display)
-----archive.php (Archive display for categories, tags, date, authors...)
-----comments.php (Comment temple include form, post comments)
-----sidebar.php
-----functions.php (All of your template functions will go here)
-----footer.php
-----style.css
-----image
-----js

Note: These files need for your template works with basic requirements such as: post, categories, tags, authors, search … viewing. If you want more, build as same as we are doing here with 404 display, links template …

Before start, copy all images in this HTML layout to images directory and all css files to the root theme folder. Furthermore, this theme is using one javascript file call script.js, so copy this file to folder js.

Let’s begin!

Split HTML layout


We will use header, sidebar and footer to display in all pages, so we need to split our HTML file into 3 main parts: header.php, sidebar.php and footer.php.

Refer to the HTML file in previous tutorial: WordPress Theme from Scratch – Day 2: PSD to HTML and after splitting, we have these files:

header.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type"content="text/html; charset=UTF-8" />
    <title>FrozenFlirt WordPress Theme From Scratch</title>
    <link href="reset.css"rel="stylesheet"type="text/css" />
    <link href="style.css"rel="stylesheet"type="text/css" />
    <link href="pagenavi-css.css"rel="stylesheet"type="text/css" />
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"type="text/javascript"></script>
    <script src="script.js"type="text/javascript"></script>
    <script type="text/javascript">

        $(document).ready(function() {

            var id = '35591378@N03';
            flickr(id);

            });

    </script>

</head>

<body>

    <div id="main-wrapper">

        <div class="container">

            <div id="header">

                <ul id="topmenu">
                    <li>
                        <a href="#"title="Home Page"><span>Home</span></a>
                    </li>
                    <li>
                        <a href="#"title="Tutorial Category"><span>Tutorial</span></a>
                    </li>
                    <li>
                        <a href="#"title="Freebie Category"><span>Freebie</span></a>
                    </li>
                    <li>
                        <a href="#"title="Inspiration Category"><span>Inspiration</span></a>
                    </li>
                    <li>
                        <a href="#"title="Resources Category"><span>Resources</span></a>
                    </li>
                </ul>

                <div id="topsearch">
                    <form action="http://aext.net/"id="searchform"method="get">
                        <fieldset>
                            <input type="text"                                    onblur="if (this.value == '') {this.value = 'Type Keywords And Hit Enter...';}"                                    onfocus="if(this.value == 'Type Keywords And Hit Enter...') {this.value = '';}"                                    value="Type Keywords And Hit Enter..."                                    class="searchfield"id="searchbox"name="s"/>
                        </fieldset>
                    </form>
                </div>

                <div class="clear"></div>

                <div id="logo">
                    <a href="#"title="FrozenFlirt Homepage"><h1>FrozenFlirt Theme</h1></a>
                    <h3>"Wordpress Theme From Scratch"</h3>
                </div>

                <div class="clear"></div>

            </div>

sidebar.php

            <div id="sidebar">

                <div class="widget"id="adblocks">

                    <a href="#"title=""><img src="images/ads/vivatheme.png"alt="Viva Theme" /></a>
                    <a href="#"title=""><img src="images/ads/pixelcrayons.jpg"alt="Pixel Crayons" /></a>
                    <a href="#"title=""><img src="images/ads/wpbest.gif"alt="WPBEST" /></a>
                    <a href="#"title=""><img src="images/ads/buysellstockdesign.gif"alt="Buy Sell Stock Design" /></a>

                </div>

                <div class="widget"id="popular-posts">
                    <h3>Popular Posts</h3>
                    <ul>

                        <li><a title="blablabla"href="#"><span class="wpp-post-title">5 New Useful jQuery Plugins For Your Next Projects</span></a> </li>
                        <li><a title="blablabla"href="#"><span class="wpp-post-title">35 Fresh and Cool Web Design Interfaces for Inspiration</span></a> </li>
                        <li><a title="blablabla"href="#"><span class="wpp-post-title">Bubble Effect with CSS</span></a> </li>
                        <li><a title="blablabla"href="#"><span class="wpp-post-title">CSS Absolute Positioning: Create A Fancy Link Block</span></a> </li>
                        <li><a title="blablabla"href="#"><span class="wpp-post-title">Incredible Drop Down Menu Solution With CSS Only</span></a> </li>
                    </ul>

                </div>

            </div>

            <div class="clear"></div>

footer.php

            <div id="flickr-stream">

                <h3>Flickr Stream</h3>
                <hr />
                <div class="clear"></div>
                <div id="flickr">
                    <noscript>Your message for people w/o javascript enabled goes here.</noscript>
                </div>

            </div>      

            <div id="twitter-update">
                <h3>Twitter Update</h3>
                <hr />
                <div class="clear"></div>
                <div id="twitter">
                    <ul id='twitter_update_list'></ul>
                </div>
                <a href="http://twitter.com/prlamnguyen"title="Follow me on twitter"><span id="followme">Follow Me!</span></a>

            </div>                      

        </div>

    </div>

    <div class="clear"></div>

    <div id="footer-wrapper">

        <div class="container">

            <p id="copyright">&copy;2009 FrozenFlirt. All Rights Reserved</p>

            <p id="designedby">WordPress Theme Design by <a href="http://aext.net"><img src="images/aext.png"alt="Theme by AEXT.NET" /></a></p>

        </div>

    </div>

    <script type="text/javascript"src="http://twitter.com/javascripts/blogger.js"></script>
    <script text="text/javascript"src="http://twitter.com/statuses/user_timeline/prlamnguyen.json?callback=twitterCallback2&count=2"></script>

</body>
</html>

The remain part we will use for replace with the content.

header.php


The header file need to declare the blog title, description (if you are using SEO plugin, I don’t think this part is important), blog feed, pingback… And off course, you need to put your stylesheet here.

Put these code to your header for:

HTML type

<meta http-equiv="Content-Type"content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />

Blog title

<title><?php wp_title('&laquo;', true, 'right'); bloginfo('name'); ?></title>

Blog description

<meta name="description"content="<?php bloginfo('description'); ?>" />

Feed and pingback

<link rel="alternate"type="application/rss+xml"title="<?php bloginfo('name'); ?> RSS Feed"href="<?php bloginfo('rss2_url'); ?>" />
<link rel="alternate"type="application/atom+xml"title="<?php bloginfo('name'); ?> Atom Feed"href="<?php bloginfo('atom_url'); ?>" />
<link rel="pingback"href="<?php bloginfo('pingback_url'); ?>" />

Because you will upload this theme to the themes folder, you need to gather the blog directory to import exactly the url to your css, javascript … files. Using this code, you will get the url to your template folder:

<?php bloginfo('template_url'); ?>

Link to your stylesheet using code above:

<?php

  print '<style type="text/css" media="all">';

  print '@import "'.get_bloginfo('template_url').'/reset.css";';
  print '@import "'.get_bloginfo('template_url').'/style.css";';  
  print '@import "'.get_bloginfo('template_url').'/pagenavi-css.css";';

  print '</style>';

?>

For more information about bloginfo, check this page Template Tags/bloginfo.

DON’T FORGET to put these code before closing the head tag

<?php wp_head(); ?>

This is one of the most essential theme hooks. You use this hook by having your function echo output to the browser, or by having it perform background tasks. This is very important because all of the plugins installed will use this hook to output their code such as css and javascript to template header.

In this theme, you can see that I made the rounded border style for the categories link on header. It will be easy to list all category links if we just make simple links by using this code:

    <ul>
      <li><a href="<?php bloginfo('url'); ?>">Home</a></li>

      <?php echo wp_list_categories('echo=0&title_li='); ?>

    </ul>

However, this function just generate a list of category with links and we cannot put a span tag inside the link to make a rounded border style like what we do with the HTML template.

This is why we use this code instead;

<ul id="topmenu">
    <li>
       <a href="<?php bloginfo('url'); ?>"title="Home Page"><span>Home</span></a>
    </li>

    <?php

        $args=array(
            'orderby' => 'name',
            'order' => 'ASC'
        );

        $categories=get_categories($args);

            foreach($categories as $category) {
                echo '<li>';
                echo '<a href="' . get_category_link( $category->term_id ) . '" title="' . sprintf( __( "View all posts in %s" ),                       $category->name ) . '" ' . '><span>' . $category->name.'</span></a> </p> ';
                echo '</li>';
            }
    ?>

</ul>

Now, with the css code I provided previous tutorial, we can build great rounded border link style.

[smartads]

sidebar.php


Actually, the sidebar is very simple. Themes usually have at least 1 or 2 sidebars, in this case, we have one. Each section in the sidebar is known as a “widget” that you can add or remove, and move up or down. You can configure your sidebar by going to Appearance > Widgets. Because nothing is special here, we only need to make it ready for widgets. That means you can add/remove widget in your sidebar in admin panel. In this case, I will keep the ads section as HTML, other widgets will be updated through widgets configuration.

In your sidebar.php, add these code:

<div id="sidebar">

    <div class="widget"id="adblocks">

        <a href="#"title="">
            <img src="<?php bloginfo('template_directory'); ?>/images/ads/vivatheme.png"alt="Viva Theme" />
        </a>
        <a href="#"title="">
            <img src="<?php bloginfo('template_directory'); ?>/images/ads/pixelcrayons.jpg"alt="Pixel Crayons" />
        </a>
        <a href="#"title="">
            <img src="<?php bloginfo('template_directory'); ?>/images/ads/wpbest.gif"alt="WPBEST" />
        </a>
        <a href="#"title="">
            <img src="<?php bloginfo('template_directory'); ?>/images/ads/buysellstockdesign.gif"alt="Buy Sell Stock Design" />
        </a>

    </div>

    <?php if( !function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : ?>

    <?php endif; ?>

</div>

<div class="clear"></div>

The code above will keep the ads section stays in the sidebar even when you add widgets in admin panel or not. Other widgets will be added through admin panel and be right next below to ads block.

However, that’s not enough. Because, in this case, we are setting up the sidebar widgets as div elements, we need to set up the sidebar format by using register_sidebar() in functions.php file. In functions.php file, add these code:

// register sidebars if( function_exists('register_sidebar')) {
    register_sidebar(array(
        'name' => 'Default sidebar',
        'id' => 'sidebar-1',
        'before_widget' => '<div class="widget" id="%1$s">',
        'after_widget' => '</div>',
        'before_title' => '<h3>',
        'after_title' => '</h3>'
    ));
}

This code used for register the default side that all widgets inside it will come inside div element with class name widget and their id by plugin widgets. The title of each widget will be wrap by an h3 tag.

That’s all you need for a sidebar with widget ready. Download this plugin WordPress Popular Posts, install, active then drag the widget to the sidebar. Done!

footer.php file


Honestly, there is nothing important here. Some blog design their beautiful footer with a lot of stuff, but in this case we only create two widgets for Flickr stream and Twitter update using javascript to make this tutorial simple. These widget display will depend on the user’s Flirkr and Twitter account, so we will create these widget display base on the options that user will put their account in. Luckily I published an useful posts “WordPress Theme Design with Options Adminstration“. Now, you have to check this post first because it’s very complicated step that should not put here for a very long long long tutorial. It’s not necessary, but at least put some code for this tutorial more complete.

In functions.php file, put these code for theme options:

// theme options $options = array(

  array(    
    "name" => "<strong>Flickr ID</strong>",
    "desc" => "Enter your Flickr ID to display Flickr Stream widget",
    "id" => "flickr_account",
    "default" => ""),

  array(    
    "name" => "<strong>Twitter Account</strong>",
    "desc" => "Enter your Twitter username to display Twitter Update widget",
    "id" => "twitter_account",
    "default" => "prlamnguyen"),

);

These lines of code will control the form submission of the theme options:

function frozenflirt_options() {
  global $options;

  if('theme_save'== $_REQUEST['action'] ) {

    foreach($options as $value) {
     if( !isset( $_REQUEST[ $value['id'] ] ) ) {  } else { update_option( $value['id'], stripslashes($_REQUEST[ $value['id']])); } }
     if(stristr($_SERVER['REQUEST_URI'],'&saved=true')) {
     $location = $_SERVER['REQUEST_URI'];
    } else {
     $location = $_SERVER['REQUEST_URI'] . "&saved=true";
    }

    header("Location: $location");
    die;

  } else if('theme_reset' == $_REQUEST['action'] ) {

    foreach($options as $value) {
     delete_option( $value['id'] );
     $location = $_SERVER['REQUEST_URI'] . "&reset=true";
    }

    header("Location: $location");
    die;

  }

  add_theme_page('FrozenFlirt Theme Setting', 'FrozenFlirt Theme Setting', 10, 'frozenflirt-settings', 'frozenflirt_admin');
}

And these code for the UI in admin panel:

<?php
function frozenflirt_admin() {
    global $options;
?>
<div class="wrap">
  <h2 class="alignleft">Theme Setting</h2>
  <br clear="all" />

  <?php
    //Check if settings saved!     if( $_REQUEST['saved'] ) {
  ?>
        <div class="updated fade"><p><strong>Setting Saved</strong></p></div>
  <?php } ?>

<form method="post"id="myForm">
<div id="poststuff"class="metabox-holder">

 <div class="stuffbox">
  <h3>Footer Setting</h3>
  <div class="inside">
    <table class="form-table"style="width: auto">
    <?php
     foreach($options as $value) {
      switch( $value['id'] ) {
        case "flickr_account": ?>
        <tr>
        <th scope="row"><?php echo $value['name']; ?><br /><?php echo $value['desc']; ?></th>
        <td>
         <input name="<?php echo $value['id']; ?>"                 id="<?php echo $value['id']; ?>"type="text"                 value="<?php get_option($value['id'])?printf(get_option($value['id'])): printf($value['default']) ?>" />
        </td>
        </tr>

      <?php break;
        case "twitter_account": ?>
        <tr>
        <th scope="row"><?php echo $value['name']; ?><br /><?php echo $value['desc']; ?></th>
        <td>
         <input name="<?php echo $value['id']; ?>"                 id="<?php echo $value['id']; ?>"type="text"                 value="<?php get_option($value['id'])?printf(get_option($value['id'])): printf($value['default']) ?>" />
        </td>
        </tr>

      <?php break;
        }
    }
    ?>
   </table>
  </div>
 </div>  

</div>
<input name="theme_save"type="submit"class="button-primary"value="Save changes" />
<input type="hidden"name="action"value="theme_save" />
</form>

<form method="post">
<input name="theme_reset"type="submit"class="button-primary"value="Reset" />
<input type="hidden"name="action"value="theme_reset" />
</form>

</div>
<?php
}
?>

Your theme options adminstration will look like:

We are good now with the theme options. Let’s get these value to display in the theme. In your footer.php, insert these code to your Twitter widgets to get twitter account name from theme options:

<script type="text/javascript"src="http://twitter.com/javascripts/blogger.js"></script>
<script type="text/javascript"src="http://twitter.com/statuses/user_timeline/<?php if(!get_option('twitter_account')) { echo 'prlamnguyen'; } else { printf(get_option('twitter_account')); } ?>.json?callback=twitterCallback2&count=2"></script>

In this code above, if the option value of twitter_account doesn’t exist, this widget will display twitter update from my twitter account by default. :D

With Flickr Stream widget, go back to header.php file to edit because I put the jQuery code to get stream from specific account on header.php file. I’m so sorry! If you want, move this code block to the footer.php file. That’s fine!

<script type="text/javascript">

        $(document).ready(function() {

            var id = '<?php printf(get_option('flickr_account')); ?>';
            flickr(id);

        });

</script>

Alright, now you have done for the three files that will used in all pages. Now, we continue to go forward to other pages that display in homepage, post pages, categories pages…

index.php


This file will used for display in the main page of your blog. It usually displays a number of recent articles. The number of posts will be display was set up in your WordPress Admin > Setting > Readingas below:

By default, you don’t need to query posts in homepage, the only code for the loop of display post in homepage is:

<?php

//The Loop if( have_posts() ) :

    while( have_posts() ) : the_post();

        //Posts in the loop     
    endwhile;

else:

        //No post in homepage ?????      
endif;

?>

However, sometime we need to display post in homepage with conditions. An example with Noupe.com, they are using the Community News which all of news were submit will go to News category, but they don’t want to display a lot of community news in homepage. The best way to do is override and replace the main query in homepage. In the case I have just mentioned(At this time, Noupe has disabled Community submission !!!), the replaced query will be:

<?php

//Begin replace the main query query_posts('cat=-155'); //155 is the id of Community News category 
//The Loop if( have_posts() ) :

    while( have_posts() ) : the_post();

        //Posts in the loop     
    endwhile;

else:

        //No post in homepage ?????      
endif;

//Reset the query wp_reset_query();

?>

With the query_posts, you can change the order, number of posts…. I would like to forward a link to Template Tags/query posts to check more information and usages.

Way back to the tutorial, you already knew how to use the loop in display posts, now we begin to work with our index.php. But at first, you have to clean this index.php because we have 4 blocks of post in HTML template. Keep only one post excerpt, remove all of others.

Before starting write code for display post excerpts, we need to look back to the split files. You remember that we split our HTML file into 3 files: header.php, sidebar.php and footer.php. Now, we need to include them again. In index.php file, put your header, sidebar and footer:

<?php

/**  * @package WordPress  * @subpackage FrozenFlirt_Theme  */
?>

<?php get_header(); ?>

            <div id="main-content">

                ..........

            </div>

            <?php get_sidebar(); ?>

<?php get_footer(); ?>

In main content elements, we write a loop of post to display:

<div id="main-content">
  <div class="container">

    <?php

    if(have_posts()) : while(have_posts()) : the_post();

    ?>

    <div class="post exerpt clearfix">
      <a href="#">
        <img alt="ahh ahh ahh"src="images/post-image-1.png"width="200"height="200"class="thumbnail" />
      </a>

      <h2><a href="#"rel="nofollow">Fronze Flirt Theme</a></h2>

      <small>Written by <a href="#"title="Lam Nguyen">Lam Nguyen</a> on <strong>Dec 11th</strong> in <a href="#"title="Tutorial Category">Tutorials</a></small>

      <div class="summary">
        <p>Lorem ipsum dolor sit amet, this is bold text consectetur adipiscing elit. This font is in italic cras lacinia pellentesque elit nec sodales. Etiam vehicula egestas interdum. Nulla facilisi. In at lectus odio, quis iaculis dui. </p>
        <p><a rel="nofollow"title="Read more this post"href="#">Continue Reading &raquo;</a></p>
      </div>

    </div>

    <?php endwhile; ?>

        <?php if(function_exists('wp_pagenavi')) : ?>
            <?php wp_pagenavi() ?>
        <?php else : ?>
            <div class="navigation"id="pagenavi">
                <div class="alignleft">
                    <?php next_posts_link(__('&laquo; Older Entries','arclite')) ?>
                </div>
                <div class="alignright">
                    <?php previous_posts_link(__('Newer Entries &raquo;','arclite')) ?>
                </div>
                <div class="clear"></div>
            </div>
        <?php endif; ?>

    <?php else: ?>
        <p><?php printf("Sorry, no posts matched your criteria."); ?></p>
    <?php endif; ?>

  </div>
</div>

This loop will display the number of post with the same title, thumbnail, description… because we haven’t change the code to display correct post title, post description… These code below is used for replace the HTML in the loop:

<?php
    if(have_posts()) : while(have_posts()) : the_post();          
?>
<div class="post excerpt clearfix">
  <a href="<?php the_permalink() ?>">
  <?php
        if( has_post_thumbnail() ) {
            the_post_thumbnail(array(200,200), array('class' => 'thumbnail'));
        } else {
            // Who doesn't want a thumbnail??         }
  ?>
  </a>
  <h2><a rel="nofollow"  href="<?php the_permalink() ?>">
    <?php the_title(); ?>
    </a></h2>

  <small>
        Written by <?php the_author_posts_link(); ?>
                on <strong><?php the_time('F jS') ?></strong>
                in <?php the_category(', '); ?>
  </small>

  <div class="summary">
    <?php the_content( 'Continue Reading &raquo;' ); ?>
  </div>

</div>
<?php endwhile; ?>

Wow, we’re going to the most interesting feature of WordPress 2.9: Thumbnail Generation for Post. You remember, in the past, how we made thumbnail for a post? It was really a nightmare with a lot of code and stuff. Today, everything has changed. With few lines of codes, you can insert thumbnail for posts easily.

In functions.php file, insert these code to active the new feature:

add_theme_support( 'post-thumbnails', array( 'post' ) );

You can make this feature active for posts, pages… but for posts only in this case. Display the thumbnail within the loop:

<a href="<?php the_permalink() ?>">
    <?php
        if( has_post_thumbnail() ) {
            the_post_thumbnail(array(200,200), array('class' => 'thumbnail'));
        } else {
            // Who doesn't want a thumbnail??         }
    ?>
</a>

This code will display the thumbnail with dimension: 200×200 pixels and the img tag is with class name thumbnail. The thumbnail will be added when writing post:

I recommend this post for new feature Post Thumbnail references: Using The New Post Thumbnail Feature In WordPress 2.9.

archive.php


This file will used for display category archive, tag archive… The easiest way is copy all code of index.php page and past it to archive.php because tag or category archive usually display in the same way as index page. In WordPress, when develop theme, the posts query was already made by WordPress, so that’s why we need just copy and paste content of index.php to the archive.php file. As I said above, if you need to display something different such as: posts order, number of posts will be displayed… just use the query_posts()function to override and replace the main query for the page.

However, in archive.php file, you need to notify users which page they are on. Insert these code on the top, before display the loop of posts:

                ...

                <?php

                if(have_posts()) :

                ?>

      <?php $post = $posts[0]; // Hack. Set $post so that the_date() works. ?>
      <?php /* If this is a category archive */ if(is_category()) { ?>
        <h2 class="pagetitle">Archive for the &#8216;<?php single_cat_title(); ?>&#8217; Category</h2>
      <?php /* If this is a tag archive */ } elseif( is_tag() ) { ?>
        <h2 class="pagetitle">Posts Tagged &#8216;<?php single_tag_title(); ?>&#8217;</h2>
      <?php /* If this is a daily archive */ } elseif(is_day()) { ?>
        <h2 class="pagetitle">Archive for <?php the_time('F jS, Y'); ?></h2>
      <?php /* If this is a monthly archive */ } elseif(is_month()) { ?>
        <h2 class="pagetitle">Archive for <?php the_time('F, Y'); ?></h2>
      <?php /* If this is a yearly archive */ } elseif(is_year()) { ?>
        <h2 class="pagetitle">Archive for <?php the_time('Y'); ?></h2>
      <?php /* If this is an author archive */ } elseif(is_author()) { ?>
        <h2 class="pagetitle">Author Archive</h2>
      <?php /* If this is a paged archive */ } elseif(isset($_GET['paged']) && !empty($_GET['paged'])) { ?>
        <h2 class="pagetitle">Blog Archives</h2>
      <?php } ?>

                <?php

                    while(have_posts()) : the_post();

                ?>

                ...

The result:

single.php


This file is used for display your WordPress posts. In this file, I will tell you a small trick. In HTML template, you see the post display as below:

<div class="summary">

    <p>Post Excerpt</p>

</div>

<div class="post-content">

    Post Main Content

</div>

If you put the_excerpt() and the_content() together to display as above. That will not work because the post excerpt will be duplicated. Even when put the excerpt to the Excerpt field which located below the post editor. This is good if you want to display links or images in your excerpt, but it doesn’t work here.

Alright, here is the trick. We will hook into the_content. In functions.php file, add these code:

add_filter('the_content', 'format_content');

function format_content($content) {

    if( preg_match('/<span id="(.*?)?"></span>/', $content, $matches) ) {

        $content = explode($matches[0], $content, 2);

        $content = '<div class="summary">' . $content[0] . '</div>' . $matches[0] . '<div class="post-content">' . $content[1] . '</div>';
    }

    return $content;

}

We will split the content into 2 parts then wrap each part by specific div tag with class name “summary” and “post-content”. Is that cool?

And this is the complete code of single.php file:

<?php

/**  * @package WordPress  * @subpackage FrozenFlirt_Theme  */
?>

<?php get_header(); ?>

            <div id="main-content">
              <div class="container">

                <?php

                if(have_posts()) : while(have_posts()) : the_post();

                ?>

                <div class="post clearfix">
                    <a href="<?php the_permalink() ?>">
                    <?php
                        if( has_post_thumbnail() ) {
                            the_post_thumbnail(array(200,200), array('class' => 'thumbnail'));
                        } else {
                            // Who doesn't want a thumbnail??                         }
                    ?>
                    </a>

                    <h2><a rel="nofollow"  href="<?php the_permalink() ?>"><?php the_title(); ?></a></h2>                
                    <small>Written by <?php the_author_posts_link(); ?> on <strong><?php the_time('F jS') ?></strong> in <?php the_category(', '); ?></small>

                    <?php the_content(); ?>

                </div>

                <?php comments_template(); ?>

                <?php endwhile; ?>

                <?php else: ?>
                    <p><?php _e("Sorry, no posts matched your criteria.","arclite"); ?></p>
                <?php endif; ?>

              </div>
            </div>

            <?php get_sidebar(); ?>

<?php get_footer(); ?>

You have done with the single.php file, but don’t forget to put <?php comments_template(); ?> before ending the loop.

comments.php


WordPress fresh installed will come with the default theme and we can use some of those files to re-use. In default theme directory, open comments.php file, copy all the code then paste it to your new theme comments.php file. Use css to style the comment form and comments list. That’s all we need for the comment template.

I recommend some tutorial that help you build a better comment:

The most important when editing the comments.php file is DON’T FORGET to put these code before closing the comment form tag:

<?php comment_id_fields(); ?>
<?php do_action('comment_form', $post->ID); ?>

With page.php file to display pages, we are good to use the same code of single.php file because the in fact, page is a post.

Conclusion

This tutorial doesn’t guide you to build a completed WordPress theme, but at least it makes the WordPress Theme FrozenFlirt works with some basic function such as: view post, view index page, archive pages, comments…. If you need to build a completed theme with all of function you will need do more. The great place and my recommend website to learn how to mastering WordPress theme is WordPress Codex. Hope you guys design great WordPress theme from this tutorial. Any suggestion helps this tutorial more completed will be appreciated.