Structure de page

Voici la structure de page par défaut que j’emploie actuellement :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-15" />
        <title>&hellip;</title>
        <link rel="stylesheet" type="text/css" media="screen" title="Affichage par d&eacute;faut" href="css/lib/reset.clean.css" />
        <link rel="stylesheet" type="text/css" media="screen" title="Affichage par d&eacute;faut" href="css/screen.css" />
        <script type="text/javascript" src="js/lib/init.min.js"></script>
    </head>
    <body>
        <!--[if IE]><div class="msie"><![endif]--><!--[if gt IE 6]><div class="msie7"><![endif]-->
        <!--[if IE 6]><div class="msie6"><![endif]--><!--[if lt IE 6]><div class="msie5"><![endif]-->
        <div id="page">
            <div id="tete">
                &hellip;
            </div>
            <hr class="masquer" />
            <div id="corps">
                &hellip;
            </div>
            <hr class="masquer" />
            <div id="pied">
                &hellip;
            </div>
        </div>
        <!--[if IE]></div></div><![endif]-->
        <script type="text/javascript" src="js/lib/jquery.min.js"></script>
        <script type="text/javascript" src="js/behaviour.js"></script>
    </body>
</html>

Ainsi que la feuille de style associée (ici, non compressée):

/* YUI reset
------------------------------------------------------------------------------*/
html
{
    color:#000;
    background-color:#FFF;
    background-position:0 0;
    background-repeat:no-repeat
}
body, div, p,
dl, dt, dd, ul, ol, li,
h1, h2, h3, h4, h5, h6,
pre, code, blockquote,
form, fieldset, legend, input, textarea,
th, td, a, span
{
    margin:0;
    padding:0;
    background-position:0 0;
    background-repeat:no-repeat
}
table
{
    border-collapse:collapse;
    border-spacing:0;
    background-position:0 0;
    background-repeat:no-repeat
}
fieldset, img
{
    border:none
}
address, caption, cite, code, dfn, em, strong, th, var
{
    font-style:normal;
    font-weight:normal;
    background-position:0 0;
    background-repeat:no-repeat
}
li
{
    list-style:none
}
caption, th
{
    text-align:left;
    background-position:0 0;
    background-repeat:no-repeat
}
h1, h2, h3, h4, h5, h6
{
    font-size:100%;
    font-weight:normal;
    background-position:0 0;
    background-repeat:no-repeat
}
q:before, q:after
{
    content:""
}
abbr, acronym
{
    border:0;
    font-variant:normal
}
sup
{
    vertical-align:text-top
}
sub
{
    vertical-align:text-bottom
}
input, textarea, select
{
    font-family:inherit;
    font-size:inherit;
    font-weight:inherit;
    background-position:0 0;
    background-repeat:no-repeat
}
legend
{
    color:#000;
    background-color:inherit;
    background-position:0 0;
    background-repeat:no-repeat
}
legend span
{
    display:block
}
/* YUI font
------------------------------------------------------------------------------*/
body
{
    font:13px/1.231 sans-serif
}
table
{
    font-size:inherit
}
pre, code, kbd, samp, tt
{
    font-family:monospace;
    line-height:100%
}
/* YUI base
------------------------------------------------------------------------------*/
h1
{
    font-size:138.5%
}
h2
{
    font-size:123.1%
}
h3
{
    font-size:108%
}
h1, h2, h3
{
    margin:1em 0
}
h1, h2, h3, h4, h5, h6, strong
{
    font-weight:bold
}
abbr, acronym
{
    border-bottom:1px dotted
} 
em
{
    font-style:italic
}
blockquote, ul, ol, dl
{
    margin:1em
}
ol, ul, dl
{
    margin-left:2em
}
ol li
{
    list-style:decimal outside
}
ul li
{
    list-style:disc outside
}
dl dd
{
    margin-left:1em
}
th, td
{
    border:1px solid;
    padding:.5em
}
th
{
    font-weight:bold;
    text-align:center
}
caption
{
    margin-bottom:.5em;
    text-align:center
}
p, fieldset, table, pre
{
    margin-bottom:1em
}
input[type=text],
input[type=password],
textarea
{
    width:12.25em
}
label
{
    cursor:pointer
}
select,
input,
textarea
{
    font-size:100%
}
/* YUI font for IE
------------------------------------------------------------------------------*/
.msie body
{
    font-size:small
}
.msie pre, .msie code, .msie kbd, .msie samp, .msie tt
{
    font-size:108%
}
.msie table
{
    font-size:100%
}
/* YUI base for IE
------------------------------------------------------------------------------*/
.msie input[type=text],
.msie input[type=password],
.msie textarea
{
    width:11.9em
}
/* classes utiles
------------------------------------------------------------------------------*/
.masquer
{
    position:absolute;
    top:-999em;left:-999em;
    display:block;
    height:0;width:0;
    overflow:hidden;
    text-indent:-999em
}
.cacher
{
    display:none
}
.liste
{
    float:left;
    margin:0
}
.liste li
{
    display:block;
    float:left;
    list-style-type:none
}
/* EOF
------------------------------------------------------------------------------*/

