vendredi 25 septembre 2026

À propos

Contact

Elementor

Widgets Elementor custom et Core Web Vitals : bien coder pour l’ère de l’INP

Depuis mars 2024, l'INP a remplacé le FID dans les Core Web Vitals. Voici comment écrire des widgets Elementor en PHP qui ne plombent pas la réactivité de vos pages.

Par Clément Hadrot • 14 mai 2024 • 8 min de lecture • Aucun commentaire
Widgets Elementor custom et Core Web Vitals : bien coder pour l'ère de l'INP

Depuis mars 2024, Google a remplacé le First Input Delay par l’Interaction to Next Paint dans son trio de Core Web Vitals. Ce changement n’est pas anecdotique pour qui développe des widgets Elementor personnalisés : le FID ne mesurait que le délai avant la toute première interaction de l’utilisateur, souvent un chiffre flatteur car il ignorait tout ce qui se passait après ce premier clic. L’INP, lui, observe toutes les interactions de la visite et retient la pire latence perçue, du clic au rendu visuel de sa conséquence.

Pour un développeur qui écrit des widgets custom en PHP, cela change la manière d’aborder le sujet. Ce n’est plus seulement « est-ce que ma page se charge vite », mais « est-ce que chaque bouton, chaque accordéon, chaque interaction reste fluide tout au long de la navigation ». Et la réponse à cette question se joue autant côté PHP, dans la façon dont vous enregistrez vos scripts, que côté JavaScript, dans ce que ces scripts font une fois exécutés.

Comprendre ce que l’INP mesure vraiment

L’INP capture le temps entre l’action de l’utilisateur (clic, appui sur une touche, tap sur mobile) et le moment où le navigateur peint visuellement le résultat de cette action à l’écran. Google considère qu’un site a un bon INP en dessous de 200 millisecondes, qu’il a besoin d’amélioration entre 200 et 500 millisecondes, et qu’il est médiocre au-delà.

Sur un site construit avec Elementor, les interactions concernées sont nombreuses : ouverture d’un menu mobile, d’un accordéon, d’une popup, filtrage d’une galerie, soumission d’un formulaire de contact. Chacun de ces widgets embarque potentiellement son propre script, et si ce script bloque le thread principal du navigateur au moment de l’interaction, l’INP en pâtit directement, même si le reste de la page se charge très vite.

Éviter le JavaScript bloquant dans le render() du widget

La méthode render() d’un widget Elementor s’exécute côté PHP, au moment de la génération du HTML. Elle n’est donc pas directement responsable de l’INP, qui est une mesure côté navigateur. Mais elle a une influence indirecte importante : c’est dans cette méthode que vous décidez quels scripts enqueuer, avec quelles dépendances, et souvent c’est là que des développeurs pressés insèrent un <script> inline directement dans le HTML retourné par le widget.

Ce script inline, exécuté de façon synchrone pendant le parsing du DOM, est l’un des pires ennemis de la réactivité. Il bloque le thread principal avant même que la page ne soit interactive, et s’il contient une logique un peu lourde (tri, filtrage, manipulation du DOM sur toute la page), il retarde toutes les interactions qui suivent, pas seulement celle liée au widget.

L'essentiel à retenir : L'INP remplace le FID depuis mars 2024 ; Éviter le JS bloquant dans le rendu des widgets ; Différer les scripts avec wp_register_script et strategy

Limiter et différer les scripts avec wp_register_script

La bonne pratique consiste à enregistrer chaque script en dépendance explicite via wp_register_script, puis à l’enqueuer uniquement quand le widget est réellement présent sur la page, en utilisant le paramètre strategy introduit par WordPress 6.3 pour différer son exécution. Deux stratégies existent : defer, qui retarde l’exécution jusqu’à ce que le DOM soit prêt sans bloquer le parsing, et async, qui télécharge le script en parallèle et l’exécute dès qu’il est prêt, sans ordre garanti par rapport aux autres scripts.

Pour un widget d’interaction comme un accordéon ou un carrousel, defer est presque toujours le bon choix : le script n’a rien à faire avant que le HTML ne soit entièrement parsé, et il doit s’exécuter dans un ordre prévisible par rapport à ses dépendances éventuelles, comme jQuery.

Exemple de widget avec chargement différé

Voici un exemple simplifié mais réaliste d’un widget Elementor personnalisé, un accordéon FAQ, qui enregistre son script avec dépendance explicite et stratégie de défer, sans rien enqueuer si le widget n’est pas utilisé sur la page :

class WPM_Faq_Accordion_Widget extends \Elementor\Widget_Base {

    public function get_name() {
        return 'wpm_faq_accordion';
    }

