{"id":1945153,"date":"2020-01-27T08:25:11","date_gmt":"2020-01-27T13:25:11","guid":{"rendered":"https:\/\/theeventscalendar.com\/knowledgebase\/?post_type=tribe-knowledgebase&#038;p=1945153"},"modified":"2026-04-21T19:53:17","modified_gmt":"2026-04-21T23:53:17","slug":"customizing-photo-view","status":"publish","type":"post","link":"https:\/\/theeventscalendar.com\/knowledgebase\/customizing-photo-view\/","title":{"rendered":"Customizing Photo View"},"content":{"rendered":"\n<p>Photo View is a feature of <a href=\"https:\/\/theeventscalendar.com\/product\/wordpress-events-calendar-pro\/\">Events Calendar Pro<\/a> that displays events as a tiled image grid \u2014 ideal when your events have featured images. This article collects all Photo View customization recipes: the grid layout setting and aspect ratio, changing image sizes, replacing the default placeholder image, CSS and template styling, and an advanced example for converting Photo View into a touch-friendly slider on mobile. <\/p>\n\n\n\n<p>Unless otherwise noted, PHP snippets can be added via your child theme&#8217;s <code>functions.php<\/code> file or using the <a href=\"https:\/\/wordpress.org\/plugins\/code-snippets\/\">Code Snippets plugin<\/a>. Template overrides should always be placed in a child theme. See <a href=\"https:\/\/theeventscalendar.com\/knowledgebase\/k\/best-practices-for-implementing-custom-code-snippets\/\">Best Practices for Implementing Custom Code Snippets<\/a> and <a href=\"https:\/\/theeventscalendar.com\/knowledgebase\/k\/customizing-template-files-2\/\">Customizing Template Files<\/a> for background on both approaches.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-grid-layout-and-aspect-ratio\">Grid Layout and Aspect Ratio<\/h2>\n\n\n\n<p>Events Calendar Pro includes a setting to display Photo View images in a uniform grid with a consistent 16:9 aspect ratio, giving your calendar a cleaner, more organized appearance.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-enabling-the-grid-layout\">Enabling the Grid Layout<\/h4>\n\n\n\n<p>To enable the grid option:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Navigate to <strong>Events \u2192 Settings \u2192 Display<\/strong> in your WordPress dashboard.<\/li>\n\n\n\n<li>Locate the option labeled <strong>&#8220;Display images as a grid on Photo View&#8221;<\/strong>.<\/li>\n\n\n\n<li>Check the option to activate the grid layout.<\/li>\n<\/ol>\n\n\n\n<p>Once enabled, all event images in Photo View will be displayed at a consistent 16:9 aspect ratio.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-changing-the-aspect-ratio\">Changing the Aspect Ratio<\/h4>\n\n\n\n<p>If 16:9 doesn&#8217;t fit your design, you can adjust the aspect ratio using CSS. The <code>padding-top<\/code> percentage controls the ratio: divide the height by the width and multiply by 100.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>16:9 (default): <code>(9 \u00f7 16) \u00d7 100 = 56.25%<\/code><\/li>\n\n\n\n<li>4:3: <code>(3 \u00f7 4) \u00d7 100 = 75%<\/code><\/li>\n\n\n\n<li>1:1 (square): <code>(1 \u00f7 1) \u00d7 100 = 100%<\/code><\/li>\n<\/ul>\n\n\n\n<p>To change to 4:3, add the following to <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong> or your child theme&#8217;s stylesheet:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.tribe-events-view--photo.tribe-events-pro.tribe-events-pro-photo--grid\n.tribe-events-pro-photo__event\n.tribe-events-pro-photo__event-featured-image-link {\n    padding-top: 75%;\n}\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"h-changing-the-image-size\">Changing the Image Size<\/h2>\n\n\n\n<p>By default, Photo View pulls the full-sized image and resizes it to a specific aspect ratio, which can result in inconsistently sized images across the grid. You can override this with a template override that specifies a different WordPress image size.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-create-the-template-override\">Create the Template Override<\/h4>\n\n\n\n<p>Find the event template file in the plugin:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nwp-content\/plugins\/events-calendar-pro\/src\/view\/v2\/photo\/event.php\n<\/pre><\/div>\n\n\n<p>Copy it to your child theme at:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;your-theme]\/tribe\/events-pro\/v2\/photo\/event.php\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-update-the-image-call\">Update the Image Call<\/h4>\n\n\n\n<p>Open the copied file and locate this line around line 28:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php $this-&gt;template( &#039;photo\/event\/featured-image&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n<\/pre><\/div>\n\n\n<p>Replace it with:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php echo tribe_event_featured_image( $event-&gt;ID, &#039;thumbnail&#039; ); ?&gt;\n<\/pre><\/div>\n\n\n<p>Replace <code>'thumbnail'<\/code> with any registered WordPress image size: <code>'medium'<\/code>, <code>'large'<\/code>, or a custom size name. Standard WordPress sizes are defined at <strong>WordPress Settings \u2192 Media<\/strong>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-registering-a-custom-cropped-size\">Registering a Custom Cropped Size<\/h4>\n\n\n\n<p>If you want a custom size that is cropped to exact dimensions, register it in your theme&#8217;s <code>functions.php<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nadd_image_size( &#039;custom-size&#039;, 220, 180, true );\n<\/pre><\/div>\n\n\n<p>The <code>true<\/code> value enables hard cropping. You can then use <code>'custom-size'<\/code> as the size name in the template override above.<\/p>\n\n\n\n<p>\ud83d\udc4b <strong>Note:<\/strong> Images uploaded before the new size was registered will not automatically have that size generated. Use the <a href=\"https:\/\/wordpress.org\/plugins\/wp-retina-2x\/\">Perfect Images<\/a> plugin or a similar regenerate-thumbnails tool to create the new sizes for existing uploads. If you continue to have sizing issues, the <a href=\"https:\/\/wordpress.org\/plugins\/my-eyes-are-up-here\/\">My Eyes Are Up Here<\/a> plugin may also help.<\/p>\n\n\n\n<p>For further reading on template customization, see:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/theeventscalendar.com\/knowledgebase\/k\/customizing-template-files-2\/\">Customizing Template Files<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/theeventscalendar.com\/knowledgebase\/k\/calendar-template-files-v2\/\">Calendar Template Files (V2)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/theeventscalendar.com\/knowledgebase\/k\/template-customization-example\/\">Template Customization Example<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-changing-the-default-placeholder-image\">Changing the Default Placeholder Image<\/h2>\n\n\n\n<p>When an event has no featured image, Photo View displays a built-in placeholder. You can replace that placeholder with your own image using a simple PHP filter.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/theeventscalendar.com\/knowledgebase\/wp-content\/uploads\/2020\/12\/photo-view-default-featured-image-1024x262.jpg\" alt=\"The default placeholder image in Photo View\"\/><\/figure>\n\n\n\n<p>First, upload your desired image to your WordPress media library and copy its URL (use the <strong>Copy URL<\/strong> button in the media library).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/theeventscalendar.com\/knowledgebase\/wp-content\/uploads\/2020\/12\/media-library-image-url-1024x488.jpg\" alt=\"The Copy URL button in the WordPress media library\"\/><\/figure>\n\n\n\n<p>Then add the following snippet to your <code>functions.php<\/code> file, replacing the URL on line 3 with your own:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nadd_filter( &#039;tribe_events_views_v2_view_template_vars&#039;, &#039;tribe_custom_default_featured_image&#039; );\n\nfunction tribe_custom_default_featured_image( $template_vars ) {\n    $template_vars&#x5B;&#039;placeholder_url&#039;] = &#039;https:\/\/your-site.com\/wp-content\/uploads\/your-image.jpg&#039;;\n    return $template_vars;\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/theeventscalendar.com\/knowledgebase\/wp-content\/uploads\/2020\/12\/photo-view-custom-default-featured-image-1024x295.jpg\" alt=\"Photo View using the custom default placeholder image\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-styling-photo-view-with-css-and-templates\">Styling Photo View with CSS and Templates<\/h2>\n\n\n\n<p>Photo View&#8217;s templates and CSS are intentionally structured as a strong starting point that you can build on. The following examples walk through CSS-only changes and a template override for a more structural change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-adjusting-title-font-and-event-spacing\">Adjusting Title Font and Event Spacing<\/h3>\n\n\n\n<p>To increase the event title font size, reduce its weight, and increase the spacing between events, add the following CSS to your child theme&#8217;s stylesheet or <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong>.<\/p>\n\n\n\n<p>Note the use of <code>.tribe-common--breakpoint-medium<\/code>: this class functions like a media query, applied by the plugin when the view container breaks from mobile to desktop size (not based on screen width directly).<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2021\/05\/styling-photo-view-01-desktop.jpg\" alt=\"The default Photo View on desktop, with event title and spacing highlighted\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2021\/05\/styling-photo-view-01-mobile.jpg\" alt=\"The default Photo View on mobile, with event title and spacing highlighted\"\/><\/figure>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.tribe-events-pro .tribe-events-pro-photo__event-title {\n    font-size: 18px;\n    font-weight: normal;\n}\n\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo__event-title {\n    font-size: 20px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__event {\n    margin-bottom: 30px;\n}\n\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo__event {\n    margin-bottom: 60px;\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2021\/05\/styling-photo-view-02-desktop.jpg\" alt=\"Photo View with custom CSS applied on desktop\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2021\/05\/styling-photo-view-02-mobile.jpg\" alt=\"Photo View with custom CSS applied on mobile\"\/><\/figure>\n\n\n\n<p>If you are using the Twenty Nineteen theme (or another theme that applies its own overrides to event styles), the spacing changes above may not display. To counter this, replace the general selectors with theme-specific ones. For Twenty Nineteen:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.tribe-theme-twentynineteen .tribe-events-pro .entry.tribe-common-g-col.tribe-events-pro-photo__event {\n    margin-bottom: 30px;\n}\n\n.tribe-theme-twentynineteen .tribe-events-pro.tribe-common--breakpoint-medium .entry.tribe-common-g-col.tribe-events-pro-photo__event {\n    margin-bottom: 60px;\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"h-moving-the-date-tag-inside-the-photo-card\">Moving the Date Tag Inside the Photo Card<\/h3>\n\n\n\n<p>By default, the date tag appears beside the photo. The following template override moves it on top of the image itself.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2020\/01\/styling-photo-view-03.jpg\" alt=\"Before and after showing the date tag moved from beside the photo to overlaid on the image\"\/><\/figure>\n\n\n\n<p>This requires overriding two template files.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-1-override-event-php\">Step 1: Override event.php<\/h4>\n\n\n\n<p>Copy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/wp-content\/plugins\/events-pro\/src\/views\/v2\/photo\/event.php\n<\/pre><\/div>\n\n\n<p>to:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;your-theme]\/tribe\/events-pro\/v2\/photo\/event.php\n<\/pre><\/div>\n\n\n<p>Remove the line that calls the date-tag template so the file looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php\n$classes = get_post_class( &#x5B; &#039;tribe-common-g-col&#039;, &#039;tribe-events-pro-photo__event&#039; ], $event-&gt;ID );\n\nif ( $event-&gt;featured ) {\n    $classes&#x5B;] = &#039;tribe-events-pro-photo__event--featured&#039;;\n}\n?&gt;\n&amp;lt;article &amp;lt;?php tribe_classes( $classes ) ?&gt;&gt;\n\n    &amp;lt;?php $this-&gt;template( &#039;photo\/event\/featured-image&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n\n    &amp;lt;div class=&quot;tribe-events-pro-photo__event-details-wrapper&quot;&gt;\n        &amp;lt;div class=&quot;tribe-events-pro-photo__event-details&quot;&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/date-time&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/title&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/cost&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n        &amp;lt;\/div&gt;\n    &amp;lt;\/div&gt;\n\n&amp;lt;\/article&gt;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-2-override-featured-image-php\">Step 2: Override featured-image.php<\/h4>\n\n\n\n<p>Copy:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/wp-content\/plugins\/events-pro\/src\/views\/v2\/photo\/event\/featured-image.php\n<\/pre><\/div>\n\n\n<p>to:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;your-theme]\/tribe\/events-pro\/v2\/photo\/event\/featured-image.php\n<\/pre><\/div>\n\n\n<p>Replace the contents with the following, which builds the image with the date tag overlaid inside the link wrapper:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php\nuse Tribe__Date_Utils as Dates;\n\n$image_url = $event-&gt;thumbnail-&gt;exists ? $event-&gt;thumbnail-&gt;full-&gt;url : $placeholder_url;\n\n$display_date = empty( $is_past ) &amp;amp;&amp;amp; ! empty( $request_date )\n    ? max( $event-&gt;dates-&gt;start_display, $request_date )\n    : $event-&gt;dates-&gt;start_display;\n\n$event_month     = $display_date-&gt;format_i18n( &#039;M&#039; );\n$event_day_num   = $display_date-&gt;format_i18n( &#039;j&#039; );\n$event_date_attr = $display_date-&gt;format( Dates::DBDATEFORMAT );\n?&gt;\n&amp;lt;div class=&quot;tribe-events-pro-photo__event-featured-image-wrapper&quot;&gt;\n    &amp;lt;a\n        href=&quot;&amp;lt;?php echo esc_url( $event-&gt;permalink ); ?&gt;&quot;\n        title=&quot;&amp;lt;?php echo esc_attr( get_the_title( $event ) ); ?&gt;&quot;\n        rel=&quot;bookmark&quot;\n        class=&quot;tribe-events-pro-photo__event-featured-image-link&quot;\n    &gt;\n        &amp;lt;img\n            src=&quot;&amp;lt;?php echo esc_url( $image_url ); ?&gt;&quot;\n            &amp;lt;?php if ( ! empty( $event-&gt;thumbnail-&gt;srcset ) ) : ?&gt;\n                srcset=&quot;&amp;lt;?php echo esc_attr( $event-&gt;thumbnail-&gt;srcset ); ?&gt;&quot;\n            &amp;lt;?php endif; ?&gt;\n            &amp;lt;?php if ( ! empty( $event-&gt;thumbnail-&gt;alt ) ) : ?&gt;\n                alt=&quot;&amp;lt;?php echo esc_attr( $event-&gt;thumbnail-&gt;alt ); ?&gt;&quot;\n            &amp;lt;?php endif; ?&gt;\n            &amp;lt;?php if ( ! empty( $event-&gt;thumbnail-&gt;title ) ) : ?&gt;\n                title=&quot;&amp;lt;?php echo esc_attr( $event-&gt;thumbnail-&gt;title ); ?&gt;&quot;\n            &amp;lt;?php endif; ?&gt;\n            class=&quot;tribe-events-pro-photo__event-featured-image&quot;\n        \/&gt;\n        &amp;lt;div class=&quot;tribe-events-pro-photo__event-featured-image-date-tag&quot;&gt;\n            &amp;lt;time\n                class=&quot;tribe-events-pro-photo__event-featured-image-date-tag-datetime&quot;\n                datetime=&quot;&amp;lt;?php echo esc_attr( $event_date_attr ); ?&gt;&quot;\n            &gt;\n                &amp;lt;span class=&quot;tribe-events-pro-photo__event-featured-image-date-tag-month&quot;&gt;\n                    &amp;lt;?php echo esc_html( $event_month ); ?&gt;\n                &amp;lt;\/span&gt;\n                &amp;lt;span class=&quot;tribe-events-pro-photo__event-featured-image-date-tag-daynum tribe-common-h5 tribe-common-h4--min-medium&quot;&gt;\n                    &amp;lt;?php echo esc_html( $event_day_num ); ?&gt;\n                &amp;lt;\/span&gt;\n            &amp;lt;\/time&gt;\n        &amp;lt;\/div&gt;\n    &amp;lt;\/a&gt;\n&amp;lt;\/div&gt;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-3-add-the-css\">Step 3: Add the CSS<\/h4>\n\n\n\n<p>Add the following to your stylesheet or <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong> to position the date tag over the image:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.tribe-events-pro .tribe-events-pro-photo__event-featured-image-link {\n    position: relative;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__event-featured-image-date-tag {\n    position: absolute;\n    bottom: 0;\n    left: 0;\n    background-color: rgba(255, 255, 255, 0.8);\n    padding: 6px 12px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__event-featured-image-date-tag-datetime {\n    display: flex;\n    flex-direction: column;\n    text-align: center;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__event-featured-image-date-tag-month {\n    color: #727272;\n    font-family: &quot;Helvetica Neue&quot;, Helvetica, -apple-system, BlinkMacSystemFont, Roboto, Arial, sans-serif;\n    font-size: 11px;\n    font-weight: 400;\n    line-height: 1.5;\n    text-transform: uppercase;\n}\n<\/pre><\/div>\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/images.theeventscalendar.com\/kb\/uploads\/2021\/05\/styling-photo-view-04.jpg\" alt=\"Photo View with the date tag now overlaid on the bottom-left corner of each event image\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-advanced-mobile-slider\">Advanced: Mobile Slider<\/h2>\n\n\n\n<p>This example converts Photo View into a touch-friendly slider on small screens while preserving the standard grid layout on desktop. It uses the <a href=\"https:\/\/swiperjs.com\/\">Swiper<\/a> slider library and hooks into The Events Calendar&#8217;s built-in JavaScript resize event system, which applies breakpoint classes to the view container rather than relying on CSS media queries.<\/p>\n\n\n\n<p>The slider adapts to device orientation: portrait shows one event at a time with navigation; landscape shows two events per slide.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/theeventscalendar.com\/knowledgebase\/wp-content\/uploads\/2020\/02\/KB-photo-view-slider-landscape.gif\" alt=\"Animated preview of the Photo View slider in landscape orientation on mobile\"\/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-1-override-the-template-files\">Step 1: Override the Template Files<\/h4>\n\n\n\n<p>Copy the following two files from the plugin to your child theme:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/wp-content\/plugins\/events-pro\/src\/views\/v2\/photo.php\n\u2192 &#x5B;your-theme]\/tribe\/events-pro\/v2\/photo.php\n\n\/wp-content\/plugins\/events-pro\/src\/views\/v2\/photo\/event.php\n\u2192 &#x5B;your-theme]\/tribe\/events-pro\/v2\/photo\/event.php\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-2-edit-photo-php\">Step 2: Edit photo.php<\/h4>\n\n\n\n<p>Replace the contents of your <code>photo.php<\/code> override with the following. The key changes are wrapping the events container in Swiper classes (<code>swiper-container<\/code>, <code>swiper-wrapper<\/code>) and adding navigation and pagination elements:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php\n$header_classes = &#x5B; &#039;tribe-events-header&#039; ];\nif ( empty( $disable_event_search ) ) {\n    $header_classes&#x5B;] = &#039;tribe-events-header--has-event-search&#039;;\n}\n?&gt;\n&amp;lt;div\n    &amp;lt;?php tribe_classes( $container_classes ); ?&gt;\n    data-js=&quot;tribe-events-view&quot;\n    data-view-rest-nonce=&quot;&amp;lt;?php echo esc_attr( $rest_nonce ); ?&gt;&quot;\n    data-view-rest-url=&quot;&amp;lt;?php echo esc_url( $rest_url ); ?&gt;&quot;\n    data-view-manage-url=&quot;&amp;lt;?php echo esc_attr( $should_manage_url ); ?&gt;&quot;\n    &amp;lt;?php foreach ( $container_data as $key =&gt; $value ) : ?&gt;\n    data-view-&amp;lt;?php echo esc_attr( $key ) ?&gt;=&quot;&amp;lt;?php echo esc_attr( $value ) ?&gt;&quot;\n    &amp;lt;?php endforeach; ?&gt;\n    &amp;lt;?php if ( ! empty( $breakpoint_pointer ) ) : ?&gt;\n    data-view-breakpoint-pointer=&quot;&amp;lt;?php echo esc_attr( $breakpoint_pointer ); ?&gt;&quot;\n    &amp;lt;?php endif; ?&gt;\n&gt;\n    &amp;lt;div class=&quot;tribe-common-l-container tribe-events-l-container&quot;&gt;\n        &amp;lt;?php $this-&gt;template( &#039;components\/loader&#039;, &#x5B; &#039;text&#039; =&gt; __( &#039;Loading...&#039;, &#039;tribe-events-calendar-pro&#039; ) ] ); ?&gt;\n        &amp;lt;?php $this-&gt;template( &#039;components\/data&#039; ); ?&gt;\n        &amp;lt;?php $this-&gt;template( &#039;components\/before&#039; ); ?&gt;\n\n        &amp;lt;header &amp;lt;?php tribe_classes( $header_classes ); ?&gt;&gt;\n            &amp;lt;?php $this-&gt;template( &#039;components\/messages&#039; ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;components\/breadcrumbs&#039; ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;components\/events-bar&#039; ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/top-bar&#039; ); ?&gt;\n        &amp;lt;\/header&gt;\n\n        &amp;lt;?php $this-&gt;template( &#039;components\/filter-bar&#039; ); ?&gt;\n\n        &amp;lt;div class=&quot;tribe-events-pro-photo swiper-container&quot;&gt;\n            &amp;lt;div class=&quot;tribe-events-pro-photo__events tribe-common-g-row tribe-common-g-row--gutters swiper-wrapper&quot;&gt;\n                &amp;lt;?php foreach ( $events as $event ) : ?&gt;\n                    &amp;lt;?php $this-&gt;setup_postdata( $event ); ?&gt;\n                    &amp;lt;?php $this-&gt;template( &#039;photo\/event&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n                &amp;lt;?php endforeach; ?&gt;\n            &amp;lt;\/div&gt;\n\n            &amp;lt;button class=&quot;swiper-button-prev tribe-common-c-btn-icon tribe-common-c-btn-icon--caret-left&quot;&gt;&amp;lt;\/button&gt;\n            &amp;lt;button class=&quot;swiper-button-next tribe-common-c-btn-icon tribe-common-c-btn-icon--caret-right&quot;&gt;&amp;lt;\/button&gt;\n            &amp;lt;div class=&quot;swiper-pagination&quot;&gt;&amp;lt;\/div&gt;\n        &amp;lt;\/div&gt;\n\n        &amp;lt;?php $this-&gt;template( &#039;photo\/nav&#039; ); ?&gt;\n        &amp;lt;?php $this-&gt;template( &#039;components\/ical-link&#039; ); ?&gt;\n        &amp;lt;?php $this-&gt;template( &#039;components\/after&#039; ); ?&gt;\n    &amp;lt;\/div&gt;\n&amp;lt;\/div&gt;\n\n&amp;lt;?php $this-&gt;template( &#039;components\/breakpoints&#039; ); ?&gt;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-3-edit-event-php\">Step 3: Edit event.php<\/h4>\n\n\n\n<p>Update your <code>event.php<\/code> override to add the <code>swiper-slide<\/code> class to each event article:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&amp;lt;?php\n$classes = get_post_class( &#x5B; &#039;tribe-common-g-col&#039;, &#039;tribe-events-pro-photo__event&#039;, &#039;swiper-slide&#039; ], $event-&gt;ID );\n\nif ( $event-&gt;featured ) {\n    $classes&#x5B;] = &#039;tribe-events-pro-photo__event--featured&#039;;\n}\n?&gt;\n&amp;lt;article &amp;lt;?php tribe_classes( $classes ) ?&gt;&gt;\n\n    &amp;lt;?php $this-&gt;template( &#039;photo\/event\/featured-image&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n\n    &amp;lt;div class=&quot;tribe-events-pro-photo__event-details-wrapper&quot;&gt;\n        &amp;lt;?php $this-&gt;template( &#039;photo\/event\/date-tag&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n        &amp;lt;div class=&quot;tribe-events-pro-photo__event-details&quot;&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/date-time&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/title&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n            &amp;lt;?php $this-&gt;template( &#039;photo\/event\/cost&#039;, &#x5B; &#039;event&#039; =&gt; $event ] ); ?&gt;\n        &amp;lt;\/div&gt;\n    &amp;lt;\/div&gt;\n\n&amp;lt;\/article&gt;\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-4-add-the-css\">Step 4: Add the CSS<\/h4>\n\n\n\n<p>Add the following to your child theme&#8217;s stylesheet or <strong>Appearance \u2192 Customize \u2192 Additional CSS<\/strong>. On mobile the events are displayed as a flat horizontal row for the slider; on desktop they revert to the standard wrapped grid. Navigation and pagination elements are hidden on desktop.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.tribe-events-pro .tribe-events-pro-photo {\n    margin: 0 -21px;\n    overflow: hidden;\n    position: relative;\n}\n\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo {\n    margin: 0;\n    padding: 0;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__events {\n    flex-wrap: nowrap;\n    margin: 0;\n}\n\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo__events {\n    flex-wrap: wrap;\n}\n\n.tribe-events-pro .tribe-events-pro-photo__event {\n    flex: none;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-pagination {\n    display: flex;\n    justify-content: center;\n    padding: 15px 16px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-pagination-bullet {\n    background-color: #bababa;\n    border-radius: 50%;\n    flex: none;\n    height: 10px;\n    margin: 0 6px;\n    width: 10px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-pagination-bullet:hover,\n.tribe-events-pro .tribe-events-pro-photo .swiper-pagination-bullet:focus,\n.tribe-events-pro .tribe-events-pro-photo .swiper-pagination-bullet-active {\n    background-color: #727272;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-button-prev,\n.tribe-events-pro .tribe-events-pro-photo .swiper-button-next {\n    position: absolute;\n    bottom: 10px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-button-prev {\n    left: 21px;\n}\n\n.tribe-events-pro .tribe-events-pro-photo .swiper-button-next {\n    right: 21px;\n}\n\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo .swiper-pagination,\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo .swiper-button-prev,\n.tribe-common--breakpoint-medium.tribe-events-pro .tribe-events-pro-photo .swiper-button-next {\n    display: none;\n    visibility: hidden;\n}\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-5-create-the-javascript-file\">Step 5: Create the JavaScript File<\/h4>\n\n\n\n<p>Create the file at <code>[your-theme]\/assets\/js\/photo-swiper.js<\/code> (adjust the path if you prefer a different location). This script listens for TEC&#8217;s <code>resize.tribeEvents<\/code> event \u2014 which fires after the plugin has processed breakpoint state \u2014 and initializes or destroys the Swiper instance based on whether the container is in mobile view. The <code>isMobile<\/code> state variable is set by TEC&#8217;s breakpoint system before the event fires, making it reliable for this purpose.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nvar photoSwiper = {};\n\n( function( $, obj ) {\n    &#039;use strict&#039;;\n    var $document = $( document );\n\n    obj.selectors = {\n        slider: &#039;.tribe-events-pro-photo.swiper-container&#039;,\n    };\n\n    obj.instances = {};\n\n    obj.deinitSwiper = function( $container ) {\n        var uid = $container.attr( &#039;data-view-breakpoint-pointer&#039; );\n        $container.find( obj.selectors.slider ).each( function( index, slider ) {\n            if ( ! obj.instances&#x5B; uid + &#039;-&#039; + index ] ) {\n                return;\n            }\n            obj.instances&#x5B; uid + &#039;-&#039; + index ].destroy();\n        } );\n    };\n\n    obj.initSwiper = function( $container ) {\n        var uid = $container.attr( &#039;data-view-breakpoint-pointer&#039; );\n        $container.find( obj.selectors.slider ).each( function( index, slider ) {\n            if ( obj.instances&#x5B; uid + &#039;-&#039; + index ] &amp;amp;&amp;amp; obj.instances&#x5B; uid + &#039;-&#039; + index ].initialized ) {\n                return;\n            }\n            obj.instances&#x5B; uid + &#039;-&#039; + index ] = new Swiper( slider, {\n                slidesPerView: &#039;auto&#039;,\n                navigation: {\n                    prevEl: slider.querySelector( &#039;.swiper-button-prev&#039; ),\n                    nextEl: slider.querySelector( &#039;.swiper-button-next&#039; ),\n                },\n                pagination: {\n                    el: &#039;.swiper-pagination&#039;,\n                    type: &#039;bullets&#039;,\n                    bulletElement: &#039;button&#039;,\n                    clickable: true,\n                }\n            } );\n        } );\n    };\n\n    obj.setSwiper = function( $container ) {\n        var containerState = $container.data( &#039;tribeEventsState&#039; );\n        var isMobile = containerState.isMobile;\n\n        if ( isMobile ) {\n            obj.initSwiper( $container );\n        } else {\n            obj.deinitSwiper( $container );\n        }\n    };\n\n    obj.handleResize = function( event ) {\n        obj.setSwiper( event.data.container );\n    };\n\n    obj.bindEvents = function( $container ) {\n        $container.on( &#039;resize.tribeEvents&#039;, { container: $container }, obj.handleResize );\n    };\n\n    obj.deinit = function( event, jqXHR, settings ) {\n        var $container = event.data.container;\n        obj.deinitSwiper( $container );\n        $container.off( &#039;beforeAjaxSuccess.tribeEvents&#039;, obj.deinit );\n    };\n\n    obj.init = function( event, index, $container, data ) {\n        var $sliders = $container.find( obj.selectors.slider );\n\n        if ( ! $sliders.length ) {\n            return;\n        }\n\n        obj.setSwiper( $container );\n        obj.bindEvents( $container );\n        $container.on( &#039;beforeAjaxSuccess.tribeEvents&#039;, { container: $container }, obj.deinit );\n    };\n\n    obj.ready = function( event ) {\n        const manager = tribe.events.views.manager;\n        manager.$containers.each( function( index, container ) {\n            var $container = $( container );\n            obj.init( event, index, $container, manager.getContainerData( $container ) );\n        } );\n        $document.on( &#039;afterSetup.tribeEvents&#039;, manager.selectors.container, obj.init );\n    };\n\n    $document.ready( obj.ready );\n} )( jQuery, photoSwiper );\n<\/pre><\/div>\n\n\n<h4 class=\"wp-block-heading\" id=\"h-step-6-enqueue-the-scripts\">Step 6: Enqueue the Scripts<\/h4>\n\n\n\n<p>Add the following to your child theme&#8217;s <code>functions.php<\/code>. This loads Swiper from a CDN and then loads your custom slider script, declaring Swiper and TEC&#8217;s viewport script as dependencies:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nfunction add_photo_swiper_js() {\n    wp_enqueue_script(\n        &#039;swiper-js&#039;,\n        &#039;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/Swiper\/4.5.1\/js\/swiper.min.js&#039;,\n        &#x5B; &#039;tribe-events-views-v2-viewport&#039; ],\n        false,\n        true\n    );\n    wp_enqueue_script(\n        &#039;custom-photo-swiper-js&#039;,\n        get_stylesheet_directory_uri() . &#039;\/assets\/js\/photo-swiper.js&#039;,\n        &#x5B; &#039;swiper-js&#039; ],\n        false,\n        true\n    );\n}\nadd_action( &#039;wp_enqueue_scripts&#039;, &#039;add_photo_swiper_js&#039; );\n<\/pre><\/div>\n\n\n<p>Visit your Photo View page \u2014 you should see a slider on mobile and the standard grid on desktop.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/theeventscalendar.com\/knowledgebase\/wp-content\/uploads\/2020\/02\/KB-photo-view-slider-portrait.gif\" alt=\"Animated preview of the Photo View slider in portrait orientation on mobile\"\/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Photo View is a feature of Events Calendar Pro that displays events as a tiled image grid \u2014 ideal when your events have featured images. This article collects all Photo View customization recipes: the grid layout setting and aspect ratio, changing image sizes, replacing the default placeholder image, CSS and template styling, and an advanced&#8230;<\/p>\n","protected":false},"author":3,"featured_media":1955565,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_swpsp_post_exclude":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"ep_exclude_from_search":false,"footnotes":""},"categories":[84],"tags":[23,25,58],"stellar-product-taxonomy":[158],"class_list":["post-1945153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-theming-overview","tag-css","tag-customizations","tag-php","stellar-product-taxonomy-events-calendar-pro"],"acf":[],"taxonomy_info":{"category":[{"value":84,"label":"Templating &amp; Layout"}],"post_tag":[{"value":23,"label":"CSS"},{"value":25,"label":"Customizations"},{"value":58,"label":"PHP"}],"stellar-product-taxonomy":[{"value":158,"label":"Events Calendar Pro"}]},"featured_image_src_large":["https:\/\/images.theeventscalendar.com\/kb\/uploads\/2023\/02\/social-share-1024x538.png",1024,538,true],"author_info":{"display_name":"Jaime Marchwinski","author_link":"https:\/\/theeventscalendar.com\/knowledgebase\/author\/jaimetri-be\/"},"comment_info":0,"category_info":[{"term_id":84,"name":"Templating &amp; Layout","slug":"theming-overview","term_group":0,"term_taxonomy_id":84,"taxonomy":"category","description":"","parent":24,"count":22,"filter":"raw","term_order":"0","cat_ID":84,"category_count":22,"category_description":"","cat_name":"Templating &amp; Layout","category_nicename":"theming-overview","category_parent":24}],"tag_info":[{"term_id":23,"name":"CSS","slug":"css","term_group":0,"term_taxonomy_id":23,"taxonomy":"post_tag","description":"","parent":20,"count":11,"filter":"raw","term_order":"0"},{"term_id":25,"name":"Customizations","slug":"customizations","term_group":0,"term_taxonomy_id":25,"taxonomy":"post_tag","description":"","parent":0,"count":33,"filter":"raw","term_order":"0"},{"term_id":58,"name":"PHP","slug":"php","term_group":0,"term_taxonomy_id":58,"taxonomy":"post_tag","description":"","parent":20,"count":23,"filter":"raw","term_order":"0"}],"_links":{"self":[{"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/posts\/1945153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/comments?post=1945153"}],"version-history":[{"count":5,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/posts\/1945153\/revisions"}],"predecessor-version":[{"id":1969850,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/posts\/1945153\/revisions\/1969850"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/media\/1955565"}],"wp:attachment":[{"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/media?parent=1945153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/categories?post=1945153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/tags?post=1945153"},{"taxonomy":"stellar-product-taxonomy","embeddable":true,"href":"https:\/\/theeventscalendar.com\/knowledgebase\/wp-json\/wp\/v2\/stellar-product-taxonomy?post=1945153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}