Et le petit bout de JS (là encore, à l’état brut) :

/* 
------------------------------------------------------------------------------*/
var BrowserDetect = {
    init: function () {
            this.browser = this.searchString(this.dataBrowser) 
                || "An unknown browser";
            this.version = this.searchVersion(navigator.userAgent)
                || this.searchVersion(navigator.appVersion)
                || "an unknown version";
            this.OS = this.searchString(this.dataOS)
                || "an unknown OS";
        },
        searchString: function (data) {
            for (var i=0;i<data.length;i++) {
                var dataString = data[i].string;
                var dataProp = data[i].prop;
                this.versionSearchString = data[i].versionSearch || data[i].identity;
                if (dataString) {
                    if (dataString.indexOf(data[i].subString) != -1)
                        return data[i].identity;
                    }
                    else if (dataProp)
                        return data[i].identity;
            }
        },
        searchVersion: function (dataString) {
        var index = dataString.indexOf(this.versionSearchString);
        if (index == -1) return;
        return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
    },
    dataBrowser: [
        {
            string: navigator.vendor,
            subString: "Apple",
            identity: "Safari"
        },
        {
            prop: window.opera,
            identity: "Opera"
        },
        {
            string: navigator.userAgent,
            subString: "Firefox",
            identity: "Firefox"
        },
        {
            string: navigator.userAgent,
            subString: "MSIE",
            identity: "Explorer",
            versionSearch: "MSIE"
        }
    ],
    dataOS : [
        {
            string: navigator.platform,
            subString: "Win",
            identity: "Windows"
        },
        {
            string: navigator.platform,
            subString: "Mac",
            identity: "Mac"
        },
        {
            string: navigator.platform,
            subString: "Linux",
            identity: "Linux"
        }
    ]
};
BrowserDetect.init();
/* 
------------------------------------------------------------------------------*/
var browser = "js";
var addclass = "class";
/* OSDetect
------------------------------------------------------------------------------*/
if(BrowserDetect.OS == "Mac")           browser += " mac";
if(BrowserDetect.OS == "Linux")         browser += " linux";
if(BrowserDetect.OS == "Windows")       browser += " win";
/* BrowserDetect
------------------------------------------------------------------------------*/
if(BrowserDetect.browser == "Firefox")  browser += " firefox";
if(BrowserDetect.browser == "Opera" )   browser += " opera";
if(BrowserDetect.browser == "Safari")   browser += " safari";
if(BrowserDetect.browser == "Explorer")addclass = "className";
/* 
------------------------------------------------------------------------------*/
document.getElementsByTagName("HTML")[0].setAttribute(addclass, browser);
/* EOF
------------------------------------------------------------------------------*/

Oui je sais, c’est un peu long… mais vous avez maintenant toutes les cartes en main.

Techniques employées

Je n’ai au final pas inventé grand chose, mais au contraire tenté de combiner aux mieux différentes techniques :

Objectifs