    public function get_title() {
        return __( 'FAQ Accordion', 'wpm-elementor' );
    }

    public function get_script_depends() {
        return [ 'wpm-faq-accordion' ];
    }

    public function get_style_depends() {
        return [ 'wpm-faq-accordion-style' ];
    }

    protected function register_controls() {
        $this->start_controls_section(
            'content_section',
            [ 'label' => __( 'Questions', 'wpm-elementor' ) ]
        );
        $this->add_control(
            'faq_items',
            [
                'label'   => __( 'Liste des questions', 'wpm-elementor' ),
                'type'    => \Elementor\Controls_Manager::REPEATER,
            ]
        );
        $this->end_controls_section();
    }

    protected function render() {
        $settings = $this->get_settings_for_display();
        echo '<div class="wpm-faq" data-widget-id="' . esc_attr( $this->get_id() ) . '">';
        foreach ( (array) $settings['faq_items'] as $item ) {
            echo '<div class="wpm-faq-item">';
            echo '<button class="wpm-faq-question">' . esc_html( $item['question'] ) . '</button>';
            echo '<div class="wpm-faq-answer">' . wp_kses_post( $item['answer'] ) . '</div>';
            echo '</div>';
        }
        echo '</div>';
    }
}

add_action( 'wp_enqueue_scripts', function () {
    wp_register_script(
        'wpm-faq-accordion',
        get_stylesheet_directory_uri() . '/assets/js/faq-accordion.js',
        [],
        '1.0.0',
        [ 'strategy' => 'defer', 'in_footer' => true ]
    );
    wp_register_style(
        'wpm-faq-accordion-style',
        get_stylesheet_directory_uri() . '/assets/css/faq-accordion.css',
        [],
        '1.0.0'
    );
} );

Le point clé ici : get_script_depends() et get_style_depends() indiquent à Elementor de n’enqueuer ces fichiers que sur les pages où le widget est effectivement utilisé, et l’enregistrement avec strategy => 'defer' garantit que le script ne bloque jamais le rendu initial de la page.

Ce qui se passe côté JavaScript compte tout autant

Différer le chargement du script ne suffit pas si son code, une fois exécuté au clic, effectue un calcul lourd de façon synchrone. Quelques règles simples à respecter dans le JavaScript de vos widgets :

  • Évitez de recalculer des positions ou des dimensions sur l’ensemble de la page à chaque interaction ; limitez le recalcul à l’élément concerné.
  • Découpez les traitements longs (tri d’une longue liste, filtrage d’une galerie avec beaucoup d’éléments) en tâches plus petites plutôt que de tout faire en une seule passe synchrone.
  • Préférez les gestionnaires d’événements délégués sur un conteneur parent plutôt qu’un listener par élément, surtout pour les widgets qui génèrent beaucoup de répétitions (accordéons, listes de témoignages).
  • Évitez les animations CSS coûteuses déclenchées en JS sur des propriétés qui forcent un reflow (comme width ou top) ; préférez transform et opacity.

Le cas particulier de l’IA générative dans les widgets

Certains widgets récents intègrent des fonctionnalités boostées par l’IA générative, par exemple pour reformuler un texte ou générer une description côté back-office. Ce type de traitement n’a rien à faire dans le parcours de l’utilisateur final : il doit rester confiné à l’expérience d’édition dans Elementor, jamais exécuté côté front au chargement de la page publique. C’est un rappel utile : la question à se poser pour chaque script n’est pas seulement « est-il différé », mais « a-t-il vraiment besoin d’être présent sur le front public ».

Testez systématiquement vos widgets avec l’outil Performance de Chrome DevTools, en simulant un CPU ralenti à 4x ou 6x : c’est souvent la seule façon de repérer une tâche longue qui reste invisible sur votre machine de développement, mais qui plombe l’INP réel de vos visiteurs sur mobile.

En résumé

L’arrivée de l’INP dans les Core Web Vitals change la façon d’évaluer un widget Elementor custom : ce n’est plus la vitesse de la première interaction qui compte, mais la réactivité de toutes les interactions tout au long de la visite. Trois réflexes à adopter systématiquement : enregistrer les scripts avec des dépendances explicites et une stratégie de défer, ne jamais insérer de script inline bloquant dans le render(), et écrire un JavaScript qui évite les tâches longues et synchrones au moment du clic.

Ce sont des habitudes de codage assez simples à prendre, mais qui demandent de la discipline, surtout quand on reprend un widget existant hérité d’un ancien projet. Prenez le temps de les auditer un par un : l’INP, contrairement au FID, ne pardonne pas les mauvaises surprises qui n’arrivent qu’au deuxième ou troisième clic de l’utilisateur.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi