Full Width Landing Pages in Genesis

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();
view raw front-page.php hosted with ❤ by GitHub

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();
view raw front-page.php hosted with ❤ by GitHub

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();
view raw front-page.php hosted with ❤ by GitHub

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

    • Bill Erickson says

      The only thing I can think of that would cause that is having one too many </div>’s in your first function.

  1. Chris P says

    Bill this seems great but I am a bit confused and am wondering you might have any advice on a project I am working on. I need to accomplish something like you achieved here: https://bloomfire.com where there are full width sections within the main content area and other parts are not full width. It’s driving me nuts trying to figure out how to achieve this. Any help would be greatly appreciated.

    • Bill Erickson says

      That’s exactly what this tutorial guides you through – creating full width content areas. What specific issue are you having?

  2. Sean Vandenberg says

    Bill,

    I wanted to give a genuine THANKS! for your code guides, Bill, especially this one. I’m embarking on my own design journey here, and I wouldn’t be where I’m at without the help of experts like yourself, Chris Coyier @ https://css-tricks.com, and Brad Dalton @ http://wpsites.net. Thanks so much for the help, guys!

    Best,

    Sean

  3. C R says

    Thanks for this- I’ve already used it in several projects. I’m just wondering- in the dashboard of the actual page, would you leave the content box there? Wouldn’t it make sense to use that box for some of the content (text)?
    If I would want to use that box for some of the home page text- how would that be included into this new template? I tried add_action (‘genesis_entry_content’, ‘genesis_do_post_content’); but nothing registers..

    Thanks!

    • Bill Erickson says

      I usually remove the editor from the backend and use a metabox for managing all the section’s content for two reasons:
      1) A single interface (metabox) is easier to use than multiple interfaces (editor + custom metabox)
      2) No one section in the design is obviously “the content”.

      But if your design does have an obvious single content area, then yeah, use the editor in the backend and insert the main page content on the frontend.

      The reason the code you’re trying isn’t working is that you’re using a hook that doesn’t run on this page. We removed the genesis() function, so all the genesis hooks are not running. You’ll want to use the new hook, be_content_area. Also, you’ll probably want to create your own function for it since you’ll need wrapping HTML. Ex: https://gist.github.com/billerickson/6873322915ea8a63015b

  4. David Hedley says

    Great post Bill. If I want to add the page content from the editor into be_content_area would I just use the_content(); or is there a more complete/correct way to call it in Genesis?

      • David Hedley says

        Hi Bill, do you have any thoughts on how best to use this layout on an entire site, whilst keeping any other important markup in such as .article and .entry-content? Would I just use genesis(); and leave all the standard WP markup in then re-size .site-inner in my CSS, or are we still able to filter out any unwanted markup to achieve this in a more cleaner way? Thanks

        • Bill Erickson says

          Why would you need the .article or .entry-content classes? You can add them if you like but they aren’t important. The schema data is what’s important and that has been added back.

          Another approach is to leave all the Genesis markup as-is and treat .site-inner as a single section of the page. You can then hook additional sections in before it (on genesis_after_header) or after it (on genesis_before_footer). For instance, if you were simply adding another full-width section with a contact form before the footer I’d just hook it to genesis_before_footer.

          The above approach should only be used for multi-section pages where all of the sections are of equal importance. That’s why we’re applying the schema attributes from .entry to the entire .site-inner.

  5. David Hedley says

    The only reason I would leave .entry-content is because a lot of my css is relative to .entry-content. This could be changed on a new project but on something existing I was hoping to keep that in place. I thought there may be away to leave .article class=”x” and .entry-content in.

    I do currently use the genesis_after_header hook on some projects but always seem to get validation warnings about the position of section headings so assumed this was not the ‘best practice’ way to do it if all content is equally important.

  6. Richard Buff says

    In your two examples, the be_site_inner_attr function has different contents. Is there a reason for that, or did you perhaps update one of them and forget to update the other?

    • Bill Erickson says

      Fixed it! Yeah, I had updated the first one but forgot to update the second. Previously I was manually specifying the schema. Later I changed this to automatically use whatever schema was supposed to be on .entry. This way if schema requirements change and Genesis is updated, this area also gets the updated schema.

  7. Carl Heyns says

    Hey Bill, thanks for taking the time and writing this article. A noobie like myself can always learn from the pros.

  8. Hans says

    Thanks for the tip. I’ve been looking to make landingspages for my websites, so I need this (or genesis dambuster plugin that seems to do something like this too). After having a clean slate like this, the landingspage or frontpage of course must be constructed.

    The genesis themes I have looked at seem to favour widgetized page templates for that, in stead of pagebuilders or shortcodes like non-genesis themes. Is that your follow up solution too, or just custom coding the page in the text editor using classes?

    It seems to me that using widgets for landingspages beside the frontpage would mean having a lot of widget area’s and a page widgetizer plugin or a specialised template for every landingspage. So a wysiwyg/drag&drop pagebuilder comes to mind as a convinient and flexible solution. I’m thinking perhaps beaver builder or a more specialised plugin like optimizepress that can a/b test and optin too. What is your position on that?

    I will keep reading and learning. Your website is a great source. Thanks for that.

    Cheers, Hans

    • Bill Erickson says

      I think widget areas should only be used for site-wide (or section-wide) content, like a sidebar or footer. Page-specific content should all be on the “Edit Page” screen.

      For the most part I avoid shortcodes. If I do plan to use shortcodes, I use Shortcode UI to improve their usability in the visual editor.

      When I’m building landing pages, I always use a custom metabox so that all the relevant fields are easy to manage. For instance, for this website here is what the backend looks like: https://cl.ly/371o1H112J2G I’ll either use CMB2 or ACF depending on the requirements.

      • Hans says

        Thanks for the tips and pointers, Bill. I like what your saying about widgets and shortcodes and agree with that. On another website I work with a premium theme that uses a lot of shortcodes, and the css isn’t that good, so they let you add “clear: both”-divs and whitespace before headings and so on to get it right. I don’t like that at all. However the result, it means making too large a commitment to that specific theme and gives no wysiwyg experience, even though just like page builders it enables a lot of more advanced display elements like counters and accordeons. Having forms to build the shortcode gives no help when it has to be changed also, and they let you enter the post-id’s for some shortcodes too.

        I very much like your lean and user friendly solution, although it requires some skills to set up (I don’t know yet how to add those tabs-layout and an upload-button for media in the backend f.i.). I have looked at the FrontPage of your website too, and saw how focused and clear it is, with social proof and such. It’s a great way to pre-select your audience, when you know how and have a clear offer. I learn a lot from that kind of examples. 🙂

        On the other hand your metabox-solution seems to be a commitment too, to a specific page-design and structure, and needs coding skills every time the page structure has to change, f.i. when new fields need to be added. So perhaps there is room for a method that uses advanced wysiwyg-editing, like Beaver Builder does or Live Composer. At least if they get it right and are able to build a lean and fast loading result on the frontend of the website. In that way they would enable more flexibility, testing and prototyping without the need of coding skills.

        Beaver builder even seems to do some things within the scope of what you say. At least, as I understand it now, Beaver Builder puts (a copy of) the basic pagecontent in the post itself, so it will stay available when BB is disabled or deleted.

        I don’t know if they use shortcodes without showing them, but after deactivation there are none visible. I’ve read somewhere they use meta and generate minimized css to store the page and present it in a lean way. And one gets some prebuild page templates to get started.

        I will surely use try your method, with many thanks for sharing. I hadn’t seen such a solution yet. And perhaps I will try out Beaver Builder too, and see how that works. Thanks for being generous with your knowledge. Much appreciated.