Page Speed – HiDonny.com https://hidonny.com Page Speed Optimization Specialist Sun, 20 Mar 2022 11:27:48 +0000 en-US hourly 1 https://wordpress.org/?v=6.7.1 https://hidonny.com/wp-content/uploads/2022/03/cropped-logo-icon.fw_-32x32.png Page Speed – HiDonny.com https://hidonny.com 32 32 How To Replace WooCommerce Product Gallery with Flickity Slider https://hidonny.com/2022/03/replace-woocommerce-gallery-with-flickity-slider/ Sun, 20 Mar 2022 11:27:43 +0000 https://en.hidonny.com/?p=1146 Default WooCommerce product gallery raises the Cumulative Layout Shift problem. Although we can solve it by adding maximum height to the gallery element area, replacing it with a non-jQuery slider is better in many situations, like flickity slider.

Let’s say you have another fancy element below the critical area that requires jQuery. When we can actually defer it until we need it to show up, we have to load so many assets because your main slider, which is placed on the critical area, also depends on jQuery.

What is the Performance Benefit from Using Flickity Slider as an Image Gallery Slider?

  1. Reduce total blocking time.
    By using flickity, we can defer javascript files which are needed later.
  2. Lazy load images.
    If you have like 10 images in your slider, you can tell the browser to show only the first one and load the other when user slide it. This way, we can save resource and reduce the blocking time caused by loading images.
  3. Improve time to interactive.
    By loading the flickity javascript files for your slider separately without waiting the whole javascript files on the page, the slider will be more responsive to human interaction. The image slider will be ready to be used even before the whole page finished loading. It’s good for user experience.

Steps to Replace WooCommerce Default Image Galler to Flickity Image Slider.

In the first step, we have to remove the WooCommerce default image gallery using this snippet:

remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 ); //Remove Single Product Image'

Now, in the second step, we create a function to remove the featured image displayed by GeneratePress. You can check the theme documentation or maybe contact the theme developer if you are using other themes.

add_action( 'wp', 'generate_remove_single_featured_image' );
function generate_remove_single_featured_image()
{
    if ( is_product() ) :
        remove_action('generate_before_content','generate_featured_page_header_inside_single', 10);
    endif;
}

In the third step, we enqueue the javascript and CSS files. I downloaded flickity.js and flickity.css and upload them to a subfolder in my WordPress subdirectory.

add_action( 'wp_enqueue_scripts', 'diko_enqueue_scripts' );
function diko_enqueue_scripts() : void {
    // Enqueue my styles.
    wp_enqueue_style( 'flickity-style', 'https://tweaked.gp.indowebstudio.com/diko/fl.css' );
     
    // Enqueue my scripts.
    wp_enqueue_script( 'flickity-script', 'https://tweaked.gp.indowebstudio.com/diko/fl.js', array(), null, true );
}

After that, the fourth step will be creating the structure for our flickity based slider.

function flickity_structure(){
	global $product;
	$attachment_ids = $product->get_gallery_attachment_ids();
	$featured_image = wp_get_attachment_image( get_post_thumbnail_id( $post->ID ), 'medium',"", array( "class" => "skip-lazy attachment-medium size-medium","loading" => "") );
	$featured_image_thumb = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'medium',"", array( "class" => "skip-lazy attachment-medium size-medium", "loading" => "") );	
	echo '<div class="slider-container">';
	echo '<div class="main-carousel" style="width:100%">';
	echo '<div class="carousel-cell">' . $featured_image . '</div>';
	foreach( $attachment_ids as $attachment_id ){
  		//Get URL of Gallery Images - default wordpress image sizes
		echo '<div class="carousel-cell">' . str_replace('src', 'data-flickity-lazyload-src', wp_get_attachment_image($attachment_id, 'medium')) . '</div>';
	}
echo '</div>';	
echo '<div class="carousel-nav">';
echo '<div class="carousel-cell" style="width:22%; display:inline-block"><img class="" src="' . $featured_image_thumb[0] . '" /></div>';	
foreach( $attachment_ids as $attachment_id ){
  //Get URL of Gallery Images - default wordpress image sizes
	echo '<div class="carousel-cell" style="width:22%; display:inline-block"><img class="" src="' . wp_get_attachment_image_src( $attachment_id, 'medium' )[0] . '" /></div>';
}
echo '</div>';
echo '</div>';
}

The structure has been built, now it’s the time to call it. We hook it into the place where we remove the WooCommerce default image gallery.

add_action('woocommerce_before_single_product_summary','flickity_structure',25);

The next step will be to give our slider an inlined CSS style. We put it inlined because the flickity slider is positioned in the critical, above the fold area. Anything placed in the “above the fold area”, should have its CSS style inlined, period.

