Caroselli in WordPress senza plugin: come ho integrato Owl Carousel nel mio child theme
Quando ho iniziato a costruire la sezione competenze del mio sito, avevo un problema semplice: volevo mostrare le icone delle tecnologie che uso in un carousel scorrevole. Niente di complicato. Ma ogni plugin carousel che ho esaminato portava con sé funzionalità che non mi servivano, CSS globali che interferivano con il tema, e in alcuni casi un editor proprietario da imparare.
Ho deciso di fare diversamente: integrare direttamente Owl Carousel 2 nel child theme, senza plugin intermedi. Quello che sembrava un lavoro di un pomeriggio mi ha insegnato alcune cose che uso ancora oggi su ogni progetto WordPress.
Il punto di partenza: cosa volevo e cosa non volevo
Il carousel delle competenze tecniche ha requisiti precisi: 21 icone SVG, loop infinito, autoplay, breakpoint responsivi. Il contenuto non cambia spesso lo aggiorno io direttamente nel codice, non da WordPress admin. Non ha senso usare il block editor per qualcosa che non verrà mai toccato da un redattore.
Ho scelto Owl Carousel 2 per tre motivi concreti: è una libreria matura (44 KB minificata), gestisce i breakpoint responsivi via oggetto di configurazione JavaScript, e funziona senza CSS aggiuntivi complessi. Non è la soluzione più moderna sul mercato, ma è stabile, documentata e fa esattamente quello che serve.
Come l’ho integrato nel child theme
La struttura dei file è minimale:
generatepress-child/
├── functions.php
├── style.css
└── inc/
├── owl-carousel.min.js (44 KB)
├── owl-carousel.min.css (4 KB)
└── img/ (21 icone SVG/WebP)Registrazione lazy degli asset
Il dettaglio che cambia tutto è la differenza tra wp_register_* e wp_enqueue_*. Sbagliando, si caricano 44 KB su ogni pagina del sito. Facendolo correttamente, quegli asset vengono iniettati nel DOM solo quando lo shortcode è effettivamente presente nella pagina.
// Registra gli asset disponibili, non ancora caricati
function dm_register_owl_carousel(): void {
wp_register_style(
'owl-carousel-style',
get_stylesheet_directory_uri() . '/inc/owl-carousel.min.css',
[], '2.3.4'
);
wp_register_script(
'owl-carousel-script',
get_stylesheet_directory_uri() . '/inc/owl-carousel.min.js',
[ 'jquery' ], '2.3.4', true
);
}
add_action( 'wp_enqueue_scripts', 'dm_register_owl_carousel' );
Lo shortcode poi fa la chiamata wp_enqueue_* solo quando viene eseguito il che avviene solo sulle pagine dove è inserito.
Lo shortcode completo
Le 21 icone sono definite in un array PHP: aggiungere una tecnologia richiede una riga, senza toccare il markup HTML. Il markup viene generato con ob_start() / ob_get_clean() per tenere separata la logica PHP dall’output HTML.
function dm_owl_software_skills(): string {
wp_enqueue_style( 'owl-carousel-style' );
wp_enqueue_script( 'owl-carousel-script' );
$skills = [
[ 'label' => 'WordPress', 'icon' => 'wordpress.svg' ],
[ 'label' => 'PHP', 'icon' => 'php.svg' ],
[ 'label' => 'JavaScript', 'icon' => 'javascript.svg' ],
[ 'label' => 'React', 'icon' => 'react.svg' ],
// ... altri skill
];
ob_start();
?>
<div id="owl-carousel-software-skills" class="owl-carousel owl-theme">
<?php foreach ( $skills as $skill ) : ?>
<div class="skill-item">
<img src="<?php echo esc_url( get_stylesheet_directory_uri() . '/img/icons/' . $skill['icon'] ); ?>"
alt="<?php echo esc_attr( $skill['label'] ); ?>"
loading="lazy" />
<span><?php echo esc_html( $skill['label'] ); ?></span>
</div>
<?php endforeach; ?>
</div>
<script>
jQuery(document).ready(function($) {
$("#owl-carousel-software-skills").owlCarousel({
loop: true,
margin: 40,
dots: false,
nav: false,
autoplay: true,
autoplayTimeout: 3000,
autoplayHoverPause: true,
responsive: {
0: { items: 4 },
600: { items: 9 },
1000: { items: 14 }
}
});
});
</script>
<?php
return ob_get_clean();
}
add_shortcode( 'owl-software-skills', 'dm_owl_software_skills' );
Un dettaglio CSS che ho dovuto aggiungere: le icone hanno altezze diverse, e senza allineamento esplicito si creano piccoli spostamenti durante lo scroll.
.owl-stage {
display: flex;
align-items: center;
}Lo stesso pattern, dati diversi
La struttura dello shortcode è riutilizzabile. Ho esteso il pattern per altri due casi d’uso:
Carousel di articoli alimentato da WP_Query, accetta attributi shortcode per filtrare per categoria, numero di post, ordinamento:
[owl-posts-carousel count="6" category="development"]
Aggiornare il carousel significa semplicemente pubblicare nuovi articoli. Il wp_reset_postdata() alla fine è essenziale: ripristina il contesto post globale e previene che i template successivi leggano il post sbagliato.
Carousel di prodotti WooCommerce estrae da post_type='product' con filtri avanzati (categoria, in evidenza, in saldo). La classe ajax_add_to_cart abilita il comportamento AJAX nativo di WooCommerce per i prodotti semplici:
[owl-products-carousel category="abbigliamento" featured="yes"]
[owl-products-carousel on_sale="yes" count="10"]Quando usare questo approccio e quando no
Owl Carousel con shortcode ha senso quando il contenuto è fisso o semi-fisso e gestito dallo sviluppatore. Per contenuti dinamici modificabili dall’admin WordPress, il block editor con GenerateBlocks Pro Carousel è la scelta giusta nessun PHP da toccare, interfaccia visuale, CSS variables native.
La stessa distinzione vale per la dipendenza da jQuery: se il sito lo usa già (come nel mio caso con GeneratePress), Owl non aggiunge peso reale. Se stai costruendo su un tema jQuery-free, considera Splide.js o Embla Carousel, che pesano rispettivamente 30 KB e 8 KB senza dipendenze.
Cosa ho imparato
Il pattern register/enqueue separato è uno di quei dettagli WordPress che sembrano burocratici finché non vedi il difference in Lighthouse tra “carico la libreria su ogni pagina” e “carico la libreria solo dove serve”. Per un sito portfolio con traffico reale, la differenza è misurabile.