In this tutorial, I will show you how to create an advanced timeline design with Elementor.
On the right, we have the timeline events, and on the left we have the sticky animation of the years.
The years are populated automatically from the dates of all the events on the page.
On mobile, the years are at the top of the screen. The same animation is preserved.
See the demo here. Use the Mobile icon in the top right to see what it looks like on mobile.
Please note that the demo might be offset by one at the end when viewed here, through an iFrame*. Visit the demo page directly to see it working flawlessly.
Here is a simplified version of the template:
Features:
- Dynamic: The years take care of themselves.
- Flexible design: The events on the right are from a Loop Template, which could be designed any way you wanted. The colors and size of the years animation are customizable.
- Polyvalent: You have events going back to the 19xx ? It still works, in that case you can choose what to do with the circle animation: either make it large enough to have the years within it, or make it smaller and more of a background progress element.
- Mobile ready: Works on mobile too!
- CPT Feed: Stay organized, and make it easy for your client to edit any event.
- Future events: We are not using the "Published" date here, but a custom field for the dates, so we can also have timeline events in the future, or the whole timeline could be a "What's to come?" section.
We are going to be using a Custom Post Type (CPT) and the Elementor Loop Grid element for this.
If you have not worked with CPTs before, I suggest you start by watching this tutorial by Paul. The current tutorial presumes you will know how to create and use a CPT.
*The demo above might be a bit buggy in the iFrame because we are using the IntersectionObserver API here, which works really well, however not so much through an iFrame.
Let's get started!
First, let's create your CPT
This is a premium tutorial. Purchase access to unlock the full tutorial.
13 Responses
Hey, is there a video tutorial of this? I'm unable to achieve this?
Greetings Chethan,
I don't have a video tutorial. If you get stuck, just write to me, ideally with login info to your test website, and I will go in and help you set it up.
Cheers!
Great tutorial. If I want to do it in descending order to show the most recent ones first. What changes should I make?
Hey Felipe!
In the PHP code snippet for the custom query, change this line
$query->set( 'order', 'ASC' );
to this:
$query->set( 'order', 'DESC' );
and in the JavaScript part of the code, change this line:
const uniqueSortedYears = [...new Set(years)].sort((a, b) => a - b);
to this:
const uniqueSortedYears = [...new Set(years)].sort((a, b) => b - a);
Cheers!
Thank you. Yes I had already set that up, but when I set it up like that, when I load the page I get the oldest year highlighted.
Once I do some scrolling it locates the correct year but it ends up getting out of order and overlapping the bottom content of the page.
Ah yes I see what you mean...
To fix the overlapping part, use z-index and background colors on your sections above and below the timeline...
For the rest, I will get you the proper code for this to work in reverse.
Cheers!
I updated my previous comment with the instructions needed.
Cheers!
Great, thank you very much, I have implemented it completely. Now tweak the look and feel a bit and ready!!!!
Hi, Maxime,
You probably remember me, it's Frank.
I gave this a try and it works fine, EXCEPT for the progress circle.
I see the circle (not the progress) in the editor, but when I preview it, the circle is not there.
My CTP is named "pers-artikels", I changed the post type slug in the script, the metafield for is event_date.
I'm using Jetengine, posttype with metafields in the latest Elementor versions.
I checked the console and read this error
persartikels/?preview_id=2787&preview_nonce=8165f49a3a&preview=true:390 Uncaught TypeError: Cannot read properties of null (reading 'getBoundingClientRect')
at persartikels/?preview_id=2787&preview_nonce=8165f49a3a&preview=true:390:50
at NodeList.forEach (<anonymous>)
at HTMLDocument.<anonymous> (persartikels/?preview_id=2787&preview_nonce=8165f49a3a&preview=true:378:20)
Here is the testpage
https://new.toverhuis.be/persartikels
Do you know what's wrong?
PS: I'm not on Facebook anymore.
Greets,
Frank
Hey Frank! Good to hear from you!
I don't see the SVG for the circle progress bar in the heading element, it's not present at all on the front end. That's the issue. Maybe it's a security setting from one of your plugin to sanitize the SVG out of the markup?
If you see the circle in the editor, it means the SVG is present in the heading element, but gets sanitized for some reason on the front end. Try turning off plugins until it show up on the front end to see which plugin is removing it...
Let me know how it goes.
Hi,
Makes sense... I have not many plugins running at the moment.
I have Elementor en Elementor, Jetengine, Happyfiles and Code Snippets.
I can't deactivate Elementor or jetengine otherwise my example won't work anymore.
Enable Unfiltered File Uploads is checked in the Elementor settings.
Much more that I can do beside some extra plugin?
Ok, I fixed it.
I asked ChatGPT to write a script to bypass the sanitization
Here it goes:
// Allow inline SVG in Elementor and WordPress
function allow_inline_svg_in_elementor( $allowed_tags ) {
// Add SVG tag and its common attributes
$allowed_tags['svg'] = array(
'xmlns' => true,
'width' => true,
'height' => true,
'viewBox' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'class' => true,
'id' => true,
);
// Add circle element
$allowed_tags['circle'] = array(
'cx' => true,
'cy' => true,
'r' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'class' => true,
'id' => true,
);
// Add path element
$allowed_tags['path'] = array(
'd' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'class' => true,
'id' => true,
);
return $allowed_tags;
}
add_filter( 'wp_kses_allowed_html', 'allow_inline_svg_in_elementor', 10, 1 );
works fine now
https://new.toverhuis.be/persartikels/
Thanks for sharing Frank it might be useful to others!