Créer des CSS dynamiques avec PHP sans LessCSS ou SCSS…

Mathieu Chartier Programmation 7 commentaires

Il m'a fallu un moment avant de reprendre le temps de rédiger un article sur ce blog, j'ai beaucoup travaillé sur mon moteur de recherche PHP et sur mes extensions WordPress comme Advanced Search ou Excerpt Generator, ce qui ne m'a pas laissé beaucoup de temps pour revenir vers vous. Comme j'ai la tête dans le code PHP en ce moment, je vous propose un article sur la création de feuilles de style CSS avec PHP.

Pourquoi ne pas le faire avec les préprocesseurs CSS ?

La tendance actuelle du web est de diriger le CSS vers la création de feuilles de style dynamiques avec des préprocesseurs toujours plus nombreux. Tout a commencé avec SASS/SCSS puis des concurrents tels que LessCSS, Stylus, CSS Crush ou encore Closure de Google et depuis, tout le monde ne parle plus que de ça... Certes, l'envie de créer des CSS dynamiques n'est pas nouvelle, mais je vous avoue que je ne comprends pas totalement l'engouement pour ces meta-langages créés de toutes pièces alors que nous pouvons faire la même chose plus facilement avec du simple PHP...

Pour être tout-à-fait honnête avec vous, j'apprécie quand même les préprocesseurs CSS comme LessCSS ou Stylus pour ne nommer qu'eux, la syntaxe est très simple et il suffit de quelques heures de pratique pour générer des feuilles CSS complexes et abouties. Toutefois, mon principal reproche est de devoir faire appel à des installations parfois "bancales" avec des parseurs PHP ou Javascript qui compilent le code créé un peu quand ils le souhaitent. LessCSS permet également de compiler avec Javascript directement côté client, c'est avantageux mais cela demande davantage de chargement si la feuille est longue et complexe...

En d'autres termes, les préprocesseurs CSS sont plutôt de bons outils, mais il faut vraiment y aller avec des pincettes pour faire de bonnes choses. L'idéal est sûrement de créer ses propres feuilles SCSS ou Less (exemple ci-dessous), de les convertir en CSS avec des outils en ligne puis d'envoyer une copie convertie sur les hébergeurs, mais cela fait pas mal de démarche pour obtenir un CSS dynamiques. Nous allons voir que la technique avec PHP est bien plus efficace et directe, et surtout bien plus complète si elle est bien pensée dès le départ...

CSS dynamique : variable avec Less CSS

Est-il plus avantageux de créer des CSS dynamiques avec PHP ?

Nous pouvons légitimement nous demander pourquoi les préprocesseurs CSS ont été créés si PHP permet de faire également des CSS dynamiques. Ma réponse est simple : je n'en sais rien du tout... Plus sérieusement, l'avantage des préprocesseurs CSS est de pouvoir compiler le code dynamiquement côté serveur mais aussi côté client quand on le souhaite, ce qui peut s'avérer pratique dans certains cas. De plus, ils offrent des écritures simplifiées et relativement pratiques pour faire de l'héritage de sélecteurs ou classes CSS, c'est très pratique et plutôt bien pensé pour conserver une logique de code même dans les feuilles de style (ce qui est souvent reproché au CSS classique).

En réalité, PHP nous permet aussi de faire de l'héritage si nous le souhaitons, il suffit de coder quelques fonctions ou quelques class en PHP objet pour obtenir de tels résultats, mais pour cela, ce sont vos petits doigts qui devront le faire... De plus l'avantage de créer des CSS dynamiques avec PHP est de pouvoir relier cela à des boutons d'actions voire à des bases de données si nécessaire (qui sait...^^). Il est également bien plus simple de coder dans un langage qu'on maîtrise plutôt que d'apprendre encore des mini-langages de niches, bien que les exemples comme SCSS ou Stylus soient plutôt "simples". Enfin, et je parle en connaissance de cause, il est bien plus agréable de passer uniquement par PHP côté serveur plutôt que d'ajouter des couches et sous-couches d'actions avec les parseurs, les compilateurs et tout ce qui va avec, notamment quand la compatibilité n'est pas au rendez-vous (petite pensée pour SCSS qui fonctionne une fois sur deux dans mes projets, selon le navigateur...).

Enfin, sachez que le W3C réfléchit déjà à l'élaboration de feuilles de styles CSS dynamiques avec des variables comme dans les autres langages de programmation. Il s'agit d'un document de travail du 29 octobre 2013 mais cela laisse rêveur. Pour résumer, il sera possible de créer des variables en ajoutant le préfixe "var-" puis en appelant dans la propriété CSS la variable créée avec la fonction "var(nomVariable);"... Le W3C réfléchit également à une fonction @supports et un système conditionnel utilisé dans certains cas comme le prouve la documentation brouillon du 9 novembre 2013. En d'autres termes, peut-être que les préprocesseurs CSS ou la technique qui va suivre

Comment procéder pour créer des CSS dynamiques avec PHP ?

Rien de plus simple en vérité... Voici la méthode complète pour créer des CSS dynamiques avec PHP, cela va même peut-être vous faire mal de savoir que c'était aussi facile si vous ne l'avez jamais tenté :

  1. Créer une feuille de style "style.php" par exemple ;
  2. Ajouter le code suivant en haut du fichier créé : <?php header("Content-type: text/css; charset=UTF-8"); ?>
  3. Appeler le fichier "style.php" dans le HEAD de votre page web avec la balise <link rel="stylesheet" href="style.php" />

Voilà, c'est tout, il suffit ensuite d'ajouter du code avec le header() du fichier "style.php" pour générer des variables (voir exemple ci-dessous). Je vous fournis quelques fonctions par la suite pour avoir une idée de ce que nous pouvons faire avec PHP pour gagner du temps. N'hésitez pas à partager vos idées si vous en avez, tout est bon à prendre pour que nous évoluions tous ensemble !

<?php
header("Content-type: text/css; charset=UTF-8");

$couleur = '#242424';
$largeur = "50%";
?>
body {
   background-color:<?php echo $couleur; ?>;
}
.maClass {
   width:<?php echo $largeur; ?>;
}

Si vous voulez améliorer les performances, vous pouvez également ajouter les lignes "ob_start('ob_gzhandler');" ou encore "header('Cache-Control: max-age=31536000, must-revalidate');" par exemple, il suffit de les coller juste avant ou juste après le "header("Content-type: text/css; charset=UTF-8");" pour que cela fonctionne bien...

Quelques fonctions d'exemples

Créer ses CSS dynamiques est avantageux mais si nous nous limitons à créer des variables, l'intérêt tombe rapidement à l'eau, surtout que l'écriture pourra paraître "lourde" et le gain de temps réduit. Le plus intéressant est de créer des fonctions qui nous font gagner du temps. Je ne suis pas là pour tout vous fournir mais voici quelques idées de fonctions qui "gagnent" du temps, n'hésitez à créer vos propres fonctions CSS en PHP...

/*----------------------------------------------------------------*/
/*-- Fonction qui permet de créer une grille CSS rapidement --*/
/*----------------------------------------------------------------*/
function creerGrille($nomClass = "class", $nbClass = 20, $baseWidth = 100, $uniteWidth = "%") {
	if($uniteWidth == "%") {
		$coefficientWidth = 100/$nbClass;
	} else {
		$coefficientWidth = $baseWidth/$nbClass;
	}

	for($i=1; $i < $nbClass+1; $i++) {
		$width = ceil($i * $coefficientWidth);
		echo ".".$nomClass."-".$i." { width:".$width.$uniteWidth."; }\n";
	}	
}

// Fonction qui génère un reset CSS simple (à appeler au début)
function resetCSS() {
	echo "* { margin:0; padding:0; font-size:100%; border:0; font-style:normal; font-weight:normal; }\n";
}

// Fonction qui créé la class .clear pour contrer les float
function clearCSS($nomClass = "clear") {
	echo ".".$nomClass." { clear:both; }\n";
}

/*---------------------------------------------------*/
/*-- Fonction pour générer la propriété "border" --*/
/*---------------------------------------------------*/
function borderCSS($direction = array(), $couleur = "#000", $width = "1px", $type = "solid") {
	if(empty($direction) && (!in_array("top", $direction) || !in_array("bottom", $direction) || !in_array("left", $direction) || !in_array("right", $direction))) {
		echo "border:".$width." ".$type." ".$couleur.";";
	} else {
		foreach($direction as $trbl) {
			echo "border-".$trbl.":".$width." ".$type." ".$couleur."; ";		
		}
	}
}

Il suffit d'appeler ces fonctions simplement avec des codes PHP :

  • <?php resetCSS(); ?>
  • <?php clearCSS(); ?>
  • <?php creerGrille("item", 10, 960, "px"); // pour créer 10 class de layout (.item-1, .item-2, etc.) jusqu'à 960px de largeur ?>
  • <?php borderCSS($array("top", "left")); // pour créer border-top et border-left, etc. ?>

De même, vous pouvez tout à fait créer une fonction simple qui permet d'ajouter les préfixes utiles en cas de besoin (bien que des outils comme PrefixFree ou PrefixR le fassent très bien), comme la fonction suivante :

function prefixesCSS($tableauProprietes = array()) {
	$result = "";
	foreach($tableauProprietes as $propriete => $valeur) {
		$result .= $propriete.":".$valeur.";\n";
		$result .= "-moz-".$propriete.":".$valeur.";\n";
		$result .= "-webkit-".$propriete.":".$valeur.";\n";
		$result .= "-o-".$propriete.":".$valeur.";\n";
		$result .= "-ms-".$propriete.":".$valeur.";\n";
		$result .= "-khtml-".$propriete.":".$valeur.";\n";
	}
	return $result;
}

/*
Elle peut s'utiliser ainsi :
$tableauProprietes = array(
	"transform" => "rotate(45deg)",
	"box-shadow" => "10px 10px 5px #888"
);
echo ".maClass {\n".prefixesCSS($tableauProprietes)."}";
*/

