
Many of my Events Calendar tutorials come from my work on Kia Miller’s website, which uses Events Calendar Pro. This latest tutorial comes thanks to work I did on the new East Bay WordPress Meetup site. That uses The Events Calendar (free) plus a community license for Event Aggregator. (Thanks, Modern Tribe, for your support of WordPress meetups.)
A Bit about CSS Grid Layout
If you’ve followed me at all, you know I’m a big fan of Flexbox for layouts, and that I’ve used it to create a horizontal event list widget before. Flexbox is ideal for laying out a single row or column of items, which is great if you want a horizontal list display in one row. But it requires a bit of extra tinkering to create a grid where elements have the same height and width even when you don’t have an even number of items in each row.
I started reading about CSS Grid Layout a few months ago and pretty much counted the minutes until browser support went from experimental to real. CSS Grid is designed specifically for laying items out along two axes, on a grid. For laying out multiple rows of items that are the same height and width, or indeed of different but specific heights and widths, Grid is actually easier than Flexbox, despite the somewhat bewildering array of terminology that goes with it.
I don’t want to take up too much of this post on background, but I’ve compiled a list of references for CSS Grid over on the East Bay WP Meetup website so you can learn more about it. Because support is still limited to the most recent browsers, it’s best to use CSS Grid with a fallback. For the specific use case I’m discussing here, the fallback is Flexbox.
Preparing the Theme
I’m using Kickstart Pro, a Genesis child theme, for the East Bay WordPress Meetup website. I chose it for its numerous front page widget areas and overall clean look. (The old EastBayWP.com website used Twenty Fourteen, and though it was possible to feature some items, it really didn’t do a good job with the existing content, and certainly didn’t have a good place to show upcoming meetups once we had Event Aggregator.)
To make The Events Calendar play nicely with Genesis, you need to make some modifications to the plugin’s default-template.php file.
- Create a
/tribe-events/
folder inside of your theme folder. - Download the
default-template.php
file from my ebwp-tribe repo on GitHub and save it your new/tribe-events/
folder. - Upload the
/tribe-events/
folder, including thedefault-template.php
file, to your server. - Choose “Default Event Template” in the display settings of The Events Calendar.
Add Featured Image to List Widget
To display each event’s featured image in your event list widget, you need to add a custom function. You can add it to your functions.php
file, but I’ve started to use the free WP Clips plugin for storing my PHP and CSS customizations, so this function is actually in my custom-functions.php
file within WP Clips on the EastBayWP.com website.
The code comes courtesy of Modern Tribe’s Knowledgebase. All I’ve changed are the name of the function and the image size (post_large
is an image size defined in the Kickstart Pro theme.)
function ebwp_tribe_widget_featured_image() {
global $post;
echo tribe_event_featured_image( $post->ID, 'post_large' );
}
add_action( 'tribe_events_list_widget_before_the_event_title', 'ebwp_tribe_widget_featured_image' );
Once you add this function, you’ll see featured images in your event list widget, but the list will still be a vertical list.
Widget Settings
First, add the Events List widget to the appropriate widget area. In this case, I’ve chosen Home Row 2, a full-width widget area on the home page. (There’s not much point generating a horizontal or grid display of events if you put your event widget in a narrow sidebar.)
The basic list widget for The Events Calendar doesn’t have many settings. The main thing to do here is choose to show a number of events that will fill your grid. I envisioned a three-column grid at the widest size for the content area, which in this case is 970px. The meetup happens once a month.
I could choose to display a whole year’s worth of events at once (assuming I had that many scheduled out), but that would be 4 rows of 3 on a desktop and many more rows on a tablet or phone, which would force site visitors to scroll a long way in order to see any information about past events. I chose 9 events as much to demonstrate the grid layout as anything; I might want to switch to 6. (Six has the advantage of being evenly divisible by both 2 and 3.)
The Magic Is in the CSS
One of the amazing things about CSS Grid Layout is that not only will it automatically populate the grid you define with block-level children of your grid container (the way Flexbox automatically populates your row or column with block-level children of the flex container), you can also tell it to keep generating as many columns as you need to fit the width of that container.
Automatically generating the number of columns (or rows) that you need to fill a container is actually one of the simplest implementations of CSS Grid, and it’s responsive, too. What I’m doing here is telling the browser to create as many 300px columns as will fit into the width of the content area. I’m separating rows and columns with a 10px grid-gap to ensure there’s always white space between them.
This widget area has max-width
defined as 970px in the theme, so I’m never going to have more than 3 columns, but if I set max-width
to 100%, we’d keep getting more columns as the browser expanded. There are no media queries required. As long as your screen is at least 320px wide, you’re golden.
Unless you want every instance of your event list widget to display in a grid, be sure to include the CSS class or ID for your widget area as part of your CSS.
/* For browsers that do support CSS Grid */
.home-row2 .tribe-list-widget {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
grid-gap: 10px;
}
On browsers that support CSS Grid Layout, your list widget now looks like this:
It’s gorgeous and elegant, and only requires 3 lines of code. But as of May 2017 when I’m writing this, very few browsers support CSS Grid.
The Flexbox Fallback
Fortunately, most browsers do support Flexbox. And you can (mostly) duplicate this layout for those browsers by using the following CSS as a fallback.
/* For browsers that don't support CSS Grid */
.home-row2 .tribe-list-widget {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.home-row2 .tribe-list-widget li {
flex: 0 1 300px;
}
.home-row2 .tribe-list-widget li:last-child {
margin-right: auto;
}
.home-row2 .tribe-events-list-widget .tribe-events-list-widget-events {
padding: 10px;
}
That gives you a widget that looks like this (screenshot taken with IE 11):
The result is very similar to what you get using Grid. The key to keeping the items the same size, and appropriately grid-like, is adding margin-right:auto
to li:last-child
. Otherwise, if you don’t fill all the rows, the items in the last row will be much larger than those on the rows above them.
Feature Queries and Fallbacks
So how do we make sure that if the browser supports CSS Grid, it renders the grid CSS? The solution is to add the Flexbox CSS first, then enclose the Grid CSS inside a feature query. Just as media queries allow you to specify different CSS for different screen sizes, feature queries let you choose which CSS to use based on what the user’s browser supports. (And to think there was a time when I didn’t like conditionals.)
A feature query looks like this: @supports (css-property: value) {}
. Because older browsers don’t support feature queries, it’s the code for the modern browser that goes inside the query:
/* For browsers that do support CSS Grid */ @supports ((display: -ms-grid) or (display: grid)) { .home-row2 .tribe-list-widget { display: grid; grid-template-columns: repeat(auto-fill, 300px); grid-gap: 10px; } .home-row2 .tribe-list-widget li { flex: 0; } }
Note that due to the way CSS works, this code has to come after the fallback code, in order to override it. See my full custom-style.css
file on GitHub for details.
And that’s all it takes to use CSS Grid Layout for your Events Calendar event list widget. If you’re not using Genesis, just skip the first part (modifying the default-template.php file).
Not even a big deal in an otherwise awesome post, but I got updates from a Microsoft Edge Program manager a couple months back about how we should be doing @supports for Grid to make sure that when Edge implements it later this year, your site will get the support it wants.
The best feature query is probably going to be like this:
@supports (grid-auto-rows: 1px) { … }
The old specification didn’t have grid-auto-*, so Edge and IE11/10 will ignore this, but future Edge versions will support it and see the code. I went back and updated an older post I wrote on the subject here if you want to see a new implementation: https://bryanlrobinson.com/blog/2017/01/18/your-code-should-fall-forward/
You’re right: I’ve since seen that it’s good to be more specific with those queries so as not to end up with unexpected results in Microsoft browsers.