Genesis, Wordpress

How to Build a Genesis Child Theme

If you’d like to customize an existing WordPress theme, especially a theme framework like Genesis, the recommended approach is to use a child theme. A child theme is a separate theme that stores all of your specific customizations. That way if the parent theme is ever updated, you don’t lose all your hard work.

There’s two more benefits to child themes. First, you have a theme that only has your specific customizations in it. It makes it really easy to see what you did on a project, and to figure out what’s going wrong. You don’t have to dig through (and figure out) a ton of code that you didn’t write just to find out what’s going wrong.

Second, if you’re always using the same parent theme like I do, all the code you develop for one project is reusable on all future projects. Of course this depends on you using a parent theme that is designed to be customized through a child theme. This means it makes extensive of actions and filters, which are two types of hooks.

Hooks: What Are They, Why You Need Them

A hook is a tool that allows you to “hook into” the theme at a certain place. An action simply allows you to execute code at a certain place. A filter let’s you modify information that’s being used by the theme. Here’s two examples (these are in WordPress, so they work regardless of the theme you use):

wp_footer is an action that allows you to execute code at the bottom of your page. For example, if you wanted to add Google Analytics code to the bottom of every page, you’d put this in your functions.php file:

function be_google_analytics() {
   google analytics code goes here
}

add_action( 'wp_footer', 'be_google_analytics' );

excerpt_length is a filter that let’s you modify how much text is displayed when you use the_excerpt() in your theme. By default it returns 55 words. If you wanted to change that to 35 words, you would put this in your functions.php file:

function be_excerpt_length( $length ) {
   $length = '35';
   return $length;
}

add_filter( 'excerpt_length', 'be_excerpt_length' );

So as you see, hooks and filters allow you to modify things without editing existing code. You can do it from the safety of your own theme, where you don’t have to worry about your changes being lost on upgrade.

Genesis: The Only WordPress Theme Framework I Need

Here’s a few reasons why I prefer Genesis over all other themes:

  • Hooks for everything. Anything that you’d want to be customized, can be customized. I’ve yet to find something I need to edit that can’t be done easily with an action or filter.
  • Develop with code, not options. While Genesis does have a Theme Settings page, the vast majority of your development will happen with code. This means I don’t have to worry that the client will flip a switch and break the site.
  • Understandable file structure. Want to figure out how to customize something in the header? Hop in genesis/lib/structure/header.php. Customizing the menu class? Look at genesis/lib/classes/menu.php. It’s easy to explore Genesis core to find all the hooks and filters you need.
  • The Community. There’s a ton of other great Genesis developers that are sharing code and expertise. StudioPress listens to their users and adds the features they request. I’ve even submitted a few patches for Genesis which have made it in.
  • Business. By building sites with Genesis, my projects are featured on StudioPress.com, which drives me even more traffic and business. Almost all of my work comes from StudioPress.com leads.

There’s one more thing I want to cover, and that’s where to place your code. Anything that is related to the look and feel of the site belongs in the theme. Anything that is core functionality belongs in a plugin. Here’s a good rule of thumb: if your user decides to change themes, any functionality he expects to bring over to his next theme should be in a plugin.

It’s also a good idea to turn things you use often or that the client might want to selectively turn off into plugins. And if there’s a piece of functionality you don’t want them turning off, you can put it in the mu-plugins directory, which stands for Must Use and are always activated.

Start Building Your First Child Theme

Here’s my typical workflow for building a child theme:

  1. Create a subdirectory on my site for this project
  2. Install WordPress and Genesis
  3. Build all the site’s functionality into a child theme
  4. Use CSS to make the outputted markup match the provided design
  5. Send it to the client for review

This tutorial is going to focus solely on creating the child theme’s functionality. I am going to use a recent project I worked on for Civic Squared, which is a creative web agency that specializes in designing and maintaining municipal websites in Canada. The project was for the Village of Barnwell. Here is what the provided PSD looks like:

And what we’re starting with:

I’m assuming you’re using Genesis. You can build child themes with any theme, but Genesis is what I use and what this tutorial is written for. We’re also starting with a blank child theme. Once you’ve built a few you’ll see there’s code you use all the time and you’ll probably develop a base child theme to build from. Here’s mine.

Create the Child Theme

Go into /wp-content/themes and create a directory. I’m going to call mine “barnwell”. The only two files you need for your child theme are style.css and functions.php. You could write a completely new stylesheet for your site, but I like to modify the default Genesis one so that I don’t forget anything (taxonomy titles, breadcrumbs…).