7 commentaires

  • Enguerran dit :

    Hum...
    "petite pensée pour SCSS qui fonctionne une fois sur deux dans mes projets, selon le navigateur", "mon principal reproche est de devoir faire appel à des installations parfois "bancales" avec des parseurs PHP ou Javascript qui compilent le code créé un peu quand ils le souhaitent".

    Ces deux affirmations me font juste penser à une mauvaise configuration du compilateur Less ou Sass. Comment un programme pourrait compiler "quand il le veut" et générer un code pas compatible d'un navigateur (à moins bien sûr que le code qu'on lui donne ne soit pas bon)?

    Par ailleurs, un petit tour sur Compass permet d'étendre encore les fonctionnalités de Sass et de pouvoir, entre autre, disposer d'un (bon) reset css. Parce que le * {margin:0; padding:0; etc.}, ce n'est plus d'actualité (si ça l'a déjà été).

    • Non Enguerran, j'insiste et je persiste (lire les "issues" de SCSS notamment) que le compilateur ne fonctionne pas bien en local sur tous les navigateurs (seulement Firefox et Safari), il faut passer par un serveur pour que la compilation devienne fonctionnelle sur tous les navigateurs. La configuration est simple puisqu'il s'agit de recopier 4-5 lignes de code toutes bêtes, donc aucun problème de ce côté là, je ne suis pas idiot à ce point (enfin je l'espère... :D).

      Concernant Sass, on peut effectivement passer par des surcouches supplémentaires comme Compass, etc. Après, ça devient une machine de guerre pour... compiler du CSS. Le principe est bien, c'est ce que je mentionne tout au long de l'article, donc j'approuve les préprocesseurs CSS, mais je relativise. C'est typiquement la même chose avec les grilles CSS, les frameworks, etc. Ce sont de bonnes aides, mais ça ne remplace (rarement) le code "fait main" avec propreté. Cela a le mérite d'exister et de servir à certaines personnes, c'est tant mieux, mais perso, je ne vais clairement pas installer un Sass+Compass alors que je peux faire la même chose en PHP (le langage le plus rapide du web, il ne faut pas l'oublier !).

      Enfin, pour les reset CSS fait en carton, je peux te citer le Reset HTML 5 fourni par Yahoo! qui est truffé d'incohérences par exemple (et ce n'est qu'un exemple parmi tant d'autres), même si c'est toujours mieux que l'étoile universelle bien entendu (cela évite quelques surcharges serveurs notamment). Toutefois, l'étoile n'est pas une faute, c'est juste moins optimisé, il faut nuancer la chose...

  • Enguerran dit :

    Ce que je veux dire et qui est clairement pas le cas en lisant cet article : les préprocesseurs CSS sont une interface supplémentaires, qui, bien utilisés, permettent à la personne qui l'utilise, d'avoir le même code CSS que si elle l'avait fait "à la main", mais plus rapidement (au final, ce ne sont que des raccourcis). Pour ça, il faut connaître et maîtriser ces outils. Mais c'est comme toutes les technos, si on en utilise sans connaître l'action et le résultat attendu, on obtient des choses que l'on attendait pas.

    J'utilise Scss (syntaxe Sass, parfois Scss) + Compass, compilé en local via le compilateur de base (Ruby) pour la mise en ligne, c'est le plus souvent déployé via Git ou SVN. Jamais moi, ni aucun de mes collaborateurs sur aucun projet depuis 1 an et demi que je l'utilise, n'avons remonté de problèmes de compatibilité entres navigateurs (pas plus qu'avec une feuille CSS faite "à la main", mais ça ne vient pas de Sass ni de Compass, qui comme dit plus haut, ne sont que des raccourcis), ni de problèmes de compilations non désirées.

    C'est vraiment une question en fait, c'est vrai que c'est la première fois que j'entends parler de problème de ce genre.

    • J'avoue en toute honnêteté que j'ai été surpris par ces problèmes. En fait, si on utilise Wamp ou EasyPHP, le problème est "réglé" via localhost, mais si on ouvre le fichier nativement (hors localhost), le problème est présent sur plusieurs navigateurs (seulement pour SCSS et Sass, pas pour LessCSS). Après je suis d'accord sur les outils, c'est quand même pratique et j'ai apprécié l'utilisation des préprocesseurs, même si ça fait un peu usine à gaz pour pas grand chose par moment (tout dépend le projet bien entendu).
      Il faut que je gratte davantage Stylus qui me semble vraiment pas mal en tout cas, plus poussé que les autres (bien que Sass+Compass soit une très bonne solution).

  • GeekPress dit :

    "Nous pouvons légitimement nous demander pourquoi les préprocesseurs CSS ont été créés si PHP permet de faire également des CSS dynamiques. "

    Pour une question de performance !

    Compiler ses fichiers via PHP est une technique à oublier et ne jamais utiliser !
    Ce n'est pas à l'utilisateur de devoir subir tous les traitements PHP pour la gestion des variables et des fonctions de vos feuilles de style.

    Cela doit être fait par un compilateur ou avant de fournir le fichier CSS. Le visiteur subit déjà assez de traitements pour qu'on lui inflige quelques uns supplémentaires qui peuvent être éviter en toute simplicité.

    • Je suis d'accord sur ce point, mais il persiste un problème qui explique pourquoi j'ai dit ça...
      La plupart des préprocesseurs CSS impliquent des compilateurs côté serveurs en Ruby ou PHP qui compilent à la volée, et non pas en amont ! De ce fait, il y a également un traitement PHP mais pour compiler du code. En revanche, ma technique ne fait qu'un "include" PHP, la demande de performance est donc plus limitée sachant que PHP reste le langage le plus rapide du marché (sur le web tout du moins).

      L'autre problème que je me pose toujours, c'est de voir que tout le monde donne des leçons de performances mais que la plupart des développeurs passent par des frameworks avec un code dégueulasse, lourd (et souvent long à charger), avec des extensions qui demandent des traitements (...), et pourtant, ce sont les premiers à conseiller les autres de ne pas faire ça. J'en suis réduit à un point où certains CMS me font "peur" tant ils génèrent des codes souvent inutiles et tant les extensions sont peu optimisées (je ne dis pas que mes extensions WordPress le sont, c'est dire !). Nous sommes dans la folie de la performance mais balayons bien devant notre porte et regardons si nous n'utilisons pas des outils peu adéquats... :D

  • Merci pour cet astuce, j'ai bien enregistré ce code d'exemple car il est peut être utile un jour

  • Déposer un commentaire

    Répondre à Mathieu Chartier Annuler la réponse

    L'adresse de messagerie ne sera pas publiée.* Champs obligatoires