add_action('wp_head','flickity_inline_css',11);
function flickity_inline_css(){
	?>
<style data-noptimize="1">
.main-carousel{
    white-space:nowrap;
    position:relative;
    overflow:hidden;
	height:calc(100vw - 60px);
	margin-bottom:30px;
}
.main-carousel .carousel-cell {
    display:inline-block;
    width:100%;
    vertical-align:top;
}
.main-carousel .carousel-cell img{
    width:100%;
    object-fit: contain;
    height:calc(100vw - 60px);
}	
	
	@media (min-width:469px){
		.main-carousel{
			height:300px;
		}
		.main-carousel .carousel-cell img{
    		height:300px;
		}		
	}
	@media (min-width:769px){
		.slider-container{
			width:48%;
			float:left;	
			position:relative;
		}
	}
.carousel-nav{
    height:75px;
}
.carousel-nav .carousel-cell{
	height:75px;
}

.carousel-nav .carousel-cell img{
    height:75px;
    width:100%;
    object-fit:contain;
    object-position:center center;
}	
</style>
	<?php
}

The last step will be to initiate the slider using javascript which we put at the bottom of the page.

//Initiate Flickity JS on footer
add_action('wp_footer','flickity_inline_js',20000);
function flickity_inline_js(){
	?>
<script data-noptimize="1">
	var elem = document.querySelector('.main-carousel');
	var flkty = new Flickity( elem, {
  		// options
  		cellAlign: 'center',
  		contain: true,
		lazyLoad: true,
		adaptiveHeight: true,
		pageDots: false,
		prevNextButtons: false,
	});
	var elem_nav = document.querySelector('.carousel-nav');
	var flkty_nav = new Flickity( elem_nav, {
  		// options
  		cellAlign: 'center',
  		contain: true,
		lazyLoad: false,
		pageDots: false,
		asNavFor: '.main-carousel',
		prevNextButtons: false,
	});	
</script>
	<?php
}

Any time any day, you can check it using the page speed insights tool, it passes all the Core Web Vital metrics and always score above 95. You can also check it using this link https://pagespeed.web.dev/report?url=https%3A%2F%2Ftweaked.gp.indowebstudio.com%2Fproduct%2Fillum-eos-saepe-et-at-dignissimos%2F

WooCommerce with Flickity slider performance test.
PSI Score
WooCommerce with Flickity slider performance test.
Core Web Vitals Metrics

That’s it for today, if you have any questions, feel free to use the Disqus comment form below. This post is an alternative way to improve page speed performance on the WooCommerce product page. Previously, I had made a tutorial, a simpler one by just adding a height to the gallery, you can read it at this link How to Fix CLS Issue on WooCommerce Product Page.

]]>
How to Fix CLS Issue on WooCommerce Product Page https://hidonny.com/2022/03/how-to-fix-cls-issue-on-woocommerce-page/ Tue, 08 Mar 2022 17:40:23 +0000 https://hidonny.com/?p=534 Continuing from my previous post, I’m going to show you an alternative way to fix the CLS issue on the WooCommerce product page with an image gallery. Cumulative Layout Shift or CLS is an essential metric of the Core Web Vitals. It’s so important to fix this problem. Not just to get a better score on Google Page Speed Insight but also to give our visitors a better user experience.

Let’s know a bit about CLS first.

Cumulative Layout Shift, abbreviated CLS, is one of the most essential Core Web Vitals metrics to measure visual stability. If the critical area on a web page is not properly styled, visitors will get unexpected layout changes which sometimes lead to frustration and eventually leave your website.

Check this video below. Watch it from 00:11 until 00:15; the product title position moves from the middle of the screen to the bottom of the image gallery. This is called layout shift. If many elements are moving like this, their accumulated shifting time is called Cumulative Layout Shift.

YouTube Video

Alright, that’s what happens on the dummy site, which is built using GeneratePress and WooCommerce. Below, you can find the score on mobile view and its Core Web Vitals metrics value.

PSI Score
CWV Metrics

Scroll down a little more to the bottom, and we’ll see the element that contributes the most to the layout shift.

That’s right, the content below the image gallery is the element that shifts position a lot while the page is loading.

How to Fix CLS Issue : Modify Image Gallery Height

Now we understand that the image gallery is the problem, so we need to replace it with another image gallery or slider or carousel script, you name it. I had made another dummy site located at https://tweaked.gp.indowebstudio.com, and I used flickity slider to build the image gallery on that site.

However, in this post, I will share something simple to fix that CLS issue. Just use a fixed height styling for the image gallery, that’s all. But it would be best if you also placed a good strategy on formatting your image’s dimension. Make sure it fits the image gallery container so it doesn’t look shrunk or stretched.

Below is the CSS code that will fix the cls issue on the WooCommerce page. Just add it to the header of the page using your favorite tool. Make sure that you put it inline on the page, not inside any file like style.css.

	.woocommerce-product-gallery__image{
		height:300px !important;
	}
	.woocommerce div.product div.images a img	{
		height:300px !important;
		object-fit:contain;
		object-position:center center;
	}

