Construye un archivo de productos con pestañas para tu tienda WooCommerce
Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)
En este tutorial aprenderás cómo hacer más atractiva tu tienda WooCommerce al organizar el archivo de producto con pestañas. Crearemos pestañas con una maquetación compuesta de varias columnas, un carrusel de varias filas, y una maquetación tipo cuadrícula ("grid layout").
Qué vamos a construir
En los próximos pasos crearemos un plugin de WordPress, dentro del cual configuraremos los shortcodes requeridos. Si deseas llevar tu archivo de productos WooCommerce más allá, podrías convertirlo en un bloque Gutenberg, usarlo con Elementor como widget o integrarlo con WPBakery Page Builder (anteriormente denominado Visual Composer).
Esta página de archivo de producto con pestañas será perfecta para mostrar los productos más recientes, los destacados, los que estén en oferta, y los más vendidos, de la siguiente manera:



Así que, ¡empecemos!
1. Crear un plugin WordPress
En tu sitio WordPress, dentro de wp-content/plugins, crea una carpeta denominada (quizá no sea el nombre más original) "woocommerce-products", y después, dentro de esta carpeta crea un archivo php con el mismo nombre. Abre el archivo y pega dentro de él el siguiente código cambiando los detalles necesarios para adaptarlo a los tuyos):
1 |
/*
|
2 |
Plugin Name: WooCommerce products
|
3 |
Plugin URI: https://www.enovathemes.com
|
4 |
Description: Better product grouping presentation for your WooCommerce shop
|
5 |
Author: Enovathemes
|
6 |
Version: 1.0
|
7 |
Author URI: https://enovathemes.com
|
8 |
*/
|
9 |
|
10 |
if ( ! defined( 'ABSPATH' ) ) { |
11 |
exit; // Exit if accessed directly |
12 |
}
|
Aquí no hemos hecho nada más que definir el nombre de nuestro plugin y proporcionar alguna meta información.
Encolar scripts y estilos
Para nuestro plugin WooCommerce de archivo de producto necesitaremos encolar los scripts y estilos necesarios, así que añade el siguiente fragmento de código:
1 |
// Enqueue/register styles and scripts
|
2 |
function plugin_scripts_styles(){ |
3 |
|
4 |
wp_enqueue_style( 'style', plugins_url('/css/style.css', __FILE__ ), array(), '1.0.0' ); |
5 |
|
6 |
// Required Plugins
|
7 |
wp_enqueue_script( 'imagesloaded'); |
8 |
wp_enqueue_script( 'owl-carousel', plugins_url('/js/owl.carousel.js', __FILE__ ), array('jquery'), '', true); |
9 |
// Main js file
|
10 |
wp_enqueue_script( 'main', plugins_url('/js/main.js', __FILE__ ), array('jquery'), '', true); |
11 |
}
|
12 |
add_action( 'wp_enqueue_scripts', 'plugin_scripts_styles' ); |
Primero, hemos añadido un archivo CSS básico para guardar nuestros estilos. Después hemos cargado el plugin integrado imageLoaded (que viene con el núcleo de WordPress), y para crear el carrusel usaremos el popular plugin jQuery owlCarousel. Y, por supuesto, el archivo js principal.
Nota: Asegúrate de añadir estos archivos en la carpeta de tu plugin y dentro a su vez de las subcarpetas pertinentes.
Para conocer más sobre la creación de plugins y shortcodes para WordPress, o para obtener más información sobre cómo usar owl.js, aquí tienes algunos tutoriales recomendados disponibles en Tuts+:


jQueryCómo construir un slider de carrusel responsivo a pantalla completa con Owl.jsGeorge Martsoukos
PluginsConsejo rápido: Usar shortcodes en el desarrollo de temasSumeet Chawla

Plugins WordPress3 proyectos prácticos para aprender a codificar plugins de WordPressRachel McCollin

