5568 sujets

Sémantique web et HTML

Bonjour à tous,

Avant de rentrer dans le vif du sujet, voici ma situation :
Je compte développer un petit plugin de post-loading pour jquery.

La première solution à laquelle j'ai pensé était d'enlever les sources des images dès que le DOM est prêt, et de les remettre après le chargement de la page. Le problème est que les navigateurs commencent à télécharger les images avant que le DOM soit prêt : Le fait d'enlever les sources au plus tôt côté client ne change rien.

Bref, la ou je veux en venir c'est que pour que cela fonctionne, il faut que le document html possède des sources d'images vide, et les remplir ensuite côté client.

Ma question est donc : dans quel attribut de l'image autre que src pourrais-je spécifier l'URL à insérer dans la source? (évidemment en respectant au mieux la sémantique HTML)

J'ai pensé au longdesc par exemple :
<img class="postLoad" src="" alt="textalt" longdesc="postLoad.txt?src=http://url-image.png" />


Où le fichier postLoad.txt contiendrait une phrase du genre : "Ceci est une image chargée après la page, activez le javascript pour optimiser blablabla..."

Le paramètre src de l'url du longdesc servirait juste au script pour remplir l'attribut src de l'image après le chargement de la page.

Qu'en pensez vous?

Concernant l'accessibilité vous semble t-il correct d'ajouter la même image entre <noscript></noscript> en dessous?

PS : Je ne sais pas vraiment si je poste au bon endroit (Javascript? Sémantique? Accessibilité?)
Modifié par Mathieu33 (31 Mar 2010 - 13:08)
Yep je connais ce plugin je l'ai déjà vu et je compte bien m'en inspirer. Le problème justement c'est que j'ai essayé la démo, et ca ne fonctionne pas : Les images sont chargées en intégralité avant la fin du chargement et non après.
(vérifié avec firebug)

