How to Display WordPress Posts in a dynamic grid layout
Introduction
This article describes creating a dynamic grid layout for WordPress posts using custom post types, CSS Grid, and jQuery for animations. Setting up a responsive design that adapts to different screen sizes, with interactive elements like expandable tabs are detailed out. Read further to learn more.
The Challenge
As part of our work for Acerail, a railway organization in the state of California, we had to create a dynamic expanding accordion with grid items to showcase the stations they serve. This was implemented on a Wordpress website, and the stations' data needed to be updated dynamically. Additionally, we were tasked with enhancing the user experience by implementing specific interactions to make the design more interactive. Below is a screenshot of the Figma design that was provided to us by our designer.
From the outset, we encountered several challenges. The responsive grid had varying numbers of columns on different screen sizes, and the expanding panel needed to move to the next row regardless of the number of items in the grid. Achieving this presented a significant difficulty.
The Architecture
The website is built using the latest version of WordPress. To make our data dynamic and easily accessible via WordPress, the most efficient approach would be to develop a custom post type and associated custom fields.
To display all our posts in a grid layout with each item's content within a div, we will need to find an effective way to loop through the posts and display the content, given that we're using Beaver Builder on our page. Adding custom classes and data attributes to facilitate scripting would be necessary.
To streamline the process, we decided to create a shortcode that would render the grid with all the desired content, making it easily usable anywhere on the site.
After conducting extensive research, we ultimately opted to utilize the CSS grid property. This allowed us to arrange the individual clickable stations within a grid, with the corresponding tab for each station added after the respective element. Using the CSS grid order property, we were able to position the tab after the end of the row.
Initially, the tab will be hidden, and only revealed when a user clicks on the corresponding station. The tab's height will smoothly expand to avoid causing distractions for the user. Once revealed, the tab will become part of the grid. We will need to use jQuery to reorder it after the last element in that row to ensure proper alignment with the current row.
Fetching our Stations
So let’s get into some code. Here’s the shortcode we created to loop through the posts and create our grid.
As you can see there are multiple custom fields for our data. We will pull them in individually and create our structure accordingly.
There is an outer container to which we will attach the grid property. There are anchor links with minimal station data which on click will reveal the container just adjacent to it with the rest of the content. This shortcode [stations] is then inserted into our beaver builder container on the Stations page. Once we have all the data on the page the next step is to style it and create our interactions.
Styling the Grid
Firstly we need to create a grid. The outer container will need values based on our breakpoints to display variable columns on different screen sizes. On smaller screen sizes we shall omit the grid property as all the content will be one below the other.
The grid item has some hover effects and will have an active representation. Let’s add a class to show our active styles.
Secondly the tab will have to be set to full width. Changing the order now would not be possible using css. We shall use jQuery to calculate the order in the next step.
We needed to refine the sliding animation, and after some research, we found a solution that leverages CSS transitions. Firstly, we had to remove the top and bottom padding to set the tab's max-height to 0px initially. Using jQuery, we can add an "expand" class to the tab, which sets its max-height to 1200px. To ensure a smooth transition, we added a duration of 700 milliseconds.
Now grid items are not assigned orders organically. We’ll loop through the links and assign them orders manually so that the tab can order itself perfectly.
So there are a bunch of things that need to happen once the link is clicked. Let’s go through each. Firstly we need to add an active class to the link itself. Before unhiding the tab we need to set its order so it doesn’t break our design. We can then unhide it. We’ve already set its height to 0 so there will be no movement. After a tiny timeout we shall add the “expand” class. With transitions enabled the tab should slide open smoothly.
Now if a tab is open, we will first need to close it and hide it so it doesn’t mess with our grid order. Also we need to wait for this animation to complete before opening our next tab. To speed up the process we can close and open the two tabs simultaneously. That’s what the second condition is for.
There are a few things more to be done. Firstly as you noticed we are changing the hash on opening the accordion. This hash is the post id, which will be unique for each Station. On page load, we can then scroll to the selected element and open the tab. Below is the code to do that.
There’s also a close button on the tab. We shall animate and hide the tab when it is clicked and then also remove the hash from the url.
Lastly, if a tab is open, and the viewport’s dimensions change, the order for our tab will be incorrect. So we write a small script to reorder an open tab on window resize.
Summary
So there it is. To sum up, we have successfully imported our station data from the custom post type and created a responsive grid structure. We also utilized jQuery to animate the tabs. Our responsive grid accordion is now complete. Thank you for reading this far and if you enjoyed this post feel free to follow us for more weekly insights.