Introduction
Le développement de thèmes WordPress a changé de nature avec l’introduction du Full Site Editing (FSE) et des block themes. En 2025, les standards de développement exigent une approche moderne qui combine l’éditeur de blocs, les global styles, l’accessibilité WCAG et les performances optimales. Ce guide vous accompagne dans la création d’un thème WordPress professionnel conforme aux dernières normes.
Architecture d’un block theme moderne
Structure de fichiers recommandée
La structure d’un block theme diffère des thèmes classiques. Voici l’organisation recommandée pour 2025 :
mon-theme/
├── style.css
├── theme.json
├── functions.php
├── templates/
│ ├── index.html
│ ├── single.html
│ ├── page.html
│ ├── archive.html
│ ├── 404.html
│ └── search.html
├── parts/
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
├── patterns/
│ ├── hero.php
│ ├── call-to-action.php
│ └── testimonials.php
├── assets/
│ ├── css/
│ ├── js/
│ └── images/
├── inc/
│ ├── block-patterns.php
│ ├── block-styles.php
│ └── custom-blocks.php
└── languages/
Le fichier style.css
Le header du fichier style.css est obligatoire et doit respecter ce format :
/*
Theme Name: Mon Theme Moderne
Theme URI: https://exemple.com/mon-theme
Author: Votre Nom
Author URI: https://exemple.com
Description: Un theme WordPress moderne construit avec les standards 2025, Full Site Editing, et optimisé pour les performances.
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 8.0
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: mon-theme
Tags: block-themes, full-site-editing, accessibility-ready, translation-ready, custom-colors, custom-menu, featured-images, threaded-comments, wide-blocks
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned.
*/
Le fichier theme.json : Le coeur du thème
Le fichier theme.json est le fichier de configuration central d’un block theme moderne. Il définit les styles globaux, les paramètres et les fonctionnalités.
Configuration complète de theme.json
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"settings": {
"appearanceTools": true,
"useRootPaddingAwareAlignments": true,
"layout": {
"contentSize": "840px",
"wideSize": "1200px"
},
"color": {
"custom": true,
"customDuotone": true,
"customGradient": true,
"defaultGradients": false,
"defaultPalette": false,
"duotone": [
{
"colors": ["#000000", "#ffffff"],
"slug": "black-and-white",
"name": "Noir et Blanc"
}
],
"gradients": [
{
"slug": "primary-to-secondary",
"gradient": "linear-gradient(135deg, var(--wp--preset--color--primary) 0%, var(--wp--preset--color--secondary) 100%)",
"name": "Primaire vers Secondaire"
}
],
"palette": [
{
"slug": "primary",
"color": "#0066cc",
"name": "Primaire"
},
{
"slug": "secondary",
"color": "#ff6b35",
"name": "Secondaire"
},
{
"slug": "foreground",
"color": "#1a1a1a",
"name": "Premier plan"
},
{
"slug": "background",
"color": "#ffffff",
"name": "Arrière-plan"
},
{
"slug": "tertiary",
"color": "#f5f5f5",
"name": "Tertiaire"
}
]
},
"typography": {
"customFontSize": true,
"fontStyle": true,
"fontWeight": true,
"letterSpacing": true,
"textDecoration": true,
"textTransform": true,
"dropCap": false,
"fluid": true,
"fontSizes": [
{
"slug": "small",
"size": "0.875rem",
"name": "Petit",
"fluid": {
"min": "0.875rem",
"max": "1rem"
}
},
{
"slug": "medium",
"size": "1rem",
"name": "Moyen",
"fluid": false
},
{
"slug": "large",
"size": "1.5rem",
"name": "Grand",
"fluid": {
"min": "1.25rem",
"max": "1.5rem"
}
},
{
"slug": "x-large",
"size": "2.5rem",
"name": "Très grand",
"fluid": {
"min": "2rem",
"max": "2.5rem"
}
}
],
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
"slug": "system",
"name": "Système"
},
{
"fontFamily": "'Inter', sans-serif",
"slug": "inter",
"name": "Inter",
"fontFace": [
{
"fontFamily": "Inter",
"fontWeight": "400",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/inter-regular.woff2"]
},
{
"fontFamily": "Inter",
"fontWeight": "700",
"fontStyle": "normal",
"fontDisplay": "swap",
"src": ["file:./assets/fonts/inter-bold.woff2"]
}
]
}
]
},
"spacing": {
"customSpacingSize": true,
"spacingScale": {
"steps": 0
},
"spacingSizes": [
{
"slug": "30",
"size": "0.5rem",
"name": "1"
},
{
"slug": "40",
"size": "1rem",
"name": "2"
},
{
"slug": "50",
"size": "1.5rem",
"name": "3"
},
{
"slug": "60",
"size": "2rem",
"name": "4"
},
{
"slug": "70",
"size": "3rem",
"name": "5"
},
{
"slug": "80",
"size": "4rem",
"name": "6"
}
],
"units": ["px", "em", "rem", "vh", "vw", "%"]
},
"custom": {
"spacing": {
"gutter": "1.5rem"
},
"transition": {
"duration": "0.3s"
}
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--background)",
"text": "var(--wp--preset--color--foreground)"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--inter)",
"fontSize": "var(--wp--preset--font-size--medium)",
"lineHeight": "1.6"
},
"spacing": {
"padding": {
"top": "0",
"right": "var(--wp--preset--spacing--40)",
"bottom": "0",
"left": "var(--wp--preset--spacing--40)"
}
},
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
},
"typography": {
"textDecoration": "underline"
},
":hover": {
"color": {
"text": "var(--wp--preset--color--secondary)"
}
}
},
"button": {
"color": {
"background": "var(--wp--preset--color--primary)",
"text": "var(--wp--preset--color--background)"
},
"typography": {
"fontSize": "var(--wp--preset--font-size--medium)",
"fontWeight": "700"
},
"spacing": {
"padding": {
"top": "0.75rem",
"right": "1.5rem",
"bottom": "0.75rem",
"left": "1.5rem"
}
},
"border": {
"radius": "0.25rem"
},
":hover": {
"color": {
"background": "var(--wp--preset--color--secondary)"
}
}
},
"h1": {
"typography": {
"fontSize": "var(--wp--preset--font-size--x-large)",
"fontWeight": "700",
"lineHeight": "1.2"
},
"spacing": {
"margin": {
"top": "0",
"bottom": "var(--wp--preset--spacing--50)"
}
}
},
"h2": {
"typography": {
"fontSize": "var(--wp--preset--font-size--large)",
"fontWeight": "700",
"lineHeight": "1.3"
}
}
},
"blocks": {
"core/navigation": {
"typography": {
"fontSize": "var(--wp--preset--font-size--medium)"
}
},
"core/post-title": {
"typography": {
"fontSize": "var(--wp--preset--font-size--x-large)",
"fontWeight": "700"
}
},
"core/quote": {
"color": {
"background": "var(--wp--preset--color--tertiary)"
},
"spacing": {
"padding": {
"top": "var(--wp--preset--spacing--50)",
"right": "var(--wp--preset--spacing--50)",
"bottom": "var(--wp--preset--spacing--50)",
"left": "var(--wp--preset--spacing--50)"
}
},
"border": {
"left": {
"width": "4px",
"style": "solid",
"color": "var(--wp--preset--color--primary)"
}
}
}
}
},
"templateParts": [
{
"name": "header",
"title": "En-tête",
"area": "header"
},
{
"name": "footer",
"title": "Pied de page",
"area": "footer"
}
],
"customTemplates": [
{
"name": "page-sans-titre",
"title": "Page sans titre",
"postTypes": ["page"]
}
]
}
Templates HTML : L’architecture des pages
Template index.html
Le template templates/index.html est obligatoire :
-