J’ai tenté via cette structure de combiner plusieurs avantages :

  • l’utilisation d’un reset CSS robuste est éprouvé ;
  • la remise à niveau des principaux styles pour éviter de tout devoir redéfinir ;
  • la possibilité de cibler facilement (et sans hack) des élements de la page et ce en fonction du navigateur et du système d’exploitation (.mac .safari #id, .js .classe, etc) ;
  • un chargement de la page optimisé (en suivant principalement quelques-unes des recommandations fournies par Yahoo!) ;
  • une validation (sans erreur ni avertissement) des fichiers HTML et CSS ;
  • fournir un gabarit générique de page pas trop complexe, et couvrant la plupart des cas de montage ;
  • l’inclusion par défaut de JQuery, la bibliothèque JS que j’utilise ;
  • et proposer quelques classes génériques utiles.

Les buts de ce billet maintenant ?

  • Partager avec vous cette structure.
  • Y trouver d’éventuelles critiques et améliorations.
  • La comparer avec vos structures respectives ?

N’hésitez pas !


10 commentaires ↓

#1 Shemu le 05.13.08 à 17:20

La détection de navigateur en JS ne me botte pas trop. Sans JS, tes CSS spécifiques ne fonctionneront plus. Pour le reste, tu sais ce que j’en pense… 😉

#2 Vincent le 05.13.08 à 17:29

En effet, ça peut poser problème dans certains cas.

Mais ces sélecteurs spécifiques sont généralement là pour notre ami IE uniquement… et justement avec les commentaires conditionnels, pas besoin de JS en l’occurrence.

#3 Yves le 05.13.08 à 20:32

Sympa l’article … Alors .. je me lance !

Le document HTML :

  • l’encodage ISO : je désapprouve, pourquoi se limiter à un type d’encodage destiné à une seule partie du monde,alors que utf-8 couvre une partie bien plus importante. On y gagne en terme de maintenabilite et d’extensibilité quand nos amis marketeux décide de passer le même site dans 10 autres langues… chinois, grec et russe au hasard …

  • les entités HTML : les utiliser pour des caractères alphabétiques gérés par ISO-8859-15 ? C’est inutile. Il en serait de même en utf-8.

  • Les elements link : Pourquoi se limiter au media screen ? Une majorité de client cherche à avoir le même rendu sur papier si il n’existe pas de feuille d’impression dédié. Actuellement j’expérimente un projet dans lequel le client récupère une seule feuille construire par le serveur, ça permet d’optimiser les temps de chargement, et de gagner en flexibilité grâce aux langages serveurs pour la maintenance des feuilles de styles. (les variables par exemple) J’inclu la print avec @media print { }

  • J’ai pas compris l’utilité des div dédiés aux différentes version de IE, ça permet certainement de développer des applications dédié, ça reste néanmoins intrusif et confus de ne pas récupérer le même DOM sur chaque navigateur.

CSS : - YUI … Ok si tu veux..

  • Les class génériques je suis contre, pour la simple raison que c’est intrusif à souhait, ça facilitent certes le développement initial, mais pas une maintenance profonde.

  • La class masquer : .masquer { position:absolute; top:-999em;left:-999em; display:block; height:0;width:0; overflow:hidden; text-indent:-999em }

Si tu cherches à cacher le contenu sur les lecteurs d’écran ton code est OK, mais un display:none aurait suffit.

Les lecteurs d’écrans prennent en compte la CSS, text-indent aura la même conséquence que display:none, ton texte sera tronqué et invisible. Il en va de même pour width:0; height:0; overflow:hidden;.

Les positions top négatifs sont également à éviter, ça entraine des bugs connu sur Windows-Eyes, tel que la duplication de lien et le changement d’ordre de tabulation. Dans la même logique left ne devrait pas être utilisé systématiquement, des sites utilisant des langues écrites de droite à gauche préfèreront certainement une position négative à droite …

  • Une dernière remarque : c’est vachement frustrant de ne pas avoir de point-virgule à la dernière ligne, je faisais pareil il y a longtemps, mais ça n’aide personne, c’est un bon réflex à avoir en CSS et en JS, je pense..

Et la partie JS :

Le code est beaucoup trop long, IE est détectable en une ligne, et il en va de même pour les autres navigateurs, fait un tour du coté de la methode detect() de Dean Edwards dans sa bibliothèque Base2 et des commentaires conditionnelles JScript dans IE.

Bon bah voilà … pour l’instant j’ai le commentaire le plus long du site 😛 Et j’en retiens que le textarea est trop petit, une petite fonction javascript pour le re-dimensionner comme on peut le faire sur Safari ce serait sympa 😛

#4 Etienne le 05.14.08 à 10:07

concernant l’encodage, effectivement UTF-8 sinon rien, ultra portable, a condition que le back-office et l’ensemble des pages du site soit encodé de la sorte.

pour les médias, je pense que l’exemple est de par son nom un exemple et qu’il s’adapte ensuite au sujet traité. Ici nous parlons de base de travail…

concernant le js (je fais pratiquement plus que ça donc j’en parle plus)…

tu utilise la méthode de Mr (majuscule svp :) Peter-Paul Kock qui me semble tout a fait aboutis, c’est également une méthode que j’utilise.

Juste un commentaire sur l’intervention de l’ami Yves pour une analyse différentielle concernant les classes .masquer et .cacher…

en matière de bon jajax ou de « des acheter aime elles », certains navigateurs (ie6 et inf, safari 2.0.4), pour certaines utilisation (affectation de propriété ou de contenu a des éléments en display none) ne trouvent pas toujours l’élément dans l’arbre dom.

du coup l’utilisation de la class masquer prend tout son sens, car le display none est loin d’être une alternative viable sur l’ensemble des navigateurs…

Je ne savais pas pour les problèmes posé sur les lecteurs d’écran window Eyes, peut être faut-il effectivement reconsidérer le fait d’utiliser left ou right pour mettre uniquement des propriétés top et bottom.

La solution serait peut-être de mettre l’ensemble des éléments d’affichage dynamique en bas de page. Au déclenchement de l’affichage de la zone masquée, une ancre nommée redirige l’utilisateur vers l’élément afficher. De part et d’autre de l’élément affiché un lien avec une ancre permettant a l’utilisateur de retourner a l’emplacement initial du dom.

… suis-je clair ?

bon a quand les soirées a thème htmlzengarden au « paradis du fruit »…?

#5 Etienne le 05.14.08 à 10:09

Tu te rend compte Vincent, tu me fait écrire sur un blog… .. . !

#6 Vincent le 05.14.08 à 10:37

Héhé, ça part dans tout les sens ! 😉

Réponse point par point sur ce qui me fait réagir.

  • Encodage ISO : tout dépend de la chaine de développement. Personnellement, je ne peux pas garantir qu’elle sera en UTF-8 tout du long et du coup, je n’hésite pas à utiliser l’encodage ISO pour les sites que je réalise en français (95% de mes productions quand même).

  • Encodage des entités : oui, c’est presque plus un réflexe qu’autre chose. Néanmoins, certains caractères étant absents de nos claviers (×, B, ©, etc), c’est parfois bien pratique.

  • Les commentaires conditionnels : ils permettent justement de s’affranchir facilement et à moindre frais des fameux hacks que l’ont voit partout. Voir à ce sujet le récent article sur les Intégristes par exemple.

  • La classe générique « masquer » : je n’étais pas non plus au courant des problèmes évoqués par Yves. Des sources à ce niveau ? Effectivement par contre, ça perturbe l’ordre de tabulation s’il s’agit d’un lien masqué. Mauvais point.

#7 Vincent le 05.14.08 à 10:39
  • Etienne : tu fais trop d’AJAX toi. Et trop de private jokes ! 😉

  • Yves : Yep, bonne idée pour le champ de saisie texte. :)
#8 Yves le 05.14.08 à 12:40
  • Etienne : T’as du mal comprendre, il faut éviter les positionnements top/bottom et utiliser uniquement left ou right. Relis :p

  • Vincent : Je n’ai pas de source au sujet des bugs de Windows-Eyes, ce sont des observations de Benjamin Hawkes-Lewis (Yahoo), qu’il ma recommandé d’appliquer au fil d’une discussion. Ces recommandations date de janvier 2008, donc je pense qu’elles sont encore d’actualité.

#9 JHB le 05.24.08 à 11:14

Bravo, on peut penser ce que l’on veut du sujet… pour moi le mélange .css & .js est plutôt critiquable mais au moins l’article est super documenté, bravo !

#10 Performance Web — HTML zen garden le 08.16.08 à 17:31

[…] me suis ainsi retrouvé […]


Laisser un commentaire

Mise en forme : vous pouvez utiliser la syntaxe Markdown. Vous verrez, c’est chouette !