Styles avec et sans Javascript

Charger le javascript le plus tard possible, ou au moins de manière asynchrone, implique que le visiteur risque de voir la page avant l’exécution du dit javascript. Si le javascript enrichit ou modifie la page, le visiteur aura la désagréable surprise de voir la page se modifier sous ses yeux.

Dans un des premiers billets je vous proposais d’ajouter une classe js à la balise <body>. L’idée est de différencier dès le début du rendu si la page est destinée à un affichage avec ou sans javascript.

Ajouter une classe au <body>

Pour l’exemple je vous proposais le code suivant juste après l’ouverture de <body> :

<script type="application/javascript">
document.body.className = "js " + document.body.className ;
</script>

J’ai un problème avec ça. On m’a fait la remarque que parfois les noeuds DOM souhaités ne sont pas disponibles quand le javascript s’exécute. Le fait que la balise d’ouverture soit déjà passée n’offrirait pas de garantie à ce niveau. J’ai quand même un doute pour le document.body. Personnellement je ne l’ai pas encore vue en défaut.

Amis lecteurs, êtes-vous capables de me trouver un contre-exemple où le document.body n’est pas disponible et utilisable dès l’ouverture la balise correspondante ? Vous avez le droit à n’importe quel navigateur grade A pour vos tests, et de monter tous les scénarios tordus que vous voulez. Même un résultat aléatoire me convient. L’idée c’est de prouver que cela peut arriver, et éventuellement de cerner les situations où c’est le cas.

Ou sur le <html>

Le cas échéant il y a une seconde technique, qui est d’utiliser document.documentElement, qui logiquement fait référence au noeud <html>. Là on a la certitude de pouvoir y accéder en javascript. Les navigateurs acceptent tous de jouer avec document.documentElement.className donc cela pourrait être une solution. Le second avantage c’est que je peux lancer ma ligne de script dès le début du <head>, je n’ai plus besoin d’attendre le corps de la page pour cela.

<script type="application/javascript">
document.documentElement.className = "js " + document.documentElement.className ;
</script>

Le défaut que je vois est théorique ce coup ci. Les spécifications DOM HTML indiquent bien la présence d’un attribut className pour <html>. Cet attribut javascript sert à accéder et modifier l’attribut class de la balise. Or là il y a une incohérence puisque dans les spécifications HTML 4 et XHTML 1, la balise <html> n’a pas d’attribut class. Mon javascript est fonctionnel et respecte ses propres spécifications, mais je lui fais faire quelque chose que je sais aller à l’encontre des recommandations du format HTML.

En pratique cette seconde technique fonctionne et nos navigateurs laxistes acceptent tous de mettre des classes à <html>, que ce soit statiquement dans le code HTML ou dynamiquement via javascript. Maintenant si je pouvais éviter cela serait quand même mieux. À défaut j’attendrais HTML 5, où l’attribut class est explicitement autorisé sur <html>.

Sur ce qui doit être recommandé

Ces deux techniques ont un gros potentiel, mais j’attend votre aide pour savoir lequel je dois conseiller. Si je n’ai pas de contre-exemple pour la première solution, alors restons avec. Sinon l’utilisation de document.documentElement peut être un bon compromis.

Publié par edaspet

Plus d'informations sur mon profil en ligne

6 réponses sur « Styles avec et sans Javascript »

  1. Je n’ai jamais eu de problème en plaçant le script après body, mais je trouve plus « propre » (après, tout est subjectif) de placer cette ligne avant /body plutôt qu’après.

    Sinon pour palier pour au problème d’attribut j’utilise non pas une class mais un id sur l’élément html.

  2. Il s’agit bien de mettre juste après l’ouverture du body, pas juste après la fermeture (j’ai un doute en te lisant).

    Le gros javascript est mieux placé avant la fermeture du body, par contre les petites lignes dont je parle leur but c’est de faire en sorte que la page « ressemble à la version finale » le plus tôt possible; Si on les met à la fin de la page, le visiteur aura une page avec un style « sans CSS » (trois boites les unes au dessous des autres au lien d’un module en trois onglets par exemple) et verra la page changer complètement au bout d’un moment. C’est ce que je veux éviter.

    Utiliser un id ne changera normalement rien, si tu peux modifier l’identifiant tu peux aussi modifier la classe. Utiliser une classe permet d’être plus souple (on peut avoir plusieurs classes pour plusieurs usages, alors que mettre « js » en identifiant ne permet pas de cumuler plusieurs spécialités)

  3. Heu, oui, petite correction. Comprendre body à la place de /body dans mon précédent message.

    Pour l’id je suis d’accord, c’était juste histoire de rester cohérent avec la spec HTML. Au niveau de la souplesse c’est vrai, mais j’ai envi de dire que je n’ai jamais eu besoin de cumuler plusieurs spécialités sur l’élément HTML (contrairement à body).

  4. Je suis content de retrouver une réflexion que j’ai déjà eu. Ce qui est amusant ici, c’est que j’ai eu une démarche différente.

    Toi, tu modifie l’HTML — et visiblement cela pose quelques problèmes — pour marquer les balises html ou body, alors que moi j’ai décidé de préciser directement le CSS en ligne, puisque le JS ne modifie souvent que très peu le rendu final de la page (en cachant un élément par exemple).

    Mon billet là dessus.

    Bien sûr, ma méthode ne s’adapte pas aux cas où les changements post-JS sont très importants.

  5. Louis: ta solution est crade par contre 🙂 (document.write, en plein milieu de la page…)

    Faudrait que je teste la méthode de Eric, j’ai déjà eu des problèmes avec du JS executé un peu trop tôt et ca foirait lors des accès DOM, mais je sais plus si c’était sur body.

Les commentaires sont fermés.