Go to /wp-content/themes/genesis/style.css and copy it to /wp-content/themes/barnwell/style.css. Do not use @import in your CSS file to pull the parent theme’s, because when the parent theme makes changes to the stylesheet it will adversely affect your layout.

At the top of the stylesheet, change the information to describe your theme. Make sure you include Template: genesis, as that is what makes this a child theme and not a standard theme. Here’s mine

/*
	Theme Name: Barnwell
	Description: Child theme of Genesis, by StudioPress.
	Author: Bill Erickson
	Author URI: http://www.billerickson.net

	Template: genesis
*/

/* Stylesheet from Genesis 1.7.1 */

This is all we’re going to do with the CSS file, so let’s move to functions.php

There’s a few ways you can structure this file. The important thing is to load Genesis core files before your customizations, because you won’t be able to customize Genesis until it has loaded. If you look at the child themes sold by StudioPress, they all do this by adding the following at the top of functions.php:

/** Start the engine */
require_once( TEMPLATEPATH . '/lib/init.php' );

While this works, I prefer to create a child theme setup function into which I attach my functions to the appropriate actions and filters. I then list my functions below this.

Here’s what I place at the top of my functions.php file:

<?php
/**
 * Functions
 *
 * @package      Barnwell
 * @author       Bill Erickson <bill@billerickson.net>
 * @copyright    Copyright (c) 2011, Bill Erickson
 * @license      http://opensource.org/licenses/gpl-2.0.php GNU Public License
 *
 */

/**
 * Theme Setup
 *
 * This setup function attaches all of the site-wide functions 
 * to the correct actions and filters. All the functions themselves
 * are defined below this setup function.
 *
 */

add_action('genesis_setup','child_theme_setup', 15);
function child_theme_setup() {

}

I also like to create a thumbnail for this theme, to make it easy to identify in the theme listing. Simply make an image thats 300×225, name it screenshot.jpg, and upload it into the /themes/barnwell directory.

Now go to Appearance > Themes and activate your child theme. You’ve now created a child theme!

Customizing the Child Theme

You’ve activated your child theme, but nothing has changed. It’s time to add code to it. I’m not going to cover everything I did on this theme, but I will cover most of the changes on the homepage. Here’s what we’ll do:

Some things not included in this tutorial:

Update Theme Settings

Genesis allows you to control many features of the site from the WordPress backend, without touching any code. We’ll need to make all the changes we can in the backend before we start coding. Go to Genesis > Theme Settings.

First go to Header Settings and select “Image Logo”. This adds a body class of header-image, which is used in the CSS to replace the site title and description with an image. Since we haven’t uploaded a logo yet, it will look like the title and description disappeared.

Then go to Navigation Settings and uncheck “Primary Navigation”. We’ll be building our own special navigation in the next section.

Here’s how the site should look now:

Build the menu

If you look closely at the screenshot on the first page, you’ll notice the header has the logo on the left, then the primary menu, then a secondary menu on the right. I went to Appearance > Menus and created two menus (Primary and Secondary), then populated them with the correct links. I will now create a function that sticks these menus inside the header.

This is functions.php (without all the comments at the top):

add_action('genesis_setup','child_theme_setup', 15);
function child_theme_setup() {

	// Add Nav to Header
	add_action( 'genesis_header', 'be_nav_menus' );

}

/**
 * Add Nav Menus to Header
 *
 */

function be_nav_menus() {
	echo '<div><div>';
	wp_nav_menu( array( 'menu' => 'Primary' ) );
	echo '</div><!-- .primary --><div>';
	wp_nav_menu( array( 'menu' => 'Secondary' ) );
	echo '</div><!-- .secondary --></div><!-- .menus -->';

}

The site should now look like this. We’ll differentiate the menus using CSS (not part of tutorial).

Before we end this section, there’s one more thing I’d like to do. Since we’re using our own menu, not the Genesis ones, I will remove the metabox on the Theme Settings page so the end user doesn’t accidentally turn one of those menus on. Here’s the updated functions.php:

add_action('genesis_setup','child_theme_setup', 15);
function child_theme_setup() {

	// ** Backend **

	// Remove Metaboxes
	add_action( 'genesis_theme_settings_metaboxes', 'be_remove_metaboxes' );

	// ** Frontend **

	// Add Nav to Header
	add_action( 'genesis_header', 'be_nav_menus' );

}

/**
 * Remove Metaboxes
 * This removes unused or unneeded metaboxes from Genesis > Theme Settings. See /genesis/lib/admin/theme-settings.php for all metaboxes.
 *
 */

function be_remove_metaboxes( $_genesis_theme_settings_pagehook ) {
	remove_meta_box( 'genesis-theme-settings-nav', $_genesis_theme_settings_pagehook, 'main' );
}