WordPressIntroducción al desarrollo de plugins para WordPressRachel McCollin
2. Crear un shortcode para la pestaña
En este paso crearemos un shortcode para la pestaña. Realmente consistirá en dos shortcodes; uno para el contenedor padre de la pestaña, y después otro para los elementos de la pestaña hija del anterior. Para el primer contenedor, añade este código al archivo PHP:
1 |
// Create tab shortcode
|
2 |
function et_tab($atts, $content = null) { |
3 |
|
4 |
extract(shortcode_atts(array(), $atts)); |
5 |
|
6 |
$output = ''; |
7 |
|
8 |
static $id_counter = 1; |
9 |
|
10 |
$class = array(); |
11 |
$class[] = 'et-tab'; |
12 |
$class[] = 'et-clearfix'; |
13 |
|
14 |
$output .='<div id="et-tab-'.$id_counter.'" class="'.implode(" ", $class).'">'; |
15 |
$output .= do_shortcode($content); |
16 |
$output .= '</div>'; |
17 |
|
18 |
$id_counter++; |
19 |
|
20 |
return $output; |
21 |
|
22 |
}
|
23 |
add_shortcode('et_tab', 'et_tab'); |
Este shortcode no requiere ningún atributo, es simplemente un contenedor para los elementos que irán dentro de él.
Hablando de los elementos de la pestaña, a continuación, añade el código de abajo para crear el elemento de pestaña hijo:
1 |
function et_tab_item($atts, $content = null) { |
2 |
|
3 |
extract(shortcode_atts(array( |
4 |
'title' => '', |
5 |
'active' => 'false', |
6 |
), $atts)); |
7 |
|
8 |
$output = ''; |
9 |
|
10 |
static $id_counter = 1; |
11 |
|
12 |
$class = array(); |
13 |
$class[] = 'tab-item'; |
14 |
$class[] = 'et-clearfix'; |
15 |
$class[] = 'active-'.esc_attr($active); |
16 |
|
17 |
$output .= '<div data-target="tab-'. sanitize_title( $title ) .'" class="'.implode(' ',$class).'">'; |
18 |
if (isset($title) && !empty($title)) { |
19 |
$output .= esc_attr($title); |
20 |
}
|
21 |
$output .= '</div> '; |
22 |
$output .= '<div id="tab-'.sanitize_title($title).'-'.$id_counter.'" class="tab-content et-clearfix">'; |
23 |
$output .= do_shortcode($content); |
24 |
$output .= '</div>'; |
25 |
|
26 |
$id_counter++; |
27 |
|
28 |
return $output; |
29 |
}
|
30 |
add_shortcode('et_tab_item', 'et_tab_item'); |
Este shortcode tiene dos atributos; el título y el indicador activo, en caso de que desees activar la pestaña de destino en la primera carga.
Cuando usemos los dos shortcodes juntos en el editor WordPress, tendrán el siguiente aspecto:
1 |
[et_tab] [et_tab_item title="Your title"] …content here[/et_tab_item][/et_tab] |
En este punto, si los añades a tu página principal y observas el resultado final en tu navegador, verás una salida HTML sin estilo que aún no funciona. Así que vamos a arreglarlo.
3. Añadir jQuery para potenciar el contenido con pestañas
Dirígete al archivo main.js y pega el código
1 |
(function($){ |
2 |
|
3 |
"use strict"; |
4 |
|
5 |
$('.et-tab').each(function(){ |
6 |
|
7 |
var $this = $(this), |
8 |
tabs = $this.find('.tab-item'), |
9 |
tabsQ = tabs.length, |
10 |
tabsContent = $this.find('.tab-content'); |
11 |
|
12 |
tabs.wrapAll('<div class="tabset et-clearfix"></div>'); |
13 |
tabsContent.wrapAll('<div class="tabs-container et-clearfix"></div>'); |
14 |
|
15 |
var tabSet = $this.find('.tabset'); |
16 |
|
17 |
if(!tabs.hasClass('active')){ |
18 |
tabs.first().addClass('active'); |
19 |
}
|
20 |
|
21 |
tabs.each(function(){ |
22 |
|
23 |
var $thiz = $(this); |
24 |
|
25 |
if ($thiz.hasClass('active')) { |
26 |
$thiz.siblings() |
27 |
.removeClass("active"); |
28 |
tabsContent.hide(0).removeClass('active'); |
29 |
tabsContent.eq($thiz.index()).show(0).addClass('active'); |
30 |
}
|
31 |
});
|
32 |
|
33 |
if(tabsQ >= 2){ |
34 |
|
35 |
tabs.on('click', function(){ |
36 |
var $self = $(this); |
37 |
|
38 |
if(!$self.hasClass("active")){ |
39 |
|
40 |
$self.addClass("active"); |
41 |
|
42 |
$self.siblings() |
43 |
.removeClass("active"); |
44 |
|
45 |
tabsContent.hide(0).removeClass('active'); |
46 |
tabsContent.eq($self.index()).show(0).addClass('active'); |
47 |
|
48 |
}
|
49 |
|
50 |
});
|
51 |
}
|
52 |
|
53 |
});
|
54 |
|
55 |
})(jQuery); |
No voy a describir todo este código detalladamente, dicho brevemente, proporciona funcionalidad a la pestaña. Si no estás familiarizado con JavaScript o jQuery, te recomiendo este increíble curso gratuito para principiantes:
Aplicar estilo a las pestañas
Ahora las pestañas ya funcionan, pero tienen un feo aspecto, así que vamos a añadir algo de CSS básico:
1 |
.tabset { |
2 |
margin-bottom: 24px; |
3 |
}
|
4 |
|
5 |
.tabset > * { |
6 |
display: inline-block; |
7 |
vertical-align: middle; |
8 |
padding: 8px 16px; |
9 |
line-height: 1em; |
10 |
background: #f5f5f5; |
11 |
margin-right: 8px; |
12 |
cursor: pointer; |
13 |
}
|
14 |
|
15 |
.tabset > .active { |
16 |
background: #000000; |
17 |
color: #ffffff; |
18 |
}
|
19 |
|
20 |
.tabset > :last-child { |
21 |
margin-right: 0; |
22 |
}
|
4. Crear el shortcode de productos WooCommerce
estamos haciendo grandes progresos; ¡nuestro archivo de producto con pestañas de WooCommerce está casi terminado! Ha llegado el momento de crear un shortcode para los productos. Este extraerá los productos a través de una consulta, a partir de esos resultados, creará una serie de matrices (arrays): productos destacados, en oferta, y los más vendidos. A continuación mostrará el contenido de esas matrices para proporcionarnos nuestras pestañas de productos.
Añade este código al archivo PHP:
1 |
function et_products($atts, $content = null) { |
2 |
extract(shortcode_atts( |
3 |
array( |
4 |
'layout' => 'grid', // grid OR carousel |
5 |
'autoplay' => 'false', // true OR false |
6 |
'columns' => '1', // 1 | 2 | 3 | 4 |
7 |
'rows' => '1', // 1 | 2 | 3 | 4 - carousel only |
8 |
'quantity' => '12', |
9 |
'type' => 'recent', // recent | featured | sale | best_selling |
10 |
), $atts) |
11 |
);
|
12 |
|
13 |
static $id_counter = 1; |
14 |
|
15 |
if (class_exists('Woocommerce')) { |
16 |
|
17 |
$output = ''; |
18 |
|
19 |
global $post; |
20 |
|
21 |
$query_options = array( |
22 |
'post_type' => 'product', |
23 |
'post_status' => 'publish', |
24 |
'meta_query' => WC()->query->get_meta_query(), |
25 |
'tax_query' => WC()->query->get_tax_query(), |
26 |
'ignore_sticky_posts' => 1, |
27 |
'posts_per_page' => absint($quantity), |
28 |
);
|
29 |
|
30 |
if ($type == "featured"){ |
31 |
$query_options = array( |
32 |
'post_type' => 'product', |
33 |
'post_status' => 'publish', |
34 |
'meta_query' => WC()->query->get_meta_query(), |
35 |
'ignore_sticky_posts' => 1, |
36 |
'posts_per_page' => absint($quantity), |
37 |
'tax_query' => array( |
38 |
array( |
39 |
'taxonomy' => 'product_visibility', |
40 |
'field' => 'name', |
41 |
'terms' => 'featured', |
42 |
'operator' => 'IN', |
43 |
)
|
44 |
),
|
45 |
);
|
46 |
}
|
47 |
|
48 |
if ($type == "sale"){ |
49 |
$query_options = array( |
50 |
'post_type' => 'product', |
51 |
'post_status' => 'publish', |
52 |
'meta_query' => WC()->query->get_meta_query(), |
53 |
'ignore_sticky_posts' => 1, |
54 |
'posts_per_page' => absint($quantity), |
55 |
'post__in' => array_merge( array( 0 ), wc_get_product_ids_on_sale() ), |
56 |
);
|
57 |
}
|
58 |
|
59 |
if ($type == "best_selling"){ |
60 |
|
61 |
$query_options = array( |
62 |
'post_type' => 'product', |
63 |
'post_status' => 'publish', |
64 |
'meta_query' => WC()->query->get_meta_query(), |
65 |
'tax_query' => WC()->query->get_tax_query(), |
66 |
'ignore_sticky_posts' => 1, |
67 |
'posts_per_page' => absint($quantity), |
68 |
'orderby' => 'meta_value_num', |
69 |
'meta_key' => 'total_sales', |
70 |
);
|
71 |
}
|
72 |
|
73 |
$products = new WP_Query($query_options); |
74 |
|
75 |
if($products->have_posts()){ |
76 |
|
77 |
$counter = 1; |
78 |
|
79 |
$class = array(); |
80 |
$attributes = array(); |
81 |
|
82 |
$class[] = 'products'; |
83 |
$class[] = esc_attr($layout); |
84 |
|
85 |
if ($layout == 'carousel') { |
86 |
$class[] = 'owl-carousel'; |
87 |
}
|
88 |
|
89 |
$attributes[] = 'data-columns="'.esc_attr($columns).'"'; |
90 |
$attributes[] = 'data-autoplay="'.esc_attr($autoplay).'"'; |
91 |
|
92 |
$output .= '<ul class="'.esc_attr(implode(' ', $class)).'" '.implode(' ', $attributes).'>'; |
93 |
|
94 |
while ($products->have_posts() ) { |
95 |
|
96 |
$products->the_post(); |
97 |
|
98 |
global $product; |
99 |
|
100 |
if ($layout == "carousel" && $rows != 1) { |
101 |
|
102 |
$product_wrapper_start = ''; |
103 |
$product_wrapper_end = ''; |
104 |
|
105 |
if (($counter % 2 == 1 && $rows == 2) || ($counter % 3 == 1 && $rows == 3) || ($counter % 4 == 1 && $rows == 4)){ |
106 |
$product_wrapper_start = '<li class="product-wrapper">'; |
107 |
}
|
108 |
|
109 |
if (($counter % 2 == 0 && $rows == 2) || ($counter % 3 == 0 && $rows == 3) || ($counter % 4 == 0 && $rows == 4)){ |
110 |
$product_wrapper_end = '</li>'; |
111 |
}
|
112 |
|
113 |
$output .= $product_wrapper_start; |
114 |
$output .= '<div class="product" id="product-'.esc_attr($product->get_id()).'">'; |
115 |
ob_start(); |
116 |
do_action( 'woocommerce_before_shop_loop_item' ); |
117 |
do_action( 'woocommerce_before_shop_loop_item_title' ); |
118 |
do_action( 'woocommerce_shop_loop_item_title' ); |
119 |
do_action( 'woocommerce_after_shop_loop_item_title' ); |
120 |
do_action( 'woocommerce_after_shop_loop_item' ); |
121 |
$output .= ob_get_clean(); |
122 |
$output .= '</div>'; |
123 |
$output .= $product_wrapper_end; |
124 |
|
125 |
$counter++; |
126 |
|
127 |
} else { |
128 |
$output .= '<li class="product" id="product-'.esc_attr($product->get_id()).'">'; |
129 |
ob_start(); |
130 |
do_action( 'woocommerce_before_shop_loop_item' ); |
131 |
do_action( 'woocommerce_before_shop_loop_item_title' ); |
132 |
do_action( 'woocommerce_shop_loop_item_title' ); |
133 |
do_action( 'woocommerce_after_shop_loop_item_title' ); |
134 |
do_action( 'woocommerce_after_shop_loop_item' ); |
135 |
$output .= ob_get_clean(); |
136 |
$output .= '</li>'; |
137 |
}
|
138 |
|
139 |
}
|
140 |
|
141 |
wp_reset_postdata(); |
142 |
|
143 |
$output .= '</ul>'; |
144 |
|
145 |
$id_counter++; |
146 |
|
147 |
return $output; |
148 |
|
149 |
}
|
150 |
|
151 |
} else { |
152 |
echo "Please install/activate Woocommerce plugin"; |
153 |
}
|
154 |
}
|
155 |
add_shortcode('et_products', 'et_products'); |
El shortcode que hemos creado aquí tiene distintos atributos:
- Layout: puede ser de cuadrícula (grid) o carrusel
- Autoplay – true (verdadero) o false (falso), esta es una opción adicional para el diseño del carrusel
- Columns: aquí puedes especificar cuántas columnas deseas
- Rows: esto es lo mismo que las columnas y solo se aplica al diseño por carrusel
- Quantity: el número de artículos que se mostrarán
- Type: aquí puedes especificar productos recientes (recent products) , los más vendidos (best sellers), los que están en oferta (sale) o featured products (productos destacados)
Una nota sobre las filas de nuestro carrusel
Cuando tienes un carrusel, cada producto se convierte en un elemento del carrusel, con comportamiento estándar cuando solo tenemos una fila. Sin embargo, ¿qué sucede si queremos dos, tres o cuatro filas por elemento de carrusel?
En este caso, necesitarías envolver cada una de estas posibilidades dentro de un contenedor que actuaría como elemento de carrusel. Y aquí aparece una cuestión: ¿Harías esto con JavaScript o con PHP? Yo prefiero la segunda opción, ya que la ejecución de JS tiene algunos retrasos. Así que, si examinas el shortcode descubrirás lo siguiente:
1 |
$product_wrapper_start = ''; |
2 |
$product_wrapper_end = ''; |
3 |
|
4 |
if (($counter % 2 == 1 && $rows == 2) || ($counter % 3 == 1 && $rows == 3) || ($counter % 4 == 1 && $rows == 4)){ |
5 |
$product_wrapper_start = '<li class="product-wrapper">'; |
6 |
}
|
7 |
|
8 |
if (($counter % 2 == 0 && $rows == 2) || ($counter % 3 == 0 && $rows == 3) || ($counter % 4 == 0 && $rows == 4)){ |
9 |
$product_wrapper_end = '</li>'; |
10 |
}
|
Advierte el
1 |
$counter = 1; |
inmediatamente después de
1 |
if($products->have_posts()){ |
Esto es muy similar a un bucle for, necesitamos un incremento para recorrer en bucle nuestra consulta y envolver cada dos, cada tres y cada cuatro elementos de producto dentro del marcado del contenedor para los elementos por carrusel.
Habrás notado el %, se trata del operador de modulo. Proporciona el resto de una división; 0 cuando el número es exactamente divisible por 2/3/4, y 1 cuando no lo es. Y con cada bucle tendremos que incrementar el contador con:
1 |
$counter++; |
Esto sucede justo tras el código:
1 |
$output .= $product_wrapper_start; |
2 |
$output .= '<div class="product" id="product-'.esc_attr($product->get_id()).'">'; |
3 |
ob_start(); |
4 |
do_action( 'woocommerce_before_shop_loop_item' ); |
5 |
do_action( 'woocommerce_before_shop_loop_item_title' ); |
6 |
do_action( 'woocommerce_shop_loop_item_title' ); |
7 |
do_action( 'woocommerce_after_shop_loop_item_title' ); |
8 |
do_action( 'woocommerce_after_shop_loop_item' ); |
9 |
$output .= ob_get_clean(); |
10 |
$output .= '</div>'; |
11 |
$output .= $product_wrapper_end; |
5. Añade los estilos de Owl 🦉�
1 |
ul.products { |
2 |
list-style: none; |
3 |
margin: 0; |
4 |
padding: 0; |
5 |
}
|
6 |
|
7 |
ul.products.grid { |
8 |
display: grid; |
9 |
grid-row-gap: 24px; |
10 |
grid-column-gap: 24px; |
11 |
}
|
12 |
|
13 |
ul.products.grid[data-columns="2"]{grid-template-columns: repeat(2, 2fr);} |
14 |
ul.products.grid[data-columns="3"]{grid-template-columns: repeat(3, 3fr);} |
15 |
ul.products.grid[data-columns="4"]{grid-template-columns: repeat(4, 4fr);} |
16 |
|
17 |
ul li { |
18 |
display: block; |
19 |
padding: 0; |
20 |
margin: 0 |
21 |
}
|
22 |
|
23 |
.product { |
24 |
position: relative; |
25 |
text-align: center; |
26 |
}
|
27 |
|
28 |
.woocommerce-loop-product__title { |
29 |
margin-top: 16px !important; |
30 |
font-size: 1em !important; |
31 |
}
|
32 |
|
33 |
.product a { |
34 |
display: block; |
35 |
text-decoration: none; |
36 |
border-bottom: none !important; |
37 |
}
|
38 |
|
39 |
.product .onsale { |
40 |
position: absolute; |
41 |
left: 0; |
42 |
padding: 4px; |
43 |
background: red; |
44 |
color: #ffffff; |
45 |
}
|
46 |
.et-tab .owl-nav { |
47 |
position: absolute; |
48 |
top: -60px; |
49 |
right: 0; |
50 |
}
|
51 |
|
52 |
.et-tab .owl-nav > * { |
53 |
display: inline-block; |
54 |
vertical-align: middle; |
55 |
width: 40px; |
56 |
height: 40px; |
57 |
text-align: center; |
58 |
line-height: 40px; |
59 |
background: #f5f5f5 !important; |
60 |
}
|
61 |
|
62 |
.et-tab .owl-nav > :last-child { |
63 |
margin-left: 8px; |
64 |
}
|
65 |
|
66 |
.et-tab .owl-nav > *:hover { |
67 |
background: #000000 !important; |
68 |
color: #ffffff !important; |
69 |
}
|
1 |
// Initialize carousel for the first load
|
2 |
|
3 |
$('.products.carousel').each(function(){ |
4 |
|
5 |
var $this = $(this); |
6 |
$this.imagesLoaded(function(){ |
7 |
$this.owlCarousel({ |
8 |
margin:24, |
9 |
nav:true, |
10 |
autoplay:$this.data('autoplay'), |
11 |
items:$this.data('columns'), |
12 |
responsive:{ |
13 |
320 : {items:1}, |
14 |
768 : {items:2}, |
15 |
1024 : {items:3}, |
16 |
1280 : {items:$this.data('columns')} |
17 |
},
|
18 |
});
|
19 |
});
|
20 |
|
21 |
});
|
6. Corregir el glitch del carruselh
1 |
function refreshCarousel(tab){ |
2 |
tab.find('.products.carousel').each(function(){ |
3 |
jQuery(this).trigger('refresh.owl.carousel'); |
4 |
});
|
5 |
}
|
1 |
tabsContent.eq($self.index()).show(0).addClass('active'); |
1 |
refreshCarousel(tabsContent.eq($self.index())); |
1 |
<!-- wp:shortcode -->
|
2 |
[et_tab][et_tab_item title="recent"][et_products layout="grid" autoplay="false" columns="3" rows="1" quantity="6" type="recent" /][/et_tab_item][et_tab_item title="featured"][et_products layout="grid" autoplay="false" columns="3" rows="1" quantity="6" type="featured" /][/et_tab_item][et_tab_item title="sale"][et_products layout="grid" autoplay="false" columns="3" rows="1" quantity="6" type="sale" /][/et_tab_item][et_tab_item title="best selling"][et_products layout="grid" autoplay="false" columns="3" rows="1" quantity="6" type="best_selling" /][/et_tab_item][/et_tab] |
3 |
<!-- /wp:shortcode -->
|
4 |
|
5 |
<!-- wp:separator -->
|
6 |
<hr class="wp-block-separator"/> |
7 |
<!-- /wp:separator -->
|
8 |
|
9 |
<!-- wp:shortcode -->
|
10 |
[et_tab][et_tab_item title="recent"][et_products layout="grid" autoplay="false" columns="4" rows="1" quantity="8" type="recent" /][/et_tab_item][et_tab_item title="featured"][et_products layout="grid" autoplay="false" columns="4" rows="1" quantity="8" type="featured" /][/et_tab_item][et_tab_item title="sale"][et_products layout="grid" autoplay="false" columns="4" rows="1" quantity="8" type="sale" /][/et_tab_item][et_tab_item title="best selling"][et_products layout="grid" autoplay="false" columns="4" rows="1" quantity="8" type="best_selling" /][/et_tab_item][/et_tab] |
11 |
<!-- /wp:shortcode -->
|
12 |
|
13 |
<!-- wp:separator -->
|
14 |
<hr class="wp-block-separator"/> |
15 |
<!-- /wp:separator -->
|
16 |
|
17 |
<!-- wp:shortcode -->
|
18 |
[et_tab][et_tab_item title="recent"][et_products layout="carousel" autoplay="false" columns="3" rows="1" quantity="12" type="recent" /][/et_tab_item][et_tab_item title="featured"][et_products layout="carousel" autoplay="false" columns="3" rows="1" quantity="12" type="featured" /][/et_tab_item][et_tab_item title="sale"][et_products layout="carousel" autoplay="false" columns="3" rows="1" quantity="12" type="sale" /][/et_tab_item][et_tab_item title="best selling"][et_products layout="carousel" autoplay="false" columns="3" rows="1" quantity="12" type="best_selling" /][/et_tab_item][/et_tab] |
19 |
<!-- /wp:shortcode -->
|
20 |
|
21 |
<!-- wp:separator -->
|
22 |
<hr class="wp-block-separator"/> |
23 |
<!-- /wp:separator -->
|
24 |
|
25 |
<!-- wp:shortcode -->
|
26 |
[et_tab][et_tab_item title="recent"][et_products layout="carousel" autoplay="false" columns="4" rows="2" quantity="12" type="recent" /][/et_tab_item][et_tab_item title="featured"][et_products layout="carousel" autoplay="false" columns="2" rows="2" quantity="12" type="featured" /][/et_tab_item][et_tab_item title="sale"][et_products layout="carousel" autoplay="false" columns="3" rows="2" quantity="12" type="sale" /][/et_tab_item][et_tab_item title="best selling"][et_products layout="carousel" autoplay="false" columns="3" rows="1" quantity="12" type="best_selling" /][/et_tab_item][/et_tab] |
27 |
<!-- /wp:shortcode -->
|