Or, if you prefer to get your hand a little dirty, you can use this PHP snippet.

add_action('wp_head','diko_gallery_fixed_height');
function diko_gallery_fixed_height(){
	if(is_product()){
	?>
<style>
	.woocommerce-product-gallery__image{
		height:300px !important;
	}
	.woocommerce div.product div.images a img	{
		height:300px !important;
		object-fit:contain;
		object-position:center center;
	}
</style>
	<?php
	}
}

Looks way much better, right?

That’s it, a simple way how to fix the CLS issue on WooCommerce Product Page with an image gallery. I believe this hack can be implemented to any theme using the default image gallery from WooCommerce.

Below the image is the metric from WooCommerce Product Page, which image gallery has been replaced by the Flickity slider.

Shall you have anything to ask? Feel free to share your opinion using the Disqus comment form below? Next, I’m going to uncover how I rebuild the image gallery into a flickity image carousel.

Cheers!

]]>
GeneratePress vs. Astra WooCommerce Speed Comparison https://hidonny.com/2022/03/generatepress-vs-astra-woocommerce-speed/ Thu, 03 Mar 2022 10:22:18 +0000 https://hidonny.com/?p=427 Howdy! I recently did some tests to determine which WordPress theme is better in satisfying the Core Web Vitals metrics. As a start, I created this GeneratePress vs. Astra theme post which both themes are known to be very light and highly customizable.

I think this is really interesting. So, I decided that I would be doing stuff like this more often in the future.

I’m using their free version theme with some adjustments on the header to make them look identical.

For this purpose, I created two identical websites. Each of them is installed with the respective theme and the same plugins. Both are hosted on the same server, a small dedicated slice from BuyVM, and use DNS service from Cloudflare with the same server setup.

GeneratePress vs Astra Theme Website Setup

Tested Website URLGeneratePressAstra
Web ServerNginxNginx
PHP VersionPHP 7.4PHP 7.4
DNS ServerCloudflareCloudflare
Caching MethodW3TC Enhanced DiskW3TC Enhanced Disk
Image Lazy LoadW3TC Lazy LoadW3TC Lazy Load
Plugins
FakerPress✔️✔️
W3Total Cache✔️✔️
WebP Express✔️✔️
WooCommerce✔️✔️

Okay, as you can see above, we need several plugins to help us achieve the goals. Those plugins are essential. No matter what kind of website you have, you will always need a page caching method, a webp images tool, and an image lazy load technique.

Both websites have identical headers on mobile and desktop views. I also put an image logo at the header along with their standard hamburger menu.

Both sites are tested using the PageSpeed Insights tool 3 times. Why? Because the first one will probably hit un-cached version of the page. The second one, sometimes glitched and still hit the un-cached version. While the last one most of time will hit the cached version of the page.

GeneratePress vs Astra WooCommerce Shop Page

The first one to test is the catalog or shop page created automatically every time we install WooCommerce on our WordPress site.


URL to Test

URL to Test
ScreenshotScreenshot
GeneratePress vs Astra Shop Page
Mobile View ScoreMobile View Score
Desktop View ScoreDesktop View Score

You can see the test results above; Astra and GeneratePress theme both are tied on mobile and desktop view scores.

GeneratePress vs Astra WooCommerce Product Page with Single Product Image

For the second test, we will see how well they perform on the single product page with only one product image.


URL to Test

URL to Test
ScreenshotScreenshot
Mobile View ScoreMobile View Score
Desktop View ScoreDesktop View Score

On mobile view score, GeneratePress scores 3 points better. I think it happens because Astra has more render-blocking CSS files (4) compared to GeneratePress (3). So the browser needs a longer time to paint the initial element of the page.

GeneratePress vs. Astra WooCommerce Product Page with Gallery Product Image

The last one will be a test on the product page, but both have image galleries on the above the fold area.


URL to Test

URL to Test
ScreenshotScreenshot
Mobile View ScoreMobile View Score
Desktop View ScoreDesktop View Score
Mobile View MetricsMobile View Metrics

Testing the product page with image galleries resulting both themes can’t even reach 90. The real problem here is the Cumulative Layout Shift (CLS) score that badly hurt Astra with a 0.668s delay, while GeneratePress gets half of it.

If we analyze it further, the layout shift on both themes is caused by the image gallery initially loaded by WooCommerce. So the solution is to modify it or completely replace it with a better non-library-dependent image gallery. Anyway, if you want to hack WooCommerce to fulfill your needs, I created a post of my WooCommerce snippets collection.

In the next post, I will show you how to optimize the GeneratePress theme and solve that CLS problem.

Feel free to open a discussion below. Are you the WPAstra team or the GeneratePress team?

]]>