Creating a timeline in Genesis could not be easier using ACF Pro. I am currently looking at my website and what plugins I have loaded it with. It is time for a clean up, so I am looking at every plugin I have installed. I thought I would take it as a challenge to replace those plugins with a simpler way to handle my requirements.
I am using Timeline Express to show the different plugins and frameworks I use on the website throughout its life. So I want to replace this plugin. While doing my research, I found an article that handles just that (you can check it out down at sources section). So I just incorporated it into Genesis with the help of ACF Pro’s repeater field.
View the demo, if you would like to see it in action. It’s interactive, so it’s worth checking the demo out.
let us start
Please note that this was done on the Genesis Sample theme.
1. Create a new page and let us call it Timeline
2. Create a new file in your child theme and let’s call it page-timeline.php. Add the following code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<?php /** * This file adds a timeline to your desired page in Genesis Framework. * * @author Omar Al-Ansari * @link http://www.alansari.io */ // Force full width content add_filter( 'genesis_pre_get_option_site_layout', '__genesis_return_full_width_content' ); add_action( 'genesis_entry_content', 'io_about_me_timeline' ); /** * Outputs a timeline using custom fields */ function io_about_me_timeline() { if ( is_singular( $post_types = 'page' ) && is_page( $page = 'timeline' ) ) { // check if the repeater field has rows of data if( have_rows('timeline_items') ): echo '<div class="timeline"><ul>'; // loop through the rows of data while ( have_rows('timeline_items') ) : the_row(); $timelineDate = get_sub_field('timeline_date'); $timelineContent = get_sub_field('timeline_content'); printf('<li><div><h3>%s</h3> %s</div></li>', $timelineDate, $timelineContent); endwhile; echo '</ul></div>'; else : // no rows found endif; } } // Enqueue timeline-init.js add_action( 'wp_enqueue_scripts', 'io_enqueue_timeline_scripts' ); function io_enqueue_timeline_scripts() { wp_enqueue_script( 'timeline-init', get_stylesheet_directory_uri() . '/js/timeline-init.js', array( 'jquery' ), '', true ); } genesis(); |
3. Create a new file and add the following code in it. Please ensure that you add the file under /js subfolder. If not available then create it under your child theme folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// https://webdesign.tutsplus.com/tutorials/building-a-vertical-timeline-with-css-and-a-touch-of-javascript--cms-26528 function isElementInViewport(el) { var rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } var items = document.querySelectorAll(".timeline li"); // code for the isElementInViewport function function callbackFunc() { for (var i = 0; i < items.length; i++) { if (isElementInViewport(items[i])) { items[i].classList.add("in-view"); } } } window.addEventListener("load", callbackFunc); window.addEventListener("scroll", callbackFunc); |
4. Add the following code to your Style.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
/* # Timeline ---------------------------------------------------------------------------------------------------- */ .timeline ul li { list-style-type: none; position: relative; width: 6px; margin: 0 auto; padding-top: 50px; background: #ddd; } .timeline ul li::after { content: ''; position: absolute; left: 50%; bottom: 6px; transform: translateX(-50%); width: 30px; height: 30px; border: 2px solid #fff; border-radius: 50%; background: inherit; } .timeline ul li div { position: relative; bottom: 0; width: 400px; padding: 15px; background: #88b7d5; border-radius:4px; } .timeline ul li div::before { content: ''; position: absolute; bottom: 7px; width: 0; height: 0; border-style: solid; } .timeline ul li:nth-child(odd) div { left: 45px; } .timeline ul li:nth-child(odd) div::before { left: -15px; border-width: 15px 20px 15px 0; border-color: transparent #88b7d5 transparent transparent; } .timeline ul li:nth-child(3n+1):nth-child(odd) div { background: #3591d1; } .timeline ul li:nth-child(3n+1):nth-child(odd) div::before { border-color: transparent #3591d1 transparent transparent; } .timeline ul li.in-view:nth-child(3n+1):nth-child(odd)::after { background: #3591d1; } .timeline ul li:nth-child(even) div { left: -439px; } .timeline ul li:nth-child(even) div::before { right: -15px; border-width: 15px 0 15px 20px; border-color: transparent transparent transparent #88b7d5; } .timeline ul li:nth-child(3n+1):nth-child(even) div { background: #35dc69; } .timeline ul li:nth-child(3n+1):nth-child(even) div::before { border-color: transparent transparent transparent #35dc69; } .timeline ul li.in-view:nth-child(3n+1):nth-child(even)::after { background: #35dc69; } .timeline ul li::after { background: #ddd; transition: background .5s ease-in-out; } .timeline ul li.in-view::after { background: #88b7d5; } .timeline ul li div { visibility: hidden; opacity: 0; transition: all .5s ease-in-out; } .timeline ul li:nth-child(odd) div { transform: translate3d(200px,0,0); } .timeline ul li:nth-child(even) div { transform: translate3d(-200px,0,0); } .timeline ul li.in-view div { transform: none; visibility: visible; opacity: 1; } @media screen and (max-width: 1024px) { .timeline ul li div { width: 250px; } .timeline ul li:nth-child(even) div { left: -289px; /*250+45-6*/ } } @media screen and (max-width: 860px) { .timeline ul li { margin-left: 20px; } .timeline ul li div { width: calc(100vw - 350px); } .timeline ul li:nth-child(even) div { left: 45px; } .timeline ul li:nth-child(even) div::before { left: -15px; border-width: 15px 20px 15px 0; border-color: transparent #88b7d5 transparent transparent; } } @media screen and (max-width: 780px) { .timeline ul li div { width: calc(100vw - 250px); } } |
5. Create the custom fields using ACF Pro.
Ensure that you link the custom field to the timeline page as shown above in the Location section of ACF.
6. Finally, edit the page you created in step 1 and start adding your timeline items
Apologies for the large images. I just wanted to get you to see what I exactly have for ACF.
I hope that you do find this helpful. If you do, then I would appreciate it if you could share it :).
Thanks for sharing the tutorial, that definitely will come in handy!
Hi William,
Thanks for the note. I am working in another one that will have a nicer UI (in my opinion). I’ll share that too, shortly.