Many of the websites in my portfolio use a full width approach for their homepages and landing pages. See my article on building landing pages with ACF for more information on how we build them.
On pages like this, Genesis outputs a lot of markup you don’t need. It includes divs for .site-inner .wrap, .content-sidebar-wrap, .content, .entry ….
We could remove the styling from those elements so they don’t take up any space and then stick all the site content before or after it, but there’s a better way.
Don’t use the genesis() function.
What’s the first step in creating a theme file in Genesis? You create a file that looks something like this:
| <?php | |
| /** | |
| * EA Genesis Child. | |
| * | |
| * @package EAGenesisChild | |
| * @since 1.0.0 | |
| * @copyright Copyright (c) 2014, Contributors to EA Genesis Child project | |
| * @license GPL-2.0+ | |
| */ | |
| genesis(); |
But what does that genesis() function actually do? If you look in /genesis/lib/framework.php, you’ll see this. To summarize, it calls get_header(), then builds the main content area, then calls get_footer().
On pages like those described above, I only want the header and footer and then I’ll take care of the main content area. So, I start with a template file that looks like this:
| <?php | |
| /** | |
| * EA Genesis Child. | |
| * | |
| * @package EAGenesisChild | |
| * @since 1.0.0 | |
| * @copyright Copyright (c) 2014, Contributors to EA Genesis Child project | |
| * @license GPL-2.0+ | |
| */ | |
| // Remove 'site-inner' from structural wrap | |
| add_theme_support( 'genesis-structural-wraps', array( 'header', 'footer-widgets', 'footer' ) ); | |
| /** | |
| * Add the attributes from 'entry', since this replaces the main entry | |
| * | |
| * @author Bill Erickson | |
| * @link http://www.billerickson.net/full-width-landing-pages-in-genesis/ | |
| * | |
| * @param array $attributes Existing attributes. | |
| * @return array Amended attributes. | |
| */ | |
| function be_site_inner_attr( $attributes ) { | |
| // Add a class of 'full' for styling this .site-inner differently | |
| $attributes['class'] .= ' full'; | |
| // Add an id of 'genesis-content' for accessible skip links | |
| $attributes['id'] = 'genesis-content'; | |
| // Add the attributes from .entry, since this replaces the main entry | |
| $attributes = wp_parse_args( $attributes, genesis_attributes_entry( array() ) ); | |
| return $attributes; | |
| } | |
| add_filter( 'genesis_attr_site-inner', 'be_site_inner_attr' ); | |
| // Build the page | |
| get_header(); | |
| do_action( 'be_content_area' ); | |
| get_footer(); |
I’m removing ‘site-inner’ from the structural wrap because my content will go inside .site-inner and those elements will have their own internal .wrap‘s.
You only have to do this if you’ve defined the structural wraps you want in your theme already and included ‘site-inner’. If you don’t have add_theme_support( 'structural-wraps' ); in your child theme, Genesis will add wraps to everything except .site-inner (see /genesis/lib/init.php, line 63). So you can leave this part out, but you’ll probably want to adjust the styling of .site-inner in your stylesheet.
In the Genesis Sample Theme, they exclude the structural wrap for .site-inner but apply a max-width to .site-inner (see here). You’ll want this to be 100% wide on your page template, so update your styles accordingly.
Since we’re removing the <content> element which has Schema attributes, we’ll want to add those attributes to .site-inner (thanks to Sridhar Katakam for the recommendation).
I also place do_action( 'be_content_area' ); between the header and footer lines. While you could put your template file code directly between these two functions, all my other theme files are using hooks to place functionality in the theme so I’m using it here to be consistent.
Then I build the page. All my functions are hooked to ‘be_content_area’ and go above the “build the page” area, just like you’d put everything above the genesis() function in other templates.
Here’s what it looks like once I add the rotator from WebAssign’s homepage:
| <?php | |
| /** | |
| * EA Genesis Child. | |
| * | |
| * @package EAGenesisChild | |
| * @since 1.0.0 | |
| * @copyright Copyright (c) 2014, Contributors to EA Genesis Child project | |
| * @license GPL-2.0+ | |
| */ | |
| /** | |
| * Home Rotator | |
| * | |
| */ | |
| function be_home_rotator() { | |
| $slides = get_post_meta( get_the_ID(), 'be_slide', true ); | |
| if( $slides ) { | |
| echo '<div class="home-rotator"><div class="wrap"><div class="flexslider"><ul class="slides">'; | |
| for( $i = 0; $i < $slides; $i++ ) { | |
| $image = wp_get_attachment_image( get_post_meta( get_the_ID(), 'be_slide_' . $i . '_image', true ), 'be_slide' ); | |
| $title = esc_attr( get_post_meta( get_the_ID(), 'be_slide_' . $i . '_title', true ) ); | |
| $button_link = esc_url( get_post_meta( get_the_ID(), 'be_slide_' . $i . '_button_link', true ) ); | |
| if( $title ) { | |
| if( $button_link ) | |
| $title = '<a href="' . $button_link . '">' . $title . '</a>'; | |
| $title = '<h2>' . $title . '</h2>'; | |
| } | |
| $content = get_post_meta( get_the_ID(), 'be_slide_' . $i . '_content', true ); | |
| $button_text = esc_attr( get_post_meta( get_the_ID(), 'be_slide_' . $i . '_button_text', true ) ); | |
| $button = $button_text && $button_link ? '<p><a href="' . $button_link . '" class="button">' . $button_text . '</a></p>' : ''; | |
| $bg = get_post_meta( get_the_ID(), 'be_slide_' . $i . '_bg', true ); | |
| $class = $bg ? 'slide-caption white-bg' : 'slide-caption'; | |
| echo '<li>' . $image . '<span class="caption-wrapper"><span class="' . $class . '">' . $title . wpautop( $content ) . $button . '</span></span></li>'; | |
| } | |
| echo '</ul></div></div></div>'; | |
| } | |
| } | |
| add_action( 'be_content_area', 'be_home_rotator' ); | |
| // Remove 'site-inner' from structural wrap | |
| add_theme_support( 'genesis-structural-wraps', array( 'header', 'footer-widgets', 'footer' ) ); | |
| /** | |
| * Add attributes for site-inner element, since we're removing 'content'. | |
| * | |
| * @param array $attributes Existing attributes. | |
| * @return array Amended attributes. | |
| */ | |
| function be_site_inner_attr( $attributes ) { | |
| // Add a class of 'full' for styling this .site-inner differently | |
| $attributes['class'] .= ' full'; | |
| // Add the attributes from .entry, since this replaces the main entry | |
| $attributes = wp_parse_args( $attributes, genesis_attributes_entry( array() ) ); | |
| return $attributes; | |
| } | |
| add_filter( 'genesis_attr_site-inner', 'be_site_inner_attr' ); | |
| // Build the page | |
| get_header(); | |
| do_action( 'be_content_area' ); | |
| get_footer(); |
SagePress says
Awesome & we love the look of the full width landing page. Thank you for sharing this Bill!
Steve Struemph says
Thank you for posting this, Bill! It’s perfect timing and will help me with a project I’m starting,
Steve Struemph says
This snippet is missing a comma after “footer-widgets”
add_theme_support( ‘genesis-structural-wraps’, array( ‘header’, ‘footer-widgets’ ‘footer’ ) );
Bill Erickson says
Updated. Thanks for catching that
Tony says
Hey Bill,
Thanks for writing about this…great way do this!
Just a heads up, the comma is fixed in the first set of code, but missing from the full snippet on line 43.
Bill Erickson says
Fixed that one too!
Wendy says
Great tutorial and great way to clean up the code. Makes completely sense to remove all that mark up. I have made a few full width landing pages but never thought to do it like this.
James Maabadi says
Those example sites are beautiful! Very nice work!
Grégoire Noyelle says
Thanks a lot Bill.
Why I never use this way before. You’re right, for a custom home page, without widget, that’s the best way, very clean.
Bashia Galt says
Thank you for sharing this Bill!
I am so glad I came across your blog. Very helpful! Its not easy to find a WordPress pro.
Well done.
Richard Senior says
That’s a great approach Bill,
I never thought about not using the genesis() function in a Genesis page template before now… Food for thought!
Thank you.
Steve Struemph says
Hi Bill,
I am working with full width images in Genesis where the image needs to load as either the featured image for the page/post or as a custom field. I think I have that part worked out but the image also needs to have text over it and be responsive where it doesn’t resize when it goes down to mobile but rather the sides need to crop. Not doing parallax on these either. I found a solution here (http://www.minimit.com/articles/solutions-tutorials/fullscreen-backgrounds-with-centered-content) that uses Javascript to get the image width and height and it centers the text. But it seems like a lot of hoops to jump through and I’m wondering if there’s a more elegant solution. On the Bloom Fire website (http://bloomfire.com/) you did what I am trying to do with the full width image at the bottom. I’m curious what your approach was for that.
Bill Erickson says
Set the image as the background. Something like this: https://gist.github.com/billerickson/cd1c47d1e26a0c494626
Patrick Sarmiento says
Hi Bill,
I would like to ask about how the contents are placed? They are HTML + Content inside WordPress editor?
Currently I am a fan of Visual Editor but my problem is the boxed layout of Genesis, and I want a full-width container.
Regards,
Patrick
Bill Erickson says
In the backend I’m using WYSIWYGs for entering the content, so clients can use the Visual Editor.
Patrick Sarmiento says
How about the WordPress loop, where do you add it?
Todd says
Hey Bill
This is great! Are you using some kind of A/B testing for the landing pages or are the clients using something? I always thought that one could use a Genesis theme for a landing page fairly easily, it’s just the A/B testing I was unsure about.
Thanks
Todd
Bill Erickson says
I believe they are doing AB Testing but am not aware of their current setup. I’m starting a project next month that will be using this for AB Testing.