/**
 * Add Nav Menus to Header
 *
 */

function be_nav_menus() {
	echo '<div><div>';
	wp_nav_menu( array( 'menu' => 'Primary' ) );
	echo '</div><!-- .primary --><div>';
	wp_nav_menu( array( 'menu' => 'Secondary' ) );
	echo '</div><!-- .secondary --></div><!-- .menus -->';

}

Setup the homepage content area

Since the homepage is static, not a listing of posts, the first thing I do is create a page called Home, then go to Settings > Reading and set the homepage to “Home”.

For all the homepage-specific code, I’m putting that in the file front-page.php. So the first thing I’ll do is create front-page.php:

<?php
/**
 * Front Page
 *
 * @package      Barnwell
 * @author       Bill Erickson <bill@billerickson.net>
 * @copyright    Copyright (c) 2011, Bill Erickson
 * @license      http://opensource.org/licenses/gpl-2.0.php GNU Public License
 *
 */

genesis();
?>

Think of this file as a functions.php that only applies to the front page. All our customizations must go before genesis().

Next I’ll force the page layout to be full width, remove the page title, and add the rotator (building this could have been a whole tutorial on its own so I’m leaving it out):

// Force full width
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );

// Remove Page Title
remove_action( 'genesis_post_title', 'genesis_do_post_title' );

// Add Rotator
add_action( 'genesis_after_header', 'be_home_rotator' );

/**
 * Rotator 
 *
 */

function be_home_rotator() {
	do_action( 'home_rotator' );
}

Now I’ll build the content area. First I remove the default loop, genesis_do_loop(), and replace it with my own, be_home_loop(). Inside my loop I have three div’s, #content-left, #content-middle, #content-right. In the left one I’m outputting the page content (the client can edit this from Pages > Home). In the middle I’m displaying the most recent posts. In the right div I’m displaying a sidebar the client can edit (Home Sidebar), then listing the upcoming events and links.

I’m not going to go into more detail on the actual code since this is more of a process tutorial. It is more important that you see how to create a custom home content area than understanding the specifics like my upcoming events query.

Here’s the total front-page.php:

<?php
/**
 * Front Page
 *
 * @package      Barnwell
 * @author       Bill Erickson <bill@billerickson.net>
 * @copyright    Copyright (c) 2011, Bill Erickson
 * @license      http://opensource.org/licenses/gpl-2.0.php GNU Public License
 *
 */

// Force full width
add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' );

// Remove Page Title
remove_action( 'genesis_post_title', 'genesis_do_post_title' );

// Add Rotator
add_action( 'genesis_after_header', 'be_home_rotator' );

/**
 * Rotator 
 *
 */

function be_home_rotator() {
	do_action( 'home_rotator' );
}

// Content Area
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action( 'genesis_loop', 'be_home_loop' );

/**
 * Home Content Area
 *
 */

function be_home_loop() {
	echo '<div>';
		while( have_posts() ): the_post(); 
			the_content();
		endwhile;
	echo '</div><!-- .content-left -->';

	echo '<div>';
		echo '<h3>Latest News</h3>';
		$news = new WP_Query('posts_per_page=3');
		while ($news->have_posts()): $news->the_post(); global $post;
			echo '<div>';
			echo '<div><a href="' . get_permalink() . '">' . get_the_post_thumbnail( $post->ID, 'thumbnail' ) . '</a></div>';
			echo '<div><span>' . get_the_date() . '</span><a href="' . get_permalink() . '">' . get_the_title() . '</a></div><!-- .content -->';
			echo '</div><!-- .news-item -->';
		endwhile; wp_reset_query();
	echo '</div><!-- .content-middle -->';

	echo '<div>';
	dynamic_sidebar( 'home-sidebar' );
	?>

	<div>
		<div>
			<p>Events</p>
			<p>Popular Links</p>
		</div><!-- /entry-header -->
		<div>
				<?php
				$args = array(
					'post_type' => 'event',
					'posts_per_page' => '5',
					'orderby' => 'ASC',
					'order' => 'meta_value_num',
					'meta_query' => array(
						array(
							'key' => 'be_events_manager_end_date',
							'value' => time(),
							'compare' => '>'
						)
					)
				);
				$events = new WP_Query( $args );
				if( $events->have_posts() ):
					echo '<ul>';
					while ( $events->have_posts() ): $events->the_post();
						echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
					endwhile; wp_reset_query();
					echo '</ul>';
				endif;
				?>
			<ul>
				<?php 
				$args = array(
					'limit' => -1,
					'title_li' => '',
					'category' => 2,
					'categorize' => 0
				);
				wp_list_bookmarks( $args ); ?>
			</ul>
			<div> </div>
		</div><!-- /entry-content -->
	</div><!-- /events-links -->
	</div><!-- .content-right -->
	<?php
}

