Recently I’ve been working on my second WooCommerce project and I’ve found it quite a flexible solution so far. Woocommerce pretty much expects products to have images and the templates expect there to be a product image, so when you have a product without an image (because it’s a service and not a physical product for example), things don’t look that good. The following solution allows you to selectively modify the appearance of imageless product listings.
Notes: This is a good solution if you have a mix of products/services with and without images, or you have imageless products for which you may want to add product images later. You could also write your own template which overrides the default template. This solution however works well with the default template WooCommerce provides.
Because WooCommerce inserts an image element with a placeholder if no image was set for the product, the first thing we need to do is to prevent the image tag from showing up. We can do that by calling a custom funtion from the appropriate WooCommerce hook. For product listings that are shown in loops, the action hook that adds the function for the image display is called ‘woo_commerce_before_shop_loop_item’. There is another action hook called ‘woocommerce_before_shop_loop_item’ that runs before the image – which is wrapped in a link – is outputted. That’s the point where we want to run our modifications.
function before_imageless_product() { if( !has_post_thumbnail( get_the_id() ) ){ remove_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 ); echo ''; } } add_action( 'woocommerce_before_shop_loop_item', 'before_imageless_product', 9 );
So what’s going on here? Well, we first check to see if the product in question has a thumbnail associated with it. If it has, we can maintain the normal templating, if it hasn’t we want to prevent an image element containing a placeholder from being inserted. We do that by calling remove_action on the ‘woocommerce_template_loop_product_thumbnail’ function. Because we want products with images to maintain their templating, we have to remember to add this function back. We do that by adding the call back right after, which we’ll get to next.
You’ll see we’re also inserting a div when there is no image present. Why? Well, the chances are you want to modify the layout in CSS so that the display looks nice in your theme. In that case we’ll need a way to style the product listings that have no image separately from those products that do have an image. Because there are no filters that are run on the CSS classes of the product listing that we can tap into easily, another way to do this is to simply wrap the product output in a div with its own class name. That way we can target the product listing in CSS without having to write a different template from scratch.
Now that we have implemented to code to remove the image from imageless product listings, we complete the modification by adding the image function back in and closing the div element we just inserted before the loop continues.
function after_imageless_product() { if( !has_post_thumbnail( get_the_id() ) ){ add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 ); echo ''; } } add_action( 'woocommerce_after_shop_loop_item', 'after_imageless_product', 9 );
You should now see that default placeholder isn’t being outputted. You may want to tweak the css to make the imageless products look better. You can now easily do so by targeting those listings with the .no-image class.
* This example assumes a default-ish WooCommerce setup, if you have customized WooCommerce or are running a WooCommerce theme, there is a small possibility that the display is handled differently and the code might not work as intended.