Développement de thèmes
2.5.x ✅ 4.0.x ✅
Ce guide couvre la création de thèmes XOOPS, y compris la structure des thèmes, l’héritage de modèles et les meilleures pratiques pour construire des thèmes réactifs et modernes.
Documentation connexe
Section intitulée « Documentation connexe »- Smarty-Basics - Principes fondamentaux de Smarty dans XOOPS
- Template-Variables - Variables disponibles dans les modèles
- Smarty-4-Migration - Mise à niveau de Smarty 3 à 4
Structure des thèmes
Section intitulée « Structure des thèmes »Un thème XOOPS se compose de la structure de répertoire suivante:
themes/ mytheme/ theme.tpl # Modèle de thème principal theme_autorun.php # PHP exécuté automatiquement (optionnel) XOOPS_version.php # Configuration du thème css/ style.css # Feuille de style principale custom.css # Styles personnalisés images/ logo.png # Images du thème js/ custom.js # JavaScript du thème language/ english/ main.php # Chaînes de langueXOOPS_version.php
Section intitulée « XOOPS_version.php »Le fichier de configuration du thème définit les propriétés du thème:
<?php$themeversion = [ 'name' => 'My Theme', 'description' => 'A modern responsive XOOPS theme', 'version' => '1.0.0', 'author' => 'Your Name', 'author_url' => 'https://yoursite.com', 'license' => 'GPL-2.0', 'credits' => 'Based on Bootstrap 5', 'parent' => '', // Parent theme name for inheritance 'screenshots' => [ 'screenshot.png', ], 'features' => [ 'responsive' => true, 'rtl' => false, ],];Structure de base de theme.tpl
Section intitulée « Structure de base de theme.tpl »<!DOCTYPE html><html lang="<{$xoops_langcode}>"><head> <meta charset="<{$xoops_charset}>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><{$xoops_pagetitle}></title>
<{* Meta tags *}> <meta name="description" content="<{$xoops_meta_description}>"> <meta name="keywords" content="<{$xoops_meta_keywords}>"> <meta name="robots" content="<{$xoops_meta_robots}>"> <meta name="author" content="<{$xoops_meta_author}>"> <meta name="generator" content="XOOPS">
<{* CSS files *}> <link rel="stylesheet" href="<{$xoops_themecss}>"> <link rel="stylesheet" href="<{$xoops_url}>/themes/<{$xoops_theme}>/css/custom.css">
<{* Additional head content *}> <{$xoops_module_header}></head>
<body> <{* Header *}> <header> <div class="container"> <a href="<{$xoops_url}>"> <img src="<{$xoops_imageurl}>images/logo.png" alt="<{$xoops_sitename}>"> </a> <h1><{$xoops_sitename}></h1> </div> </header>
<{* Navigation *}> <nav> <{$xoops_mainmenu}> </nav>
<{{* Contenu principal *}> <main class="container"> <{{* Blocs de gauche *}> <{{if $xoops_showlblock}> <aside class="left-blocks"> <{{foreach item=block from=$xoops_lblocks}> <{{include file="db:system_block_$block.template" block=$block}> <{{/foreach}> </aside> <{{/if}>
<{{* Contenu principal *}> <div class="content"> <{{$xoops_contents}> </div>
<{{* Blocs de droite *}> <{{if $xoops_showrblock}> <aside class="right-blocks"> <{{foreach item=block from=$xoops_rblocks}> <{{include file="db:system_block_$block.template" block=$block}> <{{/foreach}> </aside> <{{/if}> </main>
<{{* Pied de page *}> <footer> <div class="container"> <p>© <{{$smarty.now|date_format:"%Y"}}> <{{$xoops_sitename}}</p> <{{$xoops_footer}> </div> </footer>
<{{* JavaScript *}> <script src="<{{$xoops_url}}/themes/<{{$xoops_theme}}/js/custom.js"></script> <{{$xoops_js}></body></html>Héritage de modèle
Section intitulée « Héritage de modèle »L’héritage de modèle Smarty vous permet de créer des thèmes enfants qui héritent d’un thème parent.
Thème parent (base.tpl)
Section intitulée « Thème parent (base.tpl) »<!DOCTYPE html><html><head> <title>{block name=title}{/block} - <{$xoops_sitename}></title> {block name=head_css} <link rel="stylesheet" href="<{$xoops_themecss}>"> {/block}</head><body> {block name=header} <header> <h1><{$xoops_sitename}></h1> </header> {/block}
{block name=content} <main> <{$xoops_contents}> </main> {/block}
{block name=footer} <footer> <p>© <{$smarty.now|date_format:"%Y"}></p> </footer> {/block}</body></html>Thème enfant (theme.tpl)
Section intitulée « Thème enfant (theme.tpl) »{extends file="db:parenttheme/theme.tpl"}
{block name=title}My Custom Title{/block}
{block name=head_css} {$smarty.block.parent} {* Inclure le CSS parent *} <link rel="stylesheet" href="<{$xoops_url}>/themes/childtheme/css/custom.css">{/block}
{block name=header} <header class="custom-header"> <div class="logo"> <img src="<{$xoops_imageurl}>images/logo.png" alt="Logo"> </div> <nav class="main-nav"> <{$xoops_mainmenu}> </nav> </header>{/block}Création de variations de thème
Section intitulée « Création de variations de thème »Créez plusieurs variations de thème à partir d’un thème de base:
xbootstrap-green/theme.tpl:
{extends file="db:xbootstrap/theme.tpl"}
{block name=css}<link rel="stylesheet" href="<{$xoops_url}>/themes/xbootstrap-green/css/green.css">{/block}xbootstrap-green/XOOPS_version.php:
<?php$themeversion = [ 'name' => 'xbootstrap-green', 'parent' => 'xbootstrap', // ... other settings];theme_autorun.php
Section intitulée « theme_autorun.php »Ce fichier est exécuté automatiquement et peut être utilisé pour préparer les données pour les modèles:
<?php/** @var XoopsTpl $xoopsTpl */global $xoopsTpl;
if (!empty($xoopsTpl)) { // Add configuration directory $xoopsTpl->addConfigDir(__DIR__);}
// Include module autoloader if neededif (file_exists(XOOPS_ROOT_PATH . '/modules/publisher/preloads/autoloader.php')) { require XOOPS_ROOT_PATH . '/modules/publisher/preloads/autoloader.php';}
use XoopsModules\Publisher\Helper;use XoopsModules\Publisher\Constants;
/** * Fetch items for theme display */function getPublisherItems($limit, $sort = 'RAND()', $order = ''){ $helper = Helper::getInstance(); $itemsObj = $helper->getHandler('Item')->getItems( $limit, 0, // start [Constants::PUBLISHER_STATUS_PUBLISHED], -1, // categoryid $sort, $order );
$items = []; if ($itemsObj) { foreach ($itemsObj as $itemObj) { $newItem = [ 'itemid' => $itemObj->itemid(), 'title' => $itemObj->title(), 'body' => $itemObj->body(), 'votes' => $itemObj->votes(), 'counter' => $itemObj->counter(), 'image' => XOOPS_URL . '/uploads/blank.gif', ];
$images = $itemObj->getImages(); if (isset($images['main']) && is_object($images['main'])) { $newItem['image'] = XOOPS_URL . '/uploads/' . $images['main']->getVar('image_name'); }
$items[] = $newItem; } } return $items;}
// Assign data to templates$xoopsTpl->assign('sliderItems', getPublisherItems(9));$xoopsTpl->assign('featuredItems', getPublisherItems(3));$xoopsTpl->assign('latestItems', getPublisherItems(4));$xoopsTpl->assign('xoops_url', XOOPS_URL);Utilisation de Bootstrap
Section intitulée « Utilisation de Bootstrap »Un exemple de thème Bootstrap 5:
<!DOCTYPE html><html lang="<{$xoops_langcode}>"><head> <meta charset="<{$xoops_charset}>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><{$xoops_pagetitle}></title>
{* Bootstrap CSS *} <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="<{$xoops_url}>/themes/<{$xoops_theme}>/css/custom.css">
<{$xoops_module_header}></head><body> {* Navigation *} <nav class="navbar navbar-expand-lg navbar-light bg-light"> <div class="container"> <a class="navbar-brand" href="<{$xoops_url}>"> <{$xoops_sitename}> </a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <{$xoops_mainmenu}> </div> </div> </nav>
{* Main content *} <div class="container my-4"> <div class="row"> {* Left sidebar *} <{{if $xoops_showlblock}> <div class="col-lg-3"> <{{foreach item=block from=$xoops_lblocks}> <div class="card mb-3"> <div class="card-header"><{{$block.title}}</div> <div class="card-body"><{{$block.content}}</div> </div> <{{/foreach}> </div> <{{/if}>
{* Main content area *} <div class="col-lg-<{{if $xoops_showlblock && $xoops_showrblock}>6<{{elseif $xoops_showlblock || $xoops_showrblock}>9<{{else}>12<{{/if}>"> <{{$xoops_contents}> </div>
{* Right sidebar *} <{{if $xoops_showrblock}> <div class="col-lg-3"> <{{foreach item=block from=$xoops_rblocks}> <div class="card mb-3"> <div class="card-header"><{{$block.title}}</div> <div class="card-body"><{{$block.content}}</div> </div> <{{/foreach}> </div> <{{/if}> </div> </div>
{* Footer *} <footer class="bg-dark text-white py-4 mt-auto"> <div class="container text-center"> <p class="mb-0">© <{$smarty.now|date_format:"%Y"}> <{$xoops_sitename}></p> <{$xoops_footer}> </div> </footer>
{* Bootstrap JS *} <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <{$xoops_js}></body></html>Modèles de bloc
Section intitulée « Modèles de bloc »Créez des modèles de bloc personnalisés:
{* themes/mytheme/templates/system_block.tpl *}<div class="block"> <{{if $block.title}> <h3 class="block-title"><{{$block.title}}</h3> <{{/if}> <div class="block-content"> <{{$block.content}> </div></div>Carrousel/curseur personnalisé
Section intitulée « Carrousel/curseur personnalisé »Exemple d’un carrousel de contenu dynamique:
{* Slider using theme_autorun.php data *}<{{if $sliderItems}><div class="owl-carousel owl-theme"> <{{foreach item=item from=$sliderItems}> <div class="owl-carousel-info-wrap item"> <img src="<{{$item.image}}" class="owl-carousel-image img-fluid" alt="<{{$item.title}>">
<div class="owl-carousel-info"> <h4 class="mb-2"> <a href="<{{$xoops_url}>/modules/publisher/item.php?itemid=<{{$item.itemid}>"> <{{$item.title|truncate:15}> </a> </h4> <span class="badge">Reads: <{{$item.counter}}</span> <span class="badge">Votes: <{{$item.votes}}</span> </div> </div> <{{/foreach}></div><{{/if}>Conseils de conception réactive
Section intitulée « Conseils de conception réactive »CSS mobile-first
Section intitulée « CSS mobile-first »/* Base styles for mobile */.content { width: 100%; padding: 1rem;}
/* Tablet and up */@media (min-width: 768px) { .content { width: 75%; padding: 2rem; }}
/* Desktop and up */@media (min-width: 1024px) { .content { width: 60%; padding: 3rem; }}Affichage conditionnel de bloc
Section intitulée « Affichage conditionnel de bloc »{* Hide blocks on mobile using CSS classes *}<{{if $xoops_showlblock}><aside class="left-blocks d-none d-lg-block"> <{{foreach item=block from=$xoops_lblocks}> <{{include file="db:system_block.tpl" block=$block}> <{{/foreach}></aside><{{/if}>Meilleures pratiques
Section intitulée « Meilleures pratiques »Utiliser le HTML sémantique
Section intitulée « Utiliser le HTML sémantique »<header>...</header><nav>...</nav><main>...</main><aside>...</aside><footer>...</footer>Optimiser les actifs
Section intitulée « Optimiser les actifs »{* Defer non-critical JavaScript *}<script src="script.js" defer></script>
{* Async for independent scripts *}<script src="analytics.js" async></script>Accessibilité
Section intitulée « Accessibilité »{* Use proper ARIA labels *}<nav aria-label="Main navigation"> <{$xoops_mainmenu}></nav>
{* Provide alt text for images *}<img src="<{$item.image}>" alt="<{$item.title|escape}>">
{* Skip links for keyboard navigation *}<a href="#main-content" class="skip-link">Skip to content</a>Performance
Section intitulée « Performance »{* Lazy load images *}<img src="<{$item.image}>" loading="lazy" alt="<{$item.title}>">
{* Preload critical resources *}<link rel="preload" href="fonts/custom.woff2" as="font" type="font/woff2" crossorigin>#themes #smarty #xoops #css #design #responsive