genesis();
?>

And I also had to modify the child_theme_setup() function in functions.php to register the new sidebar.

add_action('genesis_setup','child_theme_setup', 15);
function child_theme_setup() {

	// ** Backend **

	// Remove Metaboxes
	add_action( 'genesis_theme_settings_metaboxes', 'be_remove_metaboxes' );

	// Add Home Sidebar
	genesis_register_sidebar( array( 'name' => 'Home Sidebar', 'id' => 'home-sidebar' ) );

	// ** Frontend **

	// Add Nav to Header
	add_action( 'genesis_header', 'be_nav_menus' );

}

Here’s what the site looks like after adding content to the page “Home”, adding a few events (using this plugin), and adding a widget to the home sidebar.

Finally, the last section of customization. Since the footer is site-wide, we’ll be making these customizations in functions.php. The footer area consists of 3 sections: Search, Footer Widgets and Footer.

To add search, put this at the bottom of functions.php:

/**
 * Add Search to Footer
 *
 */

function be_search() {
	?>
	<div id="searchbar">
		<div>
			<p>Can't find what you're looking for? </p> <?php get_search_form(); ?>
		</div>
	</div>
	<?php
}

Next we’ll add this to the child_theme_setup() function to tell WordPress where to put that search function:

	// Add Search to Footer
	add_action( 'genesis_before_footer', 'be_search', 4 );

That works great, except the search text says “Search this website…” and the button says “Search”. In the design the search text is empty and the button is “Go”. Luckily Genesis provides us filters for these. We’ll use the handy __return_false() function from WordPress on the search text, and create a function of our own for the button.

At the bottom of functions.php place this:

/**
 * Change search button text to Go 
 *
 */

function be_search_button_text( $text ) {
	return esc_attr( 'Go' );
}

And modify the Add Search to Footer section of child_theme_setup() to this:

	// Add Search to Footer
	add_action( 'genesis_before_footer', 'be_search', 4 );
	add_filter( 'genesis_search_text', '__return_false' );
	add_filter( 'genesis_search_button_text', 'be_search_button_text' );

Now let’s add the footer widgets. This is a built-in feature of Genesis, so it only takes one line of code in child_theme_setup():

	add_theme_support( 'genesis-footer-widgets', 6 );

You will now have 6 new widget areas accessible in Appearance > Widgets. I’m going to leave them empty for now so there’s not a bunch of text in the screenshots. If you dig into Genesis core, you’ll see it adds the footer widgets to genesis_before_footer. The default priority is 10 when attaching to an action or filter. To ensure the search shows up before the footer widgets I set the priority of the search to 4 (see the code above).

Finally I’m going to remove the default Genesis footer and replace it with my own. Place this at the bottom of functions.php:

/**
 * Footer
 *
 */

function be_footer() {
	echo '<div><p>© Copyright ' . date('Y') . ' : All Rights Reserved</p></div>';
	echo '<div>';
	wp_nav_menu( array( 'menu' => 'Footer' ) );
	echo '</div>';
}

And this in your child_theme_setup() function:

	// Footer
	remove_action( 'genesis_footer', 'genesis_do_footer' );
	add_action( 'genesis_footer', 'be_footer' );

I’m using a custom menu on the right side of the footer, so go to Appearance > Menus and create a menu called Footer.

So now this is what the site looks like.

It doesn’t look like much, but with a little CSS tweaking you can make it look like this:

And here’s the functions.php file:

<?php
/**
 * Functions
 *
 * @package      Barnwell
 * @author       Bill Erickson <bill@billerickson.net>
 * @copyright    Copyright (c) 2011, Bill Erickson
 * @license      http://opensource.org/licenses/gpl-2.0.php GNU Public License
 *
 */

/**
 * Theme Setup
 *
 * This setup function attaches all of the site-wide functions 
 * to the correct actions and filters. All the functions themselves
 * are defined below this setup function.
 *
 */

