Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Move WooCommerce subcategory list items into their own <ul> separate from the product <ul>.
<?php
/**
* Move WooCommerce subcategory list items into
* their own <ul> separate from the product <ul>.
*/
add_action( 'init', 'move_subcat_lis' );
function move_subcat_lis() {
// Remove the subcat <li>s from the old location.
remove_filter( 'woocommerce_product_loop_start', 'woocommerce_maybe_show_product_subcategories' );
add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_start', 40 );
add_action( 'woocommerce_before_shop_loop', 'msc_maybe_show_product_subcategories', 50 );
add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_end', 60 );
}
/**
* Conditonally start the product loop with a <ul> contaner if subcats exist.
*/
function msc_product_loop_start() {
$subcategories = woocommerce_maybe_show_product_subcategories();
if ( $subcategories ) {
woocommerce_product_loop_start();
}
}
/**
* Print the subcat <li>s in our new location.
*/
function msc_maybe_show_product_subcategories() {
echo woocommerce_maybe_show_product_subcategories();
}
/**
* Conditonally end the product loop with a </ul> if subcats exist.
*/
function msc_product_loop_end() {
$subcategories = woocommerce_maybe_show_product_subcategories();
if ( $subcategories ) {
woocommerce_product_loop_end();
}
}
@daw8706

This comment has been minimized.

Copy link

@daw8706 daw8706 commented Nov 3, 2018

Thank you SO much for this. It is absolutely perfect and exactly what I've been trying to do for days.
When "Display Type" is set to "Both" for a category, It allows me to move the categories ABOVE Sorting&Product Counts and into before_shop_loop, which is where it should be I think (because changing the sort order does not change the order in which the subcategories are displayed). I just changed the priorities to display the subcategories after the category description, before the sorting options and product list.
add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_start', 1 );
add_action( 'woocommerce_before_shop_loop', 'msc_maybe_show_product_subcategories', 2 );
add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_end', 3 );

You are amazing, thank you!

@daw8706

This comment has been minimized.

Copy link

@daw8706 daw8706 commented Nov 9, 2018

One question, can I give the newly created ul class="products columns-4" a different class name? It currently interferes with my filters because it tries to filter the subcategories due to still being in ul.products.

@rubinablack

This comment has been minimized.

Copy link

@rubinablack rubinablack commented Jan 30, 2019

I'm sorry but I'm not familiar with the structure of woocommerce. May I ask how exactly do you use this file? How does woocommerce reads it?
I created a woocommerce folder at my Avada child theme and place the file, but nothing changed. Do I have to add something in functions.php file? I tried add_action() functionalities mentioned above but it didn't work.
Thanks!

@StefanTrailovic

This comment has been minimized.

Copy link

@StefanTrailovic StefanTrailovic commented Feb 6, 2019

Works great, thank you!
Just one little problem. It doesn't work when you have infinite scroll for woocommerce products. I'm guessing because it reloads the original script and therefore it goes back to the original layout. Do you have any solution for this? (Infinite scroll with Flatsome theme)

@ProjectKarol

This comment has been minimized.

Copy link

@ProjectKarol ProjectKarol commented Apr 14, 2019

Working Great , than you

@eggdesign

This comment has been minimized.

Copy link

@eggdesign eggdesign commented May 9, 2019

This is excellent thanks. How do i add differnt class to the categories though? they both have ul class="products columns-3" which is causing issues with styling. Cheers

@1stwebdesigns

This comment has been minimized.

Copy link

@1stwebdesigns 1stwebdesigns commented May 24, 2019

I also want to find a way of changing the class name on the categories list. The above code is a step in the right direction but I can't believe this is still so difficult to do in Woocommerce after all these years,

@eggdesign

This comment has been minimized.

Copy link

@eggdesign eggdesign commented May 24, 2019

I also want to find a way of changing the class name on the categories list. The above code is a step in the right direction but I can't believe this is still so difficult to do in Woocommerce after all these years,

I found a workaround for it. Just copy archive-product.php to your child theme folder then add a wrapper div around the products section. This will allow you to style the products separate from the categories. You may need to add some opening & closing php tags too to add the div. Screenshot here: https://ibb.co/GTvgkTx

@fkoomek

This comment has been minimized.

Copy link

@fkoomek fkoomek commented Jun 13, 2019

My solutions:

  1. You can just delete woocommerce_product_loop_start(); and woocommerce_product_loop_end(); from the code and echo your products wrapper.
<?php
add_action( 'init', 'move_subcat_lis' );
function move_subcat_lis() {
	// Remove the subcat <li>s from the old location.
	remove_filter( 'woocommerce_product_loop_start', 'woocommerce_maybe_show_product_subcategories' );
	add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_start', 40 );
	add_action( 'woocommerce_before_shop_loop', 'msc_maybe_show_product_subcategories', 50 );
	add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_end', 60 );
}

/**
 * Conditonally start the product loop with a <ul> contaner if subcats exist.
 */
function msc_product_loop_start() {
	$subcategories = woocommerce_maybe_show_product_subcategories();
	if ( $subcategories ) {
		echo '<ul class="product-cats">';  //products wrapper
	}
}
/**
 * Print the subcat <li>s in our new location.
 */