Le problème de ce plugin vient du fait que les sources des images sont renseignées dans la page html : Les attributs src sont vidés/remplacés dès que le dom et prêt mais le navigateur télécharge déjà les images. (peut être qu'avant cela fonctionnait, mais pas avec les dernières versions des navigateurs en tout cas)

Il faut donc obligatoirement avoir la source vide dans le html, puis la renseigner par le script
Modifié par Mathieu33 (24 Mar 2010 - 00:01)
Ne prends pas un attribut existant comme longdesc pour l'utiliser de façon détournée. Ca peut occasionnellement poser des problèmes d'accessibilité... notamment si tu choisis longdesc, mais c'est pareil si tu en prends un autre.

En HTML 4 pur et dur, il n'y a pas de solution simple. En HTML 5, tu peux par contre te servir des attributs data. Ca marche déjà avec tous les navigateurs y compris IE6 si tu récupères la valeur de l'attribut avec getAttribute. Par contre, évidemment, c'est pas valide W3C, mais c'est pas si grave si c'est la seule erreur. C'est moins grave d'inventer un attribut que d'en utiliser un pour autre chose que ce pour quoi il a été prévu.
Hello, merci pour ta réponse.
Je ne connaissais pas cet attribut de l'HTML5 qui semble très pratique et tout à fait adapté à ce que je cherche, merci beaucoup Smiley smile

Concernant le fait de dupliquer chaque image devant être post-loadée dans une balise noscript en dessous ca ne pose pas de problème? (les images post-load étant en "visible:none" sans action du javascript)
Sisi, les mêmes :

Je n'ai pas du être très clair. Au final, voici le code HTML que je mettrais en place pour une image post-loadée :


<img class="postLoad" src="" data-plsrc="url/image.png" alt="textalt" />
<noscript><img src="url/image.png" alt="textalt" /></noscript>


La classe post-load ayant en propriété display:none;

Si l'utilisateur a le javascript : On remplie l'attribut src après le chargement de la page et on passe l'image en display:inline
(l'image dans le noscript n'est pas insérée dans le dom donc pas de chargement avant que l'on veuille)

Si l'utilisateur n'a pas le javascript : on ne voit pas la première image mais celle du noscript (la même) : Pas de post-loading et d'amélioration de perfs, mais on voit le même contenu qu'avec le javascript.

La question que je me pose finalement, c'est si d'un point de vue sémantique c'est correct de mettre deux fois la même image pour ceux qui on le javascript, et pour ceux qui ne l'ont pas.

Devrais-je plutôt faire un truc du genre :

<div class="postLoadHolder" data-src="url/image.png" data-alt="textalt" >
<noscript><img src="url/image.png" alt="textalt" /></noscript>
</div>

et insérer l'image postloadée dans le Holder via javascript?
Modifié par Mathieu33 (24 Mar 2010 - 13:47)
Houla attention, pas de src="" vide, dans la majorité des navigateurs ça va provoquer une requête HTTP pour la page en cours!
L'info: Empty-string URLs in HTML - A followup.
La solution: heu... un SRC absent, ça doit pas être valide et peut-être que ça perturbe certains navigateurs (à tester). Une data-URI minimale comme valeur de src, ça peut être intéressant, mais l'absence de support dans IE peut poser des problèmes (à tester aussi, ça se trouve c'est pas gênant).
Hello, merci pour ta réponse.

C'est noté pour le src vide. Concernant les data-*, je compte y accéder par jquery comme un attribut normal de l'élément, et non pas par : element.dataset.plsrc pour être sur que cela fonctionne avec un maximum de navigateurs.

Pour en revenir au plugin LazyLoad déjà existant sur jquery, il à été améliorer pour résoudre le problème dont je parle : http://www.appelsiini.net/2009/12/tuning-lazy-loader

La vrai source est renseignée dans un attribut "original" et l'attribut "src" contient un gif transparent ou gris de 1x1 px.

C'est une approche intéressante, mais si le javascript est désactivé, c'est la fin des haricots et je ne trouve pas ca top niveau sémantique.

C'est pourquoi pour clore ce sujet j'aimerais avoir votre avis sur ces deux solutions :

Solution 1 :
Code HTML envoyé au client :

<span class="postLoadHolder" data-src="url/image.png" data-alt="textalt" > 
<noscript><img src="url/image.png" alt="textalt" /></noscript> 
</span> 

DOM après modification (window.onload) :

<span class="postLoadHolder" data-src="url/image.png" data-alt="textalt" > 
<img src="url/image.png" alt="textalt" />
<noscript><img src="url/image.png" alt="textalt" /></noscript> 
</span> 
(et pourquoi pas enlever le "span" conteneur pour laisser l'image seulement).

Solution 2 :
Code HTML envoyé au client :

<img class="postLoad" src="transparent.gif" data-plsrc="url/image.png" alt="textalt" /> 
<noscript><img src="url/image.png" alt="textalt" /></noscript> 

DOM après modification (window.onload) :

<img class="postLoad" src="url/image.png" data-plsrc="url/image.png" alt="textalt" /> 
<noscript><img src="url/image.png" alt="textalt" /></noscript> 

Quel code HTML envoyé vous semble être le plus sémantique? (A moins que vous ne voyez une meilleure solution?)
Modifié par Mathieu33 (26 Mar 2010 - 15:52)
Mathieu33 a écrit :
Quel code HTML envoyé vous semble être le plus sémantique?

La première. Avec la deuxième, si JS désactivé, tu as deux images (un pixel transparent et la vraie), avec deux fois ton texte alternatif.

Mathieu33 a écrit :
A moins que vous ne voyez une meilleure solution?

Je ne sais pas si ça peut fonctionner, mais je verrais bien ça:

Code HTML envoyé au client:
<span class="postLoadHolder">
  <noscript><img src="url/image.png" alt="textalt" /></noscript>  
</span>

Code après manipulation du DOM:
<img src="url/image.png" alt="textalt" />

ou éventuellement:
<span class="postLoadHolder">
  <img src="url/image.png" alt="textalt" />
</span>
Et sinon, une solution qui va bien:
.hasJS .postLoadImage {visibility: hidden;}
.hasJS .postLoadShowImage {visibility: visible;}

Code HTML de départ:
<img class="postLoadImage" src="url/image.png" alt="textalt" width="..." height="..." />

Code HTML après manipulation en JS:
<img class="postLoadImage postLoadShowImage" src="url/image.png" alt="textalt" width="..." height="..." />

La classe "hasJS" se rajoute sur l'élément HTML, avec par exemple dans le HEAD de la page:
<script>document.documentElement.className+=" hasJS";</script>
(syntaxe simplifiée HTML5, à adapter pour d'autres doctypes).

Ensuite il faut vérifier si le visibility:hidden suffit pour que les navigateurs ne chargent pas l'image. Ce n'est pas sûr, et les navigateurs n'ont pas tous le même comportement à ce sujet. Il faudra peut-être basculer sur du display:none (et du inline pour afficher l'image ensuite), mais ça serait moins drôle car ça t'empêcherait de créer des placeholders dans ta page, lesquels peuvent être pratiques (si tu as indiqué les bonnes dimensions pour l'image) car ça évite des reflow lorsque tes images se chargeront.
Hello,
Je ne savait pas que les navigateurs pouaient ne pas télécharger les images si elles étaient en visibility: hidden / display : none
Merci pour l'info, je testerais ca sur les différents navigateurs, sinon je me rabattrais sur la solution avec le span.

Encore merci pour l'aide Smiley smile

[EDIT]

Hélas, à cause du bug webkit webkit bug #6656, les images en display:none ou visibility:hidden sont quand même téléchargées. Je vais donc utiliser la technique du span :


<span class="lz" data-lz-src="url/image.png" data-lz-width="50" data-lz-height="50" data-lz-alt="textalt" > 
<noscript><img src="url/image.png" width="50" height="50" alt="textalt" /></noscript> 
</span> 

Côté CSS :
.hasJS .lz
{
	display:inline-block;
	background:url('/content/ajax-loader.gif') center center no-repeat;
}


Du coup lorsque le DOM est prêt je donne au span la taille de la future image spécifiée dans les attributs data-lz-width et data-lz-height le gardant dans le flux (et avec un petit gif de loading en background)

Lorsque la page à été chargée j'ajoute les images dans le dom pour les télécharger (en ajoutant les attributs data-lz-* spécifiés dans le span), et lorsqu'elles sont chargées : je remplace le span par l'image correspondante.

Je considère le sujet comme résolu, mais si vous avez d'autres idées n'hésitez pas Smiley smile
Modifié par Mathieu33 (31 Mar 2010 - 13:09)