add_action('genesis_setup','child_theme_setup', 15);
function child_theme_setup() {

	// ** Backend **

	// Remove Metaboxes
	add_action( 'genesis_theme_settings_metaboxes', 'be_remove_metaboxes' );

	// Add Home Sidebar
	genesis_register_sidebar( array( 'name' => 'Home Sidebar', 'id' => 'home-sidebar' ) );

	// Add Footer Widgets
	add_theme_support( 'genesis-footer-widgets', 6 );

	// ** Frontend **

	// Add Nav to Header
	add_action( 'genesis_header', 'be_nav_menus' );

	// Add Search to Footer
	add_action( 'genesis_before_footer', 'be_search', 4 );
	add_filter( 'genesis_search_text', '__return_false' );
	add_filter( 'genesis_search_button_text', 'be_search_button_text' );

	// Footer
	remove_action( 'genesis_footer', 'genesis_do_footer' );
	add_action( 'genesis_footer', 'be_footer' );
}

/**
 * Remove Metaboxes
 * This removes unused or unneeded metaboxes from Genesis > Theme Settings. See /genesis/lib/admin/theme-settings.php for all metaboxes.
 *
 */

function be_remove_metaboxes( $_genesis_theme_settings_pagehook ) {
	remove_meta_box( 'genesis-theme-settings-nav', $_genesis_theme_settings_pagehook, 'main' );
}

/**
 * Add Nav Menus to Header
 *
 */

function be_nav_menus() {
	echo '<div><div>';
	wp_nav_menu( array( 'menu' => 'Primary' ) );
	echo '</div><!-- .primary --><div>';
	wp_nav_menu( array( 'menu' => 'Secondary' ) );
	echo '</div><!-- .secondary --></div><!-- .menus -->';

}

/**
 * Add Search to Footer
 *
 */

function be_search() {
	?>
	<div id="searchbar">
		<div>
			<p>Can't find what you're looking for? </p> <?php get_search_form(); ?>
		</div>
	</div>
	<?php
}

/**
 * Change search button text to Go 
 *
 */

function be_search_button_text( $text ) {
	return esc_attr( 'Go' );
}

/**
 * Footer
 *
 */

function be_footer() {
	echo '<div><p>© Copyright ' . date('Y') . ' : All Rights Reserved</p></div>';
	echo '<div>';
	wp_nav_menu( array( 'menu' => 'Footer' ) );
	echo '</div>';
}

– See more at: http://www.artofblog.com/building-a-genesis-child-theme/#sthash.1ZDsnNvQ.dpuf

Standard
Genesis, Wordpress

How to Customize the Footer – Genesis Framework

If you are a beginner user, you might find the Simple Edits plugin helpful as it presents an easier method of customizing the footer.

Below is the code to reposition the site footer:

<?php
//* Do NOT include the opening php tag
//* Reposition the footer
remove_action( ‘genesis_footer’, ‘genesis_footer_markup_open’, 5 );
remove_action( ‘genesis_footer’, ‘genesis_do_footer’ );
remove_action( ‘genesis_footer’, ‘genesis_footer_markup_close’, 15 );
add_action( ‘genesis_after’, ‘genesis_footer_markup_open’, 11 );
add_action( ‘genesis_after’, ‘genesis_do_footer’, 12 );
add_action( ‘genesis_after’, ‘genesis_footer_markup_close’, 13 );

Below is the code to customize the Return to Top of Page text on your site:

<?php
//* Do NOT include the opening php tag
//* Customize the return to top of page text
add_filter( ‘genesis_footer_backtotop_text’, ‘sp_footer_backtotop_text’ );
function sp_footer_backtotop_text($backtotop) {
$backtotop = ‘[footer_backtotop text=”Return to Top”]’;
return $backtotop;
}

Below is the code to customize the Credits text on your site:

<?php
//* Do NOT include the opening php tag
//* Customize the credits
add_filter( ‘genesis_footer_creds_text’, ‘sp_footer_creds_text’ );
function sp_footer_creds_text() {
echo ‘<div><p>’;
echo ‘Copyright &copy; ‘;
echo date(‘Y’);
echo ‘ &middot; <a href=”http://mydomain.com”>My Custom Link</a> &middot; Built on the <a href=”http://www.studiopress.com/themes/genesis&#8221; title=”Genesis Framework”>Genesis Framework</a>’;
echo ‘</p></div>’;
}

Alternatively, you can use this:

<?php
//* Do NOT include the opening php tag
//* Change the footer text
add_filter(‘genesis_footer_creds_text’, ‘sp_footer_creds_filter’);
function sp_footer_creds_filter( $creds ) {
$creds = ‘[footer_copyright] &middot; <a href=”http://mydomain.com”>My Custom Link</a> &middot; Built on the <a href=”http://www.studiopress.com/themes/genesis&#8221; title=”Genesis Framework”>Genesis Framework</a>’;
return $creds;
}

Below is the code to customize the entire footer text on your site:

Standard