How to set up Flexible Widgets in any Genesis child theme

Certain Genesis child themes from StudioPress like Essence Pro have the Flexible Widgets feature wherein the widgets placed in widget areas automatically get arranged in different layouts on the frontend depending on the number of widgets in the widget area.

In this article, I share code taken from Essence Pro for flexible layout widgets with a few tweaks that can be used in any Genesis child theme.

Step 1

Add the following in child theme’s functions.php:

/**
 * Counts used widgets in given sidebar.
 *
 * @param string $id The sidebar ID.
 * @return int|void The number of widgets, or nothing.
 */
function flexible_count_widgets( $id ) {

    $sidebars_widgets = wp_get_sidebars_widgets();

    if ( isset( $sidebars_widgets[ $id ] ) ) {
        return count( $sidebars_widgets[ $id ] );
    }

}

/**
 * Gives class name based on widget count.
 *
 * @param string $id The widget ID.
 * @return string The class.
 */
function flexible_widget_area_class( $id ) {

    $count = flexible_count_widgets( $id );

    $class = '';

    if ( 1 === $count ) {
        $class .= ' widget-full';
    } elseif ( 0 === $count % 3 ) {
        $class .= ' widget-thirds';
    } elseif ( 0 === $count % 4 ) {
        $class .= ' widget-fourths';
    } elseif ( 1 === $count % 2 ) {
        $class .= ' widget-halves uneven';
    } else {
        $class .= ' widget-halves';
    }

    return $class;

}

/**
 * Helper function to handle outputting widget markup and classes.
 *
 * @param string $id The id of the widget area.
 */
function flexible_do_widget( $id ) {

    $count   = flexible_count_widgets( $id );
    $columns = flexible_widget_area_class( $id );

    genesis_widget_area(
        $id, array(
            'before' => '<div id="' . $id . '" class="' . $id . '"><div class="flexible-widgets widget-area ' . $columns . '"><div class="wrap">',
            'after'  => '</div></div></div>',
        )
    );

}

Step 2

Add the following in child theme’s style.css:

/* Flexible Widgets
--------------------------------------------- */

.flexible-widgets .widget {
    float: left;
    margin-bottom: 0;
    padding: 40px;
    background-color: #fff;
}

.flexible-widgets .widget table {
    margin-bottom: 0;
}

.flexible-widgets.widget-full .widget,
.flexible-widgets.widget-halves.uneven .widget:last-of-type {
    width: 100%;
}

.flexible-widgets.widget-fourths .widget {
    width: 22%;
    margin-left: 4%;
}

.flexible-widgets.widget-halves .widget {
    width: 48%;
    margin-left: 4%;
}

.flexible-widgets.widget-thirds .widget {
    width: 31%;
    margin-left: 3.5%;
}

.flexible-widgets.widget-halves .widget:nth-of-type(odd),
.flexible-widgets.widget-thirds .widget:nth-child(3n + 1),
.flexible-widgets.widget-fourths .widget:nth-child(4n + 1) {
    clear: left;
    margin-left: 0;
}

.flexible-widgets .featured-content {
    padding: 0;
    background-color: transparent;
    -webkit-box-shadow: none;
            box-shadow: none;
}

.flexible-widgets .featured-content .entry {
    background-color: #fff;
    -webkit-box-shadow: 0 25px 60px 0 rgba(0, 0, 0, 0.05);
            box-shadow: 0 25px 60px 0 rgba(0, 0, 0, 0.05);
    text-align: center;
}

.flexible-widgets .featured-content .entry-title {
    font-size: 26px;
    font-size: 2.6rem;
    text-decoration: none;
    letter-spacing: -1px;
}

.flexible-widgets .featured-content .entry-content,
.flexible-widgets .featured-content .entry-title {
    padding: 15px 40px 0 40px;
}

.flexible-widgets .featuredpost .entry-meta {
    padding-right: 40px;
    padding-left: 40px;
}

.flexible-widgets.widget-full .featuredpost .entry,
.flexible-widgets.widget-halves.uneven .featuredpost.widget:last-of-type .entry {
    float: left;
    width: 31%;
    margin-left: 3.5%;
}

.flexible-widgets.widget-full .featuredpost .entry:nth-of-type(3n + 1),
.flexible-widgets.widget-halves.uneven .featuredpost.widget:last-of-type .entry:nth-of-type(3n + 1) {
    clear: left;
    margin-left: 0;
}

.flexible-widgets .featured-content .more-posts-title {
    padding: 30px 0;
}

.flexible-widgets .featured-content .more-posts {
    text-align: center;
}

.flexible-widgets.widget-full .featured-content .more-posts,
.flexible-widgets.widget-halves.uneven .featured-content:last-of-type .more-posts {
    clear: both;
    -webkit-column-count: 3;
    column-count: 3;
    padding-bottom: 30px;
}

.flexible-widgets .featured-content .more-from-category {
    margin-bottom: 55px;
}

@media only screen and (max-width: 860px) {

    .flexible-widgets .wrap {
        padding-left: 0;
        padding-right: 0;
    }

    .flexible-widgets.widget-fourths .widget,
    .flexible-widgets.widget-halves .widget,
    .flexible-widgets.widget-thirds .widget {
        float: none;
        margin-left: 0;
        width: 100%;
    }

    .flexible-widgets.widget-full .widget .entry,
    .flexible-widgets.widget-halves.uneven .widget:last-of-type .entry {
        margin-left: 0;
        width: 100%;
    }

    .flexible-widgets .entry:last-of-type {
        margin-bottom: 40px;
    }

    .flexible-widgets .featured-content .entry-title,
    .half-width-entries .flexible-widgets .featured-content .entry-title,
    .flexible-widgets.widget-full .entry-title,
    .flexible-widgets.widget-halves.uneven .widget:last-of-type .entry-title {
        font-size: 28px;
        font-size: 2.8rem;
    }

    .flexible-widgets.widget-full .featured-content .more-posts,
    .flexible-widgets.widget-halves.uneven .featured-content:last-of-type .more-posts {
        -webkit-column-count: 1;
        -moz-column-count: 1;
        column-count: 1;
    }

}

Step 3

If you haven’t already, register your widget area(s).

Ex.: In functions.php add

// Registers `before-footer` widget area.
genesis_register_widget_area(
    array(
        'id'          => 'before-footer',
        'name'        => __( 'Before Footer', 'my-theme-text-domain' ),
        'description' => __( 'This is the before footer section.', 'my-theme-text-domain' ),
    )
);

Step 4

Continuing with the above example, here’s how we set up the custom column class to automatically be applied to the Before Footer widget area based on the number of widgets in it AND output the widget area:

add_action( 'genesis_before_footer', 'sk_before_footer', 7 );
/**
 * Adds `before-footer` flexible featured widget area above the footer widgets.
 */
function sk_before_footer() {

    flexible_do_widget( 'before-footer' );

}

The important part is flexible_do_widget( 'before-footer' );.

We just need to pass in the ID of widget area that should be shown with the flexible widets magic.

Step 5

Go to Appearance > Widgets and populate your widget areas that have been made flexible with 1 or more widgets.

This site uses cookies to offer you a better browsing experience. By browsing this website, you agree to our use of cookies.