WP_Query is a powerful tool to control what comes out of your loop. Today I'm going to teach you all how to use it to make a 3 columned newspaper theme that has all your main blog posts in the main column, and off to the side a set of posts with a certain category. We'll be using the 960 CSS framework for the basic layout and reset of our theme, it will chop a lot of work off what's needed!
Our plan of attack is to take out all posts with a shared assigned category, and
place them off to the side separate from the main posts. We'll also look at a method
we're aiming to achieve today. Download the .psd here.
We assume that you have a live WordPress installation, whether it be local or hosted. If you need a bit of help with that, it's worth first learning how to install WordPress locally on Windows or OS X.
Step 1: The Necessities
Alrighty. So apart from the obvious need of a WordPress installation, we're going
to need a few extra things too. I got a whole bunch of files you're gonna need to
have in your theme folder.
- Everything must go in a theme folder withing wp-content/themes/, so create
a folder named triColumnNews, and place everything proceeding in it!
960 CSS Framework - This is kinda obvious too. Within your triColumnNews
folder, create another folder named 960. Head over to
960 Grid System and pick up a copy of the framework. In the download you'll
find some folders. Open the folder aptly named 'code' and copy the 3 CSS files (960.css,
reset.css and text.css) into the 960 folder you created a second
ago. That's all sweet now.
functions.php - We're gonna be needing a sidebar, so we need functions.php
to register it.
images folder - Well duh... Every decent theme has some images! Create
the folder images, and place
searchBg.png in it.
- index.php - An obvious concept... We'll work mainly on this.
page.php and single.php - Our index page will have 3 columns right? But
I don't think individual pages require 3 columns. We change the sub template pages
at the very end so that if you do go to a page, it's not all muddled due to the
incorrect WP_Query on the index (incorrect for the specific page, not the index).
- Copy that over and edit it accordingly if you wish.
Got all that? Good. You should be set for the rest of the tutorial now! Don't forget
to activate the theme in WP-admin (wp-admin/themes.php).
Step 2 - HTML and basic WordPress Code
I'm not going to give you all the WordPress code just yet. I'm going to give you
all the WordPress code you need excluding the WP_Query's. They'll have a step in
their own, because they definitely need explanation! It'd fill up the page WAY too
much, so I've included it all in a .txt rather than here.
Download it, and copy it into index.php. Or type it, whatever suits. Typing
helps you remember what you're doing!
Some things to note
That's a whole lot of code to process, so I'll just snag out the interesting parts
for you, and explain them.
head - This is all just WordPress stuff. Stylesheet, RSS2 link, and some
#dateAndTime - Have you ever read a newspaper that doesn't have the date
up top? Me neither. Let's not start now, hm? This displays the date in the format:
(Thu 17th July 08). We'll float this way up top so it stays in the browser window
at all times! Just because...
form id="searchform" - This is the searchform for the blog! I just stuck
one in to fill up space and make it all the more convincing!
dynamic_sidebar - That basically explains it... It's the sidebar we want,
named triNews so it can be identified in Dashboard.
Note - You can see that it's already starting to take shape in
terms of layout (a very squewif layout, but not the reset!) - I've imported the
960 files using an @import in style.css, to save HTTPRequests, and it also gives
our code parent power over the 960 code.
- All the little funny classes... Read on.
The 960 classes
So I bet you're noticing all these little 'grid_5' and 'container_12' classes and
going what the heck is that? Well let me explain to you. The number following 'grid_'
is the number of columns we want that select div to be. Because we want 12 columns,
we wrap the whole thing (using div#wrapper) with the 'container_12' class.
In the basic CSS I provided you with, it has the imports for the three 960 files,
so we already have half a layout when we've not coded any CSS at all!
This won't look too flashy. It hasn't been styled and it doesn't even have content:
Step 3 - WP_Querys
This is where all the magic happens! We have three WP_Querys:
theirNews - So we have split news, right? We want this section to only
show posts with the category 'theirNews'. On my part, (of my test blog) I've given
about 7 of my posts this category. You should go give them some too. You also need
to find the category ID of theirNews category, but I'll quickly take you through
how to find that later.
featured - Remember I said I'll show you how to make a featured post without
jQuery? Here's the solution in a nutshell: only show the most recent post to date
in it's own query loop.
main - the trick with this is that we don't want the category of theirNews
in here, nor do we want the first post. It's easy, you'll see in a minute.
Step 3:1 - theirNews
So we want a column of WordPress content from only a single category. How do we
do that? Using the vast range of parameters WP_Query provides us
with, it's easy to do so. Replace the theirNews comment in index.php with:
<?php $theirNews = new WP_Query(); $theirNews->query('category_name=theirNews&showposts=7'); while($theirNews->have_posts()) : $theirNews->the_post(); ?> <!-- LOOP CONTENT HERE --> <?php endwhile; ?>
Query! Let's jump right into it.
$theirNews is the variable query we'll be using for the 'theirNews' section.
This defines a new query, the whole basis of WP_Query.
query(); - Here are our specific parameters. We only want to show maximum
7 posts, all under the category name 'theirNews'. You can change these variables
around of course, 7 is just the number of posts I have the category assigned to.
- The rest of the code is a shortened loop, that is specified using our $theirNews
We need some specific loop code.
<div class="post"> <h4><?php the_title(); ?></h4> <div class="entry"> <?php the_content('<br />Read complete article'); ?> </div> </div>
Simply the title wrapped in a h4 tag, with the content wrapped in a div
classed 'entry'. Great! You've done your first WP_Query out of the 3, that should
now list only categories with the name 'theirNews'
Step 3:2 - featured
We only want to show 1 post, that doesn't have the category 'theirNews'. Only 1.
Since you now understand the fundamentals of WP_Query, I'll give you the full code
(replace the FEATURED POST comment with):
<div id="featuredPost" class="post"> <?php $featured = new WP_Query(); $featured->query('showposts=1&cat=-59'); while($featured->have_posts()) : $featured->the_post(); ?> <h2><?php the_title(); ?></h2> <em class="postMetaData">Posted under <?php the_category(', '); ?>.</em> <div class="entry"> <?php the_content('Read complete article'); ?> </div> <?php endwhile; ?> </div><!-- end div#featuredPost -->
This is our featured post, so I have aptly named the div 'featuredPost',
but because later on we'll also want styles from regular posts, I've included the
Same deal with the WP_Query. This time the parameters show only 1 posts that isn't
from the category 59. Category 59 is the ID of the category 'theirNews'. I need
to tell you how to get it!
- Open up WP-Admin.
- Click on manage.
- Click on Categories.
- Click on the category 'theirNews' (or whatever you've called it).
- Check the URL of the page. It should be something like this:
See how it's got &cat_ID=59 at the end? This is your category number.
Mine is 59, make sure you change it to whatever the ID of your 'theirNews' category!
- Remember that number, we'll need it in the next Query too.
The difference with the featured post is mainly the h2. Because it's the
second largest header on the page. Way up in the 'theirNews' section we wrapped
in in a h4 element, because after the main column's posts it'll be the
next header on the page. All for styling sake.
Step 3:3 - main
Our last WP_Query. This one will be all posts excluding posts contained
by the 'theirNews' category (You need the ID. Mine was 59, can you remember yours?).
But because we're already showing the first post overall (the feature
post), we don't want to show it again, right? So we need to offset the posts by
1 - easy to do with WP_Query's powerful parameters.Replace the MAIN WP QUERY comment
in index.php with this:
<?php $main = new WP_Query(); $main->query('posts_per_page=5&offset=1&cat=-59'); while($main->have_posts()) : $main->the_post(); ?> <div class="post"> <h3><?php the_title(); ?></h3> <em class="postMetaData">Posted under <?php the_category(', '); ?>.</em> <div class="entry"> <?php the_content('<br />Read complete article'); ?> </div> </div> <?php endwhile; ?>
posts_per_page - Is exactly what it is... When you get onto adding next
and previous pages it overrides what you set in WP-Admin. I have 3 as the default,
and couldn't be bothered changing so I made it 5 for the main column.
offset - Remember how I said we need to not show the first post, because
we already have it in the featured post section.
cat=-59 - We need to specify which category not to include - theirNews
- and for me, it has the ID of 59. The '-' right before the number basically counts
So that's all the HTML and WordPress code we need. It will still look basic, but
it will have the general 3 column layout we're after!
Step 4 - CSS
Now because all our layout is pretty much done, it's mainly only styling that's
all this CSS, and paste it into your style.css. There are a few things that
override the default 960 code. We don't need to use !IMPORTANT because
the new code is actually higher up the hierarchical ladder than the 960 code. We
use the 960 code as a sort of 'base' that we build up from. If you decorate the
foundations of a house, do you still see the raw foundations? This 'decoration'
is mainly on headers, but some general styling is used for text content etc. One
major override is the body font. We specify Georgia, when the default is actually
Helvetica. Fonts are really up to your preference, I've just used Georgia to be
different! Once you've pasted and read through all the CSS, the front page should
Step 5 - Sub Template Files (optional)
I'm only including this section so I don't get a zillion questions asking why individual
pages return the information that should be on the main page! So our index
page has 3 columns - But what would you fill 3 columns with in a specific single
page? Whatever you want! Though I'd suggest the content of the post... So I'm going
to explain just how page.php and single.php work, in case you
want to extend the theme. If you want to split index.php into header, sidebar and
footer, do so now! Otherwise, we'll steam onwards:
- Open up single.php.
- Copy all the code from index.php into single.php.
- Scroll down til you get to div#theirs.
- Delete the whole div. While you're at it, delete the featured post too!
- All you should have left is div#main.grid_5. Change the 5 to a 9 to compensate
for the 4 columns we just got rid of.
- Don't forget to change the end div comment so you don't get confused later on!
So now you should have an empty main column. We're going to fill this up with a
<?php if(have_posts()) : while(have_posts()) : the_post();?> <div class="post"> <h2><?php the_title(); ?></h2> <em class="postMetaData">Posted under <?php the_category(', '); ?>.</em> <div class="entry"> <?php the_content('Read complete article'); ?> </div> </div><!-- end div.post --> <?php endwhile; ?> <?php endif; ?>
Naw... The regular old boring loop. Feel free to spruce this single page up to whatever
you want your single posts to look like. This provides the basic
template for WordPress to display a single post.
Step 5 Part 2
So that's a single post, but we still have links to single pages in the
navigation and footer. If you click them, they will return the same as the index.
Not cool. All we need to do though, is copy everything from single over to page.php,
and it should be sweet. Easy huh? These Pages should look something like this:
So you've just had a glimpse at what WP_Query can do. I strongly suggest visiting
the Query posts docs page, which has all the same parameters as WP_Query. You can narrow your loop down to any specific post using any combination of the parameters separated by a
I hope you guys have had as much fun as I have creating a newspaper looking theme!
You can view the final product here! Enjoy!