17 mars 2024 · Tommy Bordas

Créer un thème WordPress moderne avec Tailwind CSS et Vite

wordpresstailwindperformancetheme

La création de thèmes WordPress modernes nécessite des outils adaptés aux exigences actuelles. Je partage ici mon approche pour créer des thèmes performants et maintenables avec Tailwind CSS et Vite.

Architecture du thème

1. Structure de base optimisée

theme/
├── assets/
│   ├── css/
│   │   └── app.css
│   └── js/
│       └── app.js
├── inc/
│   ├── customizer.php
│   ├── helpers.php
│   └── setup.php
├── templates/
│   ├── components/
│   └── partials/
├── package.json
├── tailwind.config.js
└── vite.config.js

2. Configuration Tailwind optimisée

// tailwind.config.js
module.exports = {
  content: [
    './templates/**/*.php',
    './inc/**/*.php',
    './assets/js/**/*.js'
  ],
  theme: {
    extend: {
      colors: {
        'wp-admin': '#2271b1',
        'wp-link': '#0073aa'
      },
      typography: {
        DEFAULT: {
          css: {
            'max-width': '65ch',
            color: 'inherit'
          }
        }
      }
    }
  },
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms')
  ]
};

3. Intégration Vite pour le développement

// vite.config.js
export default {
  build: {
    manifest: true,
    outDir: 'dist',
    rollupOptions: {
      input: {
        app: '/assets/js/app.js',
        admin: '/assets/js/admin.js'
      }
    }
  },
  plugins: [
    {
      name: 'php',
      handleHotUpdate({ file, server }) {
        if (file.endsWith('.php')) {
          server.ws.send({ type: 'full-reload' });
        }
      }
    }
  ]
};

Composants réutilisables

1. Système de cartes flexible

// templates/components/card.php
function get_card($args = []) {
    $defaults = [
        'title' => '',
        'image' => '',
        'excerpt' => '',
        'link' => '',
        'classes' => ''
    ];
    
    $props = wp_parse_args($args, $defaults);
    
    ob_start(); ?>
    <article class="bg-white rounded-lg shadow-lg overflow-hidden <?php echo esc_attr($props['classes']); ?>">
        <?php if ($props['image']) : ?>
            <img src="<?php echo esc_url($props['image']); ?>" 
                 alt="<?php echo esc_attr($props['title']); ?>"
                 class="w-full h-48 object-cover"
                 loading="lazy">
        <?php endif; ?>
        
        <div class="p-6">
            <h3 class="text-xl font-semibold mb-2">
                <?php echo esc_html($props['title']); ?>
            </h3>
            
            <?php if ($props['excerpt']) : ?>
                <p class="text-gray-600 mb-4">
                    <?php echo wp_kses_post($props['excerpt']); ?>
                </p>
            <?php endif; ?>
            
            <?php if ($props['link']) : ?>
                <a href="<?php echo esc_url($props['link']); ?>" 
                   class="inline-block bg-primary-600 text-white px-4 py-2 rounded-lg hover:bg-primary-700 transition-colors">
                    Lire la suite
                </a>
            <?php endif; ?>
        </div>
    </article>
    <?php
    return ob_get_clean();
}

2. Navigation responsive

// templates/partials/navigation.php
<nav x-data="{ open: false }" class="bg-white shadow-lg">
    <div class="max-w-7xl mx-auto px-4">
        <div class="flex justify-between h-16">
            <!-- Logo -->
            <div class="flex-shrink-0 flex items-center">
                <?php if (has_custom_logo()) : ?>
                    <?php the_custom_logo(); ?>
                <?php else : ?>
                    <a href="<?php echo esc_url(home_url('/')); ?>" class="text-xl font-bold">
                        <?php bloginfo('name'); ?>
                    </a>
                <?php endif; ?>
            </div>

            <!-- Menu principal -->
            <?php
            wp_nav_menu([
                'theme_location' => 'primary',
                'container' => false,
                'menu_class' => 'hidden md:flex space-x-8',
                'fallback_cb' => false,
                'items_wrap' => '<ul class="%2$s">%3$s</ul>',
                'walker' => new TailwindMenuWalker()
            ]);
            ?>

            <!-- Bouton mobile -->
            <button @click="open = !open" class="md:hidden">
                <span class="sr-only">Menu</span>
                <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                    <path x-show="!open" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
                    <path x-show="open" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
                </svg>
            </button>
        </div>
    </div>

    <!-- Menu mobile -->
    <div x-show="open" class="md:hidden">
        <?php
        wp_nav_menu([
            'theme_location' => 'primary',
            'container' => false,
            'menu_class' => 'px-2 pt-2 pb-3 space-y-1',
            'fallback_cb' => false
        ]);
        ?>
    </div>
</nav>

Optimisations de performance

1. Chargement des assets

function theme_enqueue_assets() {
    $manifest = json_decode(
        file_get_contents(get_template_directory() . '/dist/manifest.json'),
        true
    );

    wp_enqueue_style(
        'theme-styles',
        get_template_directory_uri() . '/dist/' . $manifest['app.css'],
        [],
        null
    );

    wp_enqueue_script(
        'theme-scripts',
        get_template_directory_uri() . '/dist/' . $manifest['app.js'],
        [],
        null,
        true
    );
}
add_action('wp_enqueue_scripts', 'theme_enqueue_assets');

2. Optimisation des images

add_theme_support('post-thumbnails');
add_image_size('card-thumb', 800, 600, true);
add_image_size('hero', 1920, 1080, true);

function optimize_image_sizes($sizes) {
    unset($sizes['medium_large']);
    return $sizes;
}
add_filter('intermediate_image_sizes_advanced', 'optimize_image_sizes');

Intégration Gutenberg

1. Styles personnalisés

function theme_gutenberg_styles() {
    add_theme_support('editor-styles');
    add_editor_style('dist/editor.css');
    
    add_theme_support('custom-spacing');
    add_theme_support('custom-units');
    add_theme_support('appearance-tools');
}
add_action('after_setup_theme', 'theme_gutenberg_styles');

2. Blocs personnalisés

function register_custom_blocks() {
    register_block_type('theme/cta', [
        'editor_script' => 'theme-blocks',
        'render_callback' => function($attributes) {
            return sprintf(
                '<div class="wp-block-theme-cta bg-primary-100 p-8 rounded-lg">
                    <h2 class="text-2xl font-bold mb-4">%s</h2>
                    <p class="mb-6">%s</p>
                    <a href="%s" class="btn btn-primary">%s</a>
                </div>',
                esc_html($attributes['title']),
                esc_html($attributes['content']),
                esc_url($attributes['link']),
                esc_html($attributes['buttonText'])
            );
        }
    ]);
}
add_action('init', 'register_custom_blocks');

Résultats

Les thèmes créés avec cette architecture obtiennent :

  • Score PageSpeed > 95
  • Temps de chargement < 1s
  • Excellente maintenabilité
  • Support complet de Gutenberg

Conclusion

Cette approche moderne de création de thèmes WordPress combine le meilleur des outils actuels pour un résultat optimal. Si vous cherchez à moderniser votre thème WordPress ou à en créer un nouveau, je peux vous accompagner dans cette démarche.