Développer un thème WordPress avec les standards 2025
Introduction Le développement de thèmes WordPress a changé de nature avec l’introduction du Full Site Editing (FSE) et des block themes. En 2025, les standards de développement exigent une approche…
Template single.html
Le fichier functions.php : Configuration et extensions
Le fichier functions.php reste essentiel même dans un block theme :
100,
'width' => 400,
'flex-height' => true,
'flex-width' => true,
) );
// Support HTML5
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
) );
// Support de l'éditeur de blocs
add_theme_support( 'wp-block-styles' );
add_theme_support( 'responsive-embeds' );
add_theme_support( 'editor-styles' );
add_editor_style( 'assets/css/editor-style.css' );
// Support des liens Atom pour les commentaires
add_theme_support( 'automatic-feed-links' );
// Enregistrer les menus
register_nav_menus( array(
'primary' => **( 'Menu principal', 'mon-theme' ),
'footer' => **( 'Menu pied de page', 'mon-theme' ),
) );
}
add_action( 'after_setup_theme', 'montheme_setup' );
/**
* Enregistrer et charger les scripts/styles
*/
function montheme_enqueue_scripts() {
// Style principal (déjà inclus par WordPress)
wp_enqueue_style( 'montheme-style', get_stylesheet_uri(), array(), MONTHEME_VERSION );
// Styles supplémentaires
wp_enqueue_style(
'montheme-blocks',
MONTHEME_URI . '/assets/css/blocks.css',
array( 'montheme-style' ),
MONTHEME_VERSION
);
// Script principal avec dépendances modernes
wp_enqueue_script(
'montheme-script',
MONTHEME_URI . '/assets/js/main.js',
array(),
MONTHEME_VERSION,
true
);
// Support des commentaires threaded
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
wp_enqueue_script( 'comment-reply' );
}
}
add_action( 'wp_enqueue_scripts', 'montheme_enqueue_scripts' );
/**
* Enregistrer les scripts pour l'éditeur
*/
function montheme_enqueue_editor_assets() {
wp_enqueue_script(
'montheme-editor',
MONTHEME_URI . '/assets/js/editor.js',
array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
MONTHEME_VERSION,
true
);
}
add_action( 'enqueue_block_editor_assets', 'montheme_enqueue_editor_assets' );
/**
* Charger les fichiers d'inclusion
*/
require_once MONTHEME_DIR . '/inc/block-patterns.php';
require_once MONTHEME_DIR . '/inc/block-styles.php';
/**
* Ajouter des styles de blocs personnalisés
*/
function montheme_register_block_styles() {
// Style pour le bloc paragraphe
register_block_style(
'core/paragraph',
array(
'name' => 'montheme-highlight',
'label' => **( 'Mise en évidence', 'mon-theme' ),
'style_handle' => 'montheme-blocks',
)
);
// Style pour le bloc bouton
register_block_style(
'core/button',
array(
'name' => 'montheme-outline',
'label' => **( 'Contour', 'mon-theme' ),
'style_handle' => 'montheme-blocks',
)
);
// Style pour le bloc groupe
register_block_style(
'core/group',
array(
'name' => 'montheme-card',
'label' => **( 'Carte', 'mon-theme' ),
'style_handle' => 'montheme-blocks',
)
);
}
add_action( 'init', 'montheme_register_block_styles' );
/**
* Personnaliser la requête principale
*/
function montheme_pre_get_posts( $query ) {
// Modifier uniquement la requête principale sur le front-end
if ( ! is_admin() && $query->is_main_query() ) {
// Exemple : afficher 12 posts par page sur les archives
if ( $query->is_archive() ) {
$query->set( 'posts_per_page', 12 );
}
}
}
add_action( 'pre_get_posts', 'montheme_pre_get_posts' );
/**
* Ajouter des classes CSS personnalisées au body
*/
function montheme_body_classes( $classes ) {
// Ajouter une classe si le sidebar est actif
if ( is_active_sidebar( 'sidebar-1' ) ) {
$classes[] = 'has-sidebar';
}
// Ajouter une classe pour les pages sans titre
if ( is_page() && ! get_the_title() ) {
$classes[] = 'no-title';
}
return $classes;
}
add_filter( 'body_class', 'montheme_body_classes' );
/**
* Filtrer l'excerpt length
*/
function montheme_excerpt_length( $length ) {
return 30;
}
add_filter( 'excerpt_length', 'montheme_excerpt_length' );
/**
* Personnaliser le "read more" de l'excerpt
*/
function montheme_excerpt_more( $more ) {
if ( ! is_admin() ) {
return sprintf(
' %s',
esc_url( get_permalink() ),
esc_html**( 'Continuer la lecture', 'mon-theme' )
);
}
return $more;
}
add_filter( 'excerpt_more', 'montheme_excerpt_more' );
/**
* Optimisation des performances : Désactiver les emojis
*/
function montheme_disable_emojis() {
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
}
add_action( 'init', 'montheme_disable_emojis' );
/**
* Ajouter un préchargement pour les polices
*/
function montheme_preload_fonts() {
?>
Block Patterns : Créer des modèles réutilisables
Créez le fichier inc/block-patterns.php :
**( 'Sections Hero', 'mon-theme' ) )
);
register_block_pattern_category(
'montheme-cta',
array( 'label' => **( 'Call to Action', 'mon-theme' ) )
);
register_block_pattern_category(
'montheme-testimonials',
array( 'label' => **( 'Témoignages', 'mon-theme' ) )
);
}
add_action( 'init', 'montheme_register_pattern_categories' );
/**
* Enregistrer les patterns
*/
function montheme_register_patterns() {
// Pattern Hero avec image de fond
register_block_pattern(
'montheme/hero-with-background',
array(
'title' => **( 'Hero avec image de fond', 'mon-theme' ),
'description' => **( 'Une section hero avec image de fond et texte centré', 'mon-theme' ),
'categories' => array( 'montheme-hero' ),
'content' => '
Bienvenue sur notre site
Découvrez nos services exceptionnels
',
)
);
// Pattern CTA
register_block_pattern(
'montheme/cta-box',
array(
'title' => **( 'Boîte CTA', 'mon-theme' ),
'description' => **( 'Une boîte call-to-action avec fond coloré', 'mon-theme' ),
'categories' => array( 'montheme-cta' ),
'content' => '
Prêt à commencer ?
Rejoignez des milliers d'utilisateurs satisfaits
',
)
);
}
add_action( 'init', 'montheme_register_patterns' );
Accessibilité : Standards WCAG 2025
Skip link dans le header
Créez parts/header.html avec un skip link :
CSS pour l'accessibilité
Ajoutez dans assets/css/blocks.css :
/**
* Styles d'accessibilité
*/
/* Skip link */
.skip-link {
position: absolute;
left: -9999px;
top: 2.5em;
z-index: 999999;
text-decoration: underline;
background-color: #fff;
color: #000;
padding: 1em;
border-radius: 4px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}
.skip-link:focus {
left: 1em;
}
/* Screen reader text */
.screen-reader-text {
border: 0;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
word-wrap: normal !important;
}
.screen-reader-text:focus {
background-color: #fff;
border-radius: 3px;
box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
clip: auto !important;
clip-path: none;
color: #000;
display: block;
font-size: 0.875rem;
font-weight: 700;
height: auto;
left: 5px;
line-height: normal;
padding: 15px 23px 14px;
text-decoration: none;
top: 5px;
width: auto;
z-index: 100000;
}
/* Focus visible pour la navigation au clavier */
a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
outline: 2px solid var(--wp--preset--color--primary);
outline-offset: 2px;
border-radius: 2px;
}
/* Contraste élevé pour les liens */
a {
text-decoration-thickness: 1px;
text-underline-offset: 2px;
}
/* Améliorer la lisibilité */
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Animations respectant prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Mode sombre */
@media (prefers-color-scheme: dark) {
:root {
--wp--preset--color--foreground: #ffffff;
--wp--preset--color--background: #1a1a1a;
--wp--preset--color--tertiary: #2a2a2a;
}
}
/**
* Styles de blocs personnalisés
*/
/* Style highlight pour paragraphe */
.is-style-montheme-highlight {
background-color: var(--wp--preset--color--tertiary);
padding: var(--wp--preset--spacing--50);
border-left: 4px solid var(--wp--preset--color--primary);
}
/* Style outline pour bouton */
.is-style-montheme-outline.wp-block-button__link {
background-color: transparent;
border: 2px solid currentColor;
}
.is-style-montheme-outline.wp-block-button__link:hover {
background-color: var(--wp--preset--color--primary);
color: var(--wp--preset--color--background);
}
/* Style card pour groupe */
.is-style-montheme-card {
background-color: var(--wp--preset--color--background);
border: 1px solid var(--wp--preset--color--tertiary);
border-radius: 8px;
padding: var(--wp--preset--spacing--60);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.is-style-montheme-card:hover {
transform: translateY(-4px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
/**
* Optimisations pour les performances
*/
/* Lazy loading fade-in */
img[loading="lazy"] {
opacity: 0;
transition: opacity 0.3s;
}
img[loading="lazy"].loaded {
opacity: 1;
}
/* Optimisation des polices */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('../fonts/inter-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('../fonts/inter-bold.woff2') format('woff2');
}
/* Conteneur responsive */
.wp-block-group.is-layout-constrained > * {
max-width: 100%;
}
Optimisation des performances
Chargement différé des images JavaScript
Créez assets/js/main.js :
/**
* Scripts front-end du thème
*/
(function() {
'use strict';
/**
* Lazy loading manuel pour images
*/
const lazyLoadImages = () => {
const images = document.querySelectorAll('img[loading="lazy"]');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.classList.add('loaded');
observer.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
} else {
// Fallback pour navigateurs anciens
images.forEach(img => img.classList.add('loaded'));
}
};
/**
* Smooth scroll pour les liens d'ancrage
*/
const initSmoothScroll = () => {
const links = document.querySelectorAll('a[href^="#"]');
links.forEach(link => {
link.addEventListener('click', function(e) {
const targetId = this.getAttribute('href');
if (targetId === '#') return;
const target = document.querySelector(targetId);
if (target) {
e.preventDefault();
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
// Mettre le focus sur l'élément cible (accessibilité)
target.focus();
// Mettre à jour l'URL
if (history.pushState) {
history.pushState(null, null, targetId);
}
}
});
});
};
/**
* Améliorer l'accessibilité du menu mobile
*/
const enhanceMobileMenu = () => {
const menuToggles = document.querySelectorAll('.wp-block-navigation__responsive-container-open');
menuToggles.forEach(toggle => {
toggle.addEventListener('click', function() {
const isExpanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', !isExpanded);
});
});
};
/**
* Détecter et signaler les erreurs JavaScript
*/
const setupErrorTracking = () => {
window.addEventListener('error', function(e) {
if (window.console && console.error) {
console.error('Theme Error:', e.message, e.filename, e.lineno);
}
});
};
/**
* Initialisation au chargement du DOM
*/
document.addEventListener('DOMContentLoaded', function() {
lazyLoadImages();
initSmoothScroll();
enhanceMobileMenu();
setupErrorTracking();
});
})();
Erreurs courantes à éviter
1. Oublier le support REST API
MAUVAIS : Ne pas inclure show_in_rest dans theme.json
BON : Toujours activer le support REST pour FSE
2. Hardcoder les couleurs et tailles
MAUVAIS :
.mon-element {
color: #0066cc;
font-size: 16px;
}
BON :
.mon-element {
color: var(--wp--preset--color--primary);
font-size: var(--wp--preset--font-size--medium);
}
3. Ignorer l'accessibilité
MAUVAIS : Pas de skip link, pas de focus visible
BON : Implémenter tous les standards WCAG 2.1 niveau AA minimum
4. Ne pas tester les performances
Utilisez les outils de test :
- Google PageSpeed Insights
- WebPageTest
- Lighthouse
- Query Monitor (plugin)
- Utilisez theme.json pour tous les réglages de design
- Créez des templates HTML avec des blocs
- Implémentez des block patterns réutilisables
- Respectez les standards WCAG 2.1 niveau AA
- Optimisez les performances (lazy loading, préchargement de polices)
- Utilisez des variables CSS natives de WordPress
- Testez sur différents navigateurs et appareils
- Block Theme Documentation
- Theme.json Reference
- Theme Handbook
- Accessibility Handbook
- Performance Best Practices
Conclusion
Le développement de thèmes WordPress en 2025 requiert une maîtrise du Full Site Editing, de theme.json, et une attention particulière à l'accessibilité et aux performances. Les block themes sont la direction que prend WordPress et offrent une vraie flexibilité tout en maintenant une expérience utilisateur cohérente.
Points clés à retenir :
Ressources supplémentaires
Mots-clés:* thème WordPress 2025, block theme, Full Site Editing, theme.json, WordPress FSE, développement thème WordPress, accessibilité WordPress WCAG, performances WordPress, WordPress global styles, block patterns WordPress