function msc_maybe_show_product_subcategories() {
	echo woocommerce_maybe_show_product_subcategories();
}
/**
 * Conditonally end the product loop with a </ul> if subcats exist.
 */
function msc_product_loop_end() {
	$subcategories = woocommerce_maybe_show_product_subcategories();
	if ( $subcategories ) {
		echo '</ul>';  //products wrapper ends
	}
}

You will need some CSS to style your subcategories then. For example:

ul.product-cats li {
    list-style: none;
    margin-bottom: 4.236em;
	font-size:1.1em;
	float: left;	
	width: 48%;
}

ul.product-cats li:nth-child(2n+2){
float:right;	
}

ul.product-cats li img {
    margin: 0 0 1em; 
}

ul.product-cats{
margin:0;	
}
 
@media screen and (min-width:769px) {
    ul.product-cats li {
        width: 22.05%;
        float: left;
        margin: 0 3.8% 2em 0;
    }
		ul.product-cats li:nth-child(2n+2){
float:left;	
}
    ul.product-cats li:nth-of-type(4n+4) {
        margin-right: 0;
    }
}

the CSS code is made to fit my theme so you will have to tweak it.
I was working with the CSS provided at https://code.tutsplus.com/tutorials/display-woocommerce-categories-subcategories-and-products-in-separate-lists--cms-25479 so maybe it will better option to start with.

You can wrap the whole ul element of subcategories with your own element like:

<?php
add_action( 'init', 'move_subcat_lis' );
function move_subcat_lis() {
	// Remove the subcat <li>s from the old location.
	remove_filter( 'woocommerce_product_loop_start', 'woocommerce_maybe_show_product_subcategories' );
	add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_start', 40 );
	add_action( 'woocommerce_before_shop_loop', 'msc_maybe_show_product_subcategories', 50 );
	add_action( 'woocommerce_before_shop_loop', 'msc_product_loop_end', 60 );
}
/**
 * Conditonally start the product loop with a <ul> contaner if subcats exist.
 */
function msc_product_loop_start() {
	$subcategories = woocommerce_maybe_show_product_subcategories();
	if ( $subcategories ) {
		echo '<div class="subcategories">'; //custom wrapper 
		woocommerce_product_loop_start();
	}
}
/**
 * Print the subcat <li>s in our new location.
 */
function msc_maybe_show_product_subcategories() {
	echo woocommerce_maybe_show_product_subcategories();
}
/**
 * Conditonally end the product loop with a </ul> if subcats exist.
 */
function msc_product_loop_end() {
	$subcategories = woocommerce_maybe_show_product_subcategories();
	if ( $subcategories ) {
		woocommerce_product_loop_end();
		echo '</div>'; //custom wrapper ends
	}
}
@Timoti

This comment has been minimized.

Copy link

@Timoti Timoti commented Oct 3, 2019

Super stoked to find this @twoelevenjay - thanks for sharing and supporting

@twoelevenjay

This comment has been minimized.

Copy link
Owner Author

@twoelevenjay twoelevenjay commented Oct 3, 2019

@rubinablack ypu would add this code to your functions.php file or include the file by writing require_once 'PATH_TO_FILE'; in the functions.php file. Sorry this reply is so late. I don't get notifications for comments unless I am @ mentioned.

@twoelevenjay

This comment has been minimized.

Copy link
Owner Author

@twoelevenjay twoelevenjay commented Oct 3, 2019

@daw8706, @eggdesign , @1stwebdesigns sorry I never so these comments before. I am happy that @fkoomek gave a good answer on how to change the value of the class property of the

    tag.

@twoelevenjay

This comment has been minimized.

Copy link
Owner Author

@twoelevenjay twoelevenjay commented Oct 3, 2019

@StefanTrailovic, I am sorry I don't have Flatsome. I am guessing that maybe infinite scroll evokes the template files directly and doesn't use the actions that I have hooked here. Or maybe infinite scroll has its own template files. You would have to look through the code for template files named something like loop-start-end.php, or look for functions like add_action(). Sorry for the delayed response.

@newcomer9087

This comment has been minimized.

Copy link

@newcomer9087 newcomer9087 commented Nov 13, 2019

@twoelevenjay I am having the same problem as @StefanTrailovic different theme, infinite loader load twice the products as I start scrolling, I don't know much coding any specific fix?
searched for the loop.php file but I think there is none, looking for the functions seems impossible to me.
Any help will be much appreciated.

@twoelevenjay

This comment has been minimized.

Copy link
Owner Author

@twoelevenjay twoelevenjay commented Nov 13, 2019

@newcomer9087, by any chance, is there a publicly accessible URL that I can see this issue in action? What theme are you using, and is the infinite scroll a theme option or from a plugin?

@newcomer9087

This comment has been minimized.

Copy link

@newcomer9087 newcomer9087 commented Nov 14, 2019

@twoelevenjay Theme is inktheme, fresh veggies layout, but I don't think it has to do with the theme, is more about the plugin how it acts with wocommerce with your code added into functions.php.

The plugin is WooCommerce Load More Products - BeRocket.

I have emailed you the site let me know if you did not receive any mail.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment