Pourquoi combiner ACF et Gutenberg en 2024-2025 ?

Depuis l’arrivée de l’éditeur Gutenberg dans WordPress 5.0 (décembre 2018), le paysage du développement WordPress a profondément changé. L’éditeur de blocs est devenu le standard, et plus de 65 % des sites WordPress actifs utilisent désormais Gutenberg comme éditeur principal.

Mais soyons honnêtes : développer des blocs Gutenberg natifs en React/JSX reste complexe. Il faut maîtriser JavaScript moderne, la librairie @wordpress/blocks, le système de build avec webpack, et l’API REST de WordPress. Pour un projet client classique — une landing page, un site vitrine, un portail d’entreprise — cette complexité est souvent disproportionnée.

C’est là qu’Advanced Custom Fields Pro entre en jeu. ACF Pro permet de créer des blocs Gutenberg personnalisés en PHP pur, avec un système de champs visuels que les développeurs WordPress connaissent déjà. Résultat :

  • Temps de développement réduit de 40 à 60 % par rapport à l’approche JSX native
  • Expérience d’édition intuitive pour les clients finaux
  • Maintenance simplifiée (pas de build JS, pas de dépendances npm)
  • Compatibilité totale avec l’écosystème WordPress

Chez Lueur Externe, agence web basée dans les Alpes-Maritimes et experte WordPress depuis 2003, cette approche ACF + Gutenberg est devenue notre standard pour les projets sur-mesure. Elle nous permet de livrer des sites performants, faciles à maintenir et agréables à utiliser pour nos clients.

Comprendre l’architecture des blocs ACF Gutenberg

Le principe fondamental

Un bloc ACF Gutenberg fonctionne selon un mécanisme simple :

  1. Vous déclarez le bloc via la fonction acf_register_block_type() (ou le fichier block.json depuis ACF 6.0)
  2. Vous définissez les champs dans l’interface ACF (texte, image, sélecteur, répéteur, etc.)
  3. Vous créez un template PHP qui affiche le rendu du bloc
  4. WordPress fait le lien : dans l’éditeur, l’utilisateur voit le bloc avec ses champs, et le rendu est généré côté serveur via votre template

Contrairement aux blocs natifs qui exigent un fichier edit.js (interface éditeur) et un save.js (rendu front), les blocs ACF utilisent un rendu serveur unique (Server Side Rendering). Le même template PHP sert pour l’aperçu dans l’éditeur et pour le front-end.

Comparaison : bloc natif JSX vs bloc ACF

Voici un tableau comparatif pour mieux comprendre les différences :

CritèreBloc natif (JSX)Bloc ACF (PHP)
Langage principalJavaScript / ReactPHP
Courbe d’apprentissageÉlevéeFaible à modérée
Build nécessaire (webpack)OuiNon
Flexibilité des champsTotale (API JS)Très large (50+ types de champs ACF)
Rendu dans l’éditeurTemps réel côté clientServer-side (léger délai)
Performances front-endExcellentExcellent
Maintenance long termeComplexe (dépendances JS)Simple (PHP pur)
Compatible FSEOuiOui (depuis ACF 6.0)
Dépendance pluginAucuneACF Pro requis
Temps de développement moyen par bloc4 à 8 heures1 à 3 heures

Pour la majorité des projets clients, l’approche ACF est la plus pragmatique. Elle ne convient pas à tous les cas (les blocs très interactifs avec des états complexes nécessitent toujours du React), mais elle couvre facilement 80 à 90 % des besoins courants.

Guide pratique : créer un bloc Gutenberg personnalisé avec ACF Pro

Étape 1 : enregistrer le bloc

Depuis ACF Pro 6.0, la méthode recommandée est d’utiliser un fichier block.json dans un dossier dédié. Voici la structure de fichiers recommandée :

theme/
├── blocks/
│   └── hero-section/
│       ├── block.json
│       ├── render.php
│       └── style.css
├── functions.php

Le fichier block.json de notre bloc “Hero Section” :

{
    "name": "acf/hero-section",
    "title": "Section Hero",
    "description": "Bloc hero avec titre, sous-titre, image de fond et bouton CTA.",
    "category": "theme",
    "icon": "cover-image",
    "keywords": ["hero", "bannière", "header"],
    "acf": {
        "mode": "preview",
        "renderTemplate": "blocks/hero-section/render.php"
    },
    "styles": [
        { "name": "default", "label": "Par défaut", "isDefault": true },
        { "name": "dark", "label": "Sombre" }
    ],
    "supports": {
        "align": ["wide", "full"],
        "anchor": true,
        "jsx": false
    }
}

Puis dans functions.php, on charge automatiquement tous les blocs du dossier blocks/ :

<?php
add_action('init', function() {
    $blocks_dir = get_template_directory() . '/blocks/';
    
    if (!is_dir($blocks_dir)) {
        return;
    }
    
    $block_folders = array_filter(glob($blocks_dir . '*'), 'is_dir');
    
    foreach ($block_folders as $block_folder) {
        register_block_type($block_folder);
    }
});

Cette boucle automatique est très pratique : chaque nouveau dossier dans blocks/ est automatiquement enregistré comme bloc Gutenberg. Plus besoin de modifier functions.php à chaque nouveau bloc.

Étape 2 : définir les champs dans ACF

Dans l’admin WordPress, allez dans ACF → Groupes de champs et créez un nouveau groupe. Configurez la règle d’affichage sur “Bloc est égal à Hero Section”.

Ajoutez les champs suivants :

  • titre_hero (Texte) — Le titre principal
  • sous_titre (Zone de texte) — Le sous-titre descriptif
  • image_fond (Image, retour : tableau) — L’image de fond
  • bouton_texte (Texte) — Le libellé du bouton CTA
  • bouton_lien (Lien) — L’URL du bouton
  • overlay_opacite (Plage, min: 0, max: 100, pas: 10) — L’opacité du calque sombre

L’avantage d’ACF réside dans la richesse de ses types de champs. Avec plus de 50 types disponibles (texte, image, galerie, répéteur, contenu flexible, sélecteur de couleur, Google Maps, relation, etc.), vous pouvez concevoir des interfaces d’édition extrêmement complètes sans écrire une seule ligne de JavaScript.

Étape 3 : créer le template de rendu

Voici le fichier render.php qui génère le HTML du bloc :

<?php
/**
 * Bloc Hero Section — Template de rendu
 *
 * @param array $block      Les données du bloc.
 * @param string $content   Le contenu du bloc (vide pour ACF).
 * @param bool $is_preview  True dans l'éditeur Gutenberg.
 * @param int $post_id      L'ID du post.
 * @param array $context    Le contexte du bloc.
 */

// Récupération des champs
$titre       = get_field('titre_hero');
$sous_titre  = get_field('sous_titre');
$image       = get_field('image_fond');
$btn_texte   = get_field('bouton_texte');
$btn_lien    = get_field('bouton_lien');
$opacite     = get_field('overlay_opacite') ?: 50;

// Classes et ID du bloc
$block_id    = 'hero-' . $block['id'];
$class_name  = 'hero-section';

if (!empty($block['className'])) {
    $class_name .= ' ' . $block['className'];
}
if (!empty($block['align'])) {
    $class_name .= ' align' . $block['align'];
}

// Image de fond
$bg_style = '';
if ($image) {
    $bg_style = 'background-image: url(' . esc_url($image['url']) . ');';
}
?>

<section id="<?php echo esc_attr($block_id); ?>" class="<?php echo esc_attr($class_name); ?>" style="<?php echo $bg_style; ?>">
    <div class="hero-section__overlay" style="opacity: <?php echo esc_attr($opacite / 100); ?>;"></div>
    <div class="hero-section__content">
        <?php if ($titre) : ?>
            <h2 class="hero-section__title"><?php echo esc_html($titre); ?></h2>
        <?php endif; ?>

        <?php if ($sous_titre) : ?>
            <p class="hero-section__subtitle"><?php echo esc_html($sous_titre); ?></p>
        <?php endif; ?>

        <?php if ($btn_lien) : ?>
            <a href="<?php echo esc_url($btn_lien['url']); ?>"
               class="hero-section__cta"
               target="<?php echo esc_attr($btn_lien['target'] ?: '_self'); ?>">
                <?php echo esc_html($btn_texte ?: $btn_lien['title']); ?>
            </a>
        <?php endif; ?>
    </div>
</section>

Notez les bonnes pratiques appliquées ici :

  • Échappement systématique des données avec esc_html(), esc_url(), esc_attr()
  • Gestion des classes dynamiques (alignement, classes personnalisées)
  • Valeurs par défaut pour éviter les erreurs si un champ est vide
  • ID unique pour chaque instance du bloc

Étape 4 : ajouter les styles du bloc

Créez le fichier style.css dans le dossier du bloc :

.hero-section {
    position: relative;
    min-height: 500px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
    overflow: hidden;
}

.hero-section__overlay {
    position: absolute;
    inset: 0;
    background-color: #000;
    z-index: 1;
}

.hero-section__content {
    position: relative;
    z-index: 2;
    text-align: center;
    max-width: 800px;
    padding: 2rem;
    color: #fff;
}

.hero-section__title {
    font-size: clamp(2rem, 5vw, 3.5rem);
    margin-bottom: 1rem;
    line-height: 1.2;
}

.hero-section__subtitle {
    font-size: clamp(1rem, 2.5vw, 1.25rem);
    margin-bottom: 2rem;
    opacity: 0.9;
}

.hero-section__cta {
    display: inline-block;
    padding: 0.875rem 2rem;
    background-color: #2563eb;
    color: #fff;
    text-decoration: none;
    border-radius: 6px;
    font-weight: 600;
    transition: background-color 0.2s ease;
}

.hero-section__cta:hover {
    background-color: #1d4ed8;
}

WordPress charge automatiquement ce fichier style.css grâce à la déclaration dans block.json. Pas besoin de wp_enqueue_style() manuel.

Techniques avancées pour des blocs ACF professionnels

Utiliser les InnerBlocks pour du contenu imbriqué

Parfois, un bloc a besoin de contenir d’autres blocs Gutenberg à l’intérieur. ACF supporte les InnerBlocks en activant le support JSX :

{
    "supports": {
        "jsx": true
    }
}

Dans votre template PHP :

<div class="mon-bloc__wrapper">
    <div class="mon-bloc__sidebar">
        <?php // Champs ACF classiques ?>
    </div>
    <div class="mon-bloc__content">
        <InnerBlocks allowedBlocks='["core/paragraph", "core/heading", "core/list", "core/image"]' />
    </div>
</div>

Cette technique est idéale pour les blocs de mise en page (colonnes personnalisées, sections avec sidebar, etc.) tout en laissant l’utilisateur libre de composer le contenu interne.

Le mode d’édition : preview vs edit

ACF offre trois modes d’affichage pour les blocs dans l’éditeur :

  • preview (par défaut) : affiche le rendu PHP directement dans l’éditeur. L’utilisateur modifie les champs dans le panneau latéral.
  • edit : affiche les champs ACF directement dans la zone d’édition, pas de rendu visuel.
  • auto : permet de basculer entre preview et edit en cliquant sur le bloc.

Pour la meilleure expérience utilisateur, nous recommandons le mode preview avec la possibilité de basculer :

{
    "acf": {
        "mode": "preview"
    }
}

L’éditeur peut alors cliquer sur l’icône crayon dans la barre d’outils du bloc pour passer en mode édition.

Optimiser les performances avec le lazy loading

Pour les blocs contenant des images lourdes ou des éléments complexes, pensez aux performances :

  • Utilisez wp_get_attachment_image() plutôt que de construire les balises <img> manuellement. WordPress gère automatiquement le srcset, le loading="lazy" et les formats WebP.
  • Implémentez du chargement conditionnel pour les scripts et styles spécifiques à un bloc.
  • Profitez de la mise en cache serveur — les blocs ACF étant rendus en PHP, ils bénéficient naturellement des systèmes de cache page (Redis, Varnish, cache objet).
<?php
// Au lieu de :
$image = get_field('image_fond');
echo '<img src="' . $image['url'] . '" alt="' . $image['alt'] . '">';

// Préférez :
$image_id = get_field('image_fond');
if ($image_id) {
    echo wp_get_attachment_image($image_id, 'large', false, [
        'class' => 'hero-section__bg-image',
        'loading' => 'eager' // Pour les images above-the-fold
    ]);
}

Pour cela, configurez le champ image ACF avec le format de retour “ID d’image” plutôt que “Tableau” ou “URL”.

Organiser un projet WordPress avec une bibliothèque de blocs

Sur les projets d’envergure, la création de blocs ACF peut vite devenir un vrai système de design. Voici l’architecture que nous utilisons chez Lueur Externe pour nos projets WordPress professionnels :

theme/
├── blocks/
│   ├── hero-section/
│   │   ├── block.json
│   │   ├── render.php
│   │   ├── style.css
│   │   └── screenshot.png    # Aperçu dans l'inserter
│   ├── cards-grid/
│   ├── testimonials-slider/
│   ├── pricing-table/
│   ├── team-members/
│   ├── cta-banner/
│   ├── faq-accordion/
│   └── stats-counter/
├── parts/                     # Sous-templates réutilisables
│   ├── card.php
│   ├── button.php
│   └── heading.php
├── assets/
│   ├── css/
│   │   └── blocks-common.css  # Styles partagés entre blocs
│   └── js/
│       └── blocks-front.js    # JS front (sliders, animations)
└── functions.php

Cette structure modulaire présente plusieurs avantages :

  • Un bloc = un dossier : facile à localiser, dupliquer, supprimer
  • Templates partiels réutilisables : un composant “carte” ou “bouton” utilisé par plusieurs blocs
  • Séparation claire entre logique (PHP), présentation (CSS) et comportement (JS)
  • Déploiement propre via Git, sans conflit entre développeurs

Pour un site typique de 15 à 25 pages, nous créons généralement entre 8 et 15 blocs personnalisés. Ce nombre suffit pour couvrir tous les besoins éditoriaux tout en gardant l’interface d’édition claire et non encombrée.

Les pièges à éviter

Après des années de développement WordPress avec ACF et Gutenberg, voici les erreurs les plus fréquentes que nous constatons :

1. Créer trop de blocs

Chaque bloc est un choix supplémentaire pour l’éditeur. Au-delà de 20 blocs personnalisés, l’interface devient confuse. Préférez des blocs polyvalents avec des variantes de style plutôt que des dizaines de blocs ultra-spécifiques.

2. Négliger l’aperçu dans l’éditeur

Un bloc qui affiche un message “Aperçu non disponible” dans Gutenberg frustre les utilisateurs. Investissez du temps dans le rendu éditeur : il doit être fidèle au front-end, même si une approximation est acceptable.

3. Oublier la gestion des champs vides

Testez toujours vos blocs avec des champs vides. Un get_field() qui retourne null ou false peut casser votre markup si vous ne gérez pas les conditions.

4. Sous-estimer la documentation

Documentez chaque bloc : son objectif, ses champs, ses variantes. Quand un autre développeur (ou vous-même dans 6 mois) reprend le projet, cette documentation fait gagner un temps considérable.

5. Ignorer l’accessibilité

Vos blocs doivent respecter les normes WCAG 2.1 : contraste suffisant, navigation clavier, attributs ARIA lorsque nécessaire, textes alternatifs pour les images. Ce n’est pas optionnel, c’est une obligation légale (RGAA en France).

Performances et SEO : ce que disent les chiffres

Les blocs ACF étant rendus côté serveur, ils n’ajoutent aucun JavaScript supplémentaire au front-end par défaut. C’est un avantage considérable pour les Core Web Vitals :

  • LCP (Largest Contentful Paint) : les blocs ACF ne bloquent pas le rendu — contrairement aux blocs dynamiques React qui nécessitent une hydratation côté client
  • CLS (Cumulative Layout Shift) : le HTML étant généré côté serveur, la mise en page est stable dès le chargement initial
  • INP (Interaction to Next Paint) : sans JavaScript superflu, les interactions sont immédiates

Sur les projets que nous avons mesurés chez Lueur Externe, les sites utilisant des blocs ACF Gutenberg obtiennent en moyenne un score PageSpeed Insights de 92/100 sur mobile, contre 78/100 pour des sites équivalents construits avec des page builders classiques (Elementor, WPBakery).

Ce gain de performance se traduit directement en meilleur référencement naturel. Google utilise les Core Web Vitals comme facteur de classement depuis 2021, et chaque milliseconde de chargement en moins compte.

Quand choisir ACF Gutenberg vs d’autres solutions ?

L’approche ACF + Gutenberg n’est pas universelle. Voici un guide de décision rapide :

  • Choisissez ACF + Gutenberg si : votre client doit pouvoir éditer le contenu facilement, le site a entre 5 et 100 pages, vous avez besoin de blocs sur-mesure mais sans interactivité complexe côté client.
  • Choisissez les blocs natifs React si : vous développez un plugin distribué (pas de dépendance à ACF), le bloc nécessite des interactions riches en temps réel dans l’éditeur, vous avez une équipe JavaScript confirmée.
  • Choisissez un page builder (Elementor, etc.) si : le budget est très limité, le client veut construire ses pages sans intervention développeur, le design n’a pas besoin d’être pixel-perfect.

Conclusion : passez à l’action avec des blocs Gutenberg sur-mesure

Le duo ACF Pro + Gutenberg est aujourd’hui la méthode la plus efficace pour développer des sites WordPress professionnels, performants et faciles à maintenir. En supprimant la complexité JavaScript inutile, cette approche permet aux développeurs PHP de créer des expériences d’édition modernes, tout en conservant un contrôle total sur le markup HTML et les performances.

Que vous démarriez un nouveau projet ou que vous souhaitiez migrer un site existant vers une architecture Gutenberg modulaire, l’investissement en vaut la peine. Vos clients apprécieront l’interface d’édition intuitive, et votre référencement naturel bénéficiera de pages plus rapides et mieux structurées.

Vous avez un projet WordPress nécessitant des blocs Gutenberg personnalisés ? L’équipe de Lueur Externe, spécialiste WordPress et SEO depuis plus de 20 ans dans les Alpes-Maritimes, vous accompagne de la conception à la mise en production. Contactez-nous pour discuter de votre projet et obtenir un devis adapté à vos besoins.