Enfin ! Depuis le temps que je souhaitais refondre le site légèrement désuet qu’était le site de mon agence, cette fois, l’occasion est arrivée. Le nouveau site de Prezenz a été mis en ligne il y a quelques semaines, et le moins qu’on puisse dire, c’est que côté intégration j’ai eu quelques défis bien sympas à relever sur ce site !
Cette refonte ayant touché beaucoup de domaines, pour ce billet, je m’en tiendrai « juste » à l’intégration, car il y a déjà beaucoup à dire.
Les objectifs
Les objectifs ont été clairs : pour le site de l’agence, on va mettre le paquet. Site en responsive, mobiles, micro-datas, optimisation SEO, etc. D’entrée de jeu, j’ai imposé une intégration en mobile-first, et tant qu’à faire les besoins en JavaScript seront faits autant que possible à la main !
Les navigateurs cibles seront en premier les modernes, les vieux ne seront pas oubliés pour autant, mais ils passeront clairement après les modernes.
De nombreux contenus ont été rédigés, un gestionnaire de site sur mesure a été créé, Google Analytics a aussi eu de quoi faire, de nombreux trackers ont été mis en place afin de voir clairement si les choix qui ont été faits sont compris et utilisés.
Construction d’une CSS mobile-first, responsive avec Sass/Compass et RÖCSSTI
Mon micro-framework était construit en desktop-first, et du coup, avec ce site, une version Sass de RÖCSSTI construite en mobile-first a été mise au point. Le début a consisté à changer l’ordre de la CSS : on part du plus petit dénominateur commun pour aller vers les résolutions plus élevées, en ne changeant que ce qui est nécessaire à chaque étape.
Je dis bien « au départ » car quelques légères modifications ont dû suivre, j’y reviendrai.
L’intégration mobile-first est un exercice de style intéressant, même si j’en avais déjà fait une pour mon site personnel, là c’était un poil plus compliqué, et donc plus intéressant.
Autant le dire de suite, j’avais des wireframes et des guides de styles très précis, et je ne vois pas comment intégrer un site correctement (comprenez sans perdre de temps et en respectant autant que possible l’intention du design). Si parfois sur un site desktop, on peut se permettre d’improviser les points imprécis, sur une intégration construite en mobile-first, j’aurais tendance à le déconseiller vivement !
Alors certes, avec les vrais contenus, certaines adaptations en cours de route ont dû être faites, mais l’idée générale m’a bien guidé.
Structure du projet avec Sass
À l’inverse de bon nombre d’intégrateurs, je ne suis pas un fan de tout morceler mes CSS en plein de fichiers. C’est sûrement utile avec des CSS immenses, mais je ne suis pas allé aussi loin.
Par contre, quand j’ai eu le guide de styles en mains, j’ai fait un sous-fichier avec tous les paramètres : notamment toutes les couleurs données en référence ont été mises dans des variables et nommées telles quelles, comme par exemple $prz-grey: #363636;
. Et je me suis interdit d’utiliser autre chose que ces variables !
Ainsi, toute référence venant des graphistes et qui serait en-dehors des clous posés par… eux-mêmes (!) aura vite été remise dans le droit chemin. Seule exception, je n’ai pas créé de variable pour le blanc pur.
Les autres sous-fichiers (qui a dit includes ?) étaient principalement pour la gestion des sprites, afin de ne pas surcharger le fichier principal, qui, avec les commentaires, est resté très facilement maintenable et lisible.
Les em
, j’aime !
Je reste légèrement surpris que la conférence de Nicolas Hoizey à Paris-Web sur l’unité em ait presque un goût de grande nouveauté pour beaucoup, car c’est vraiment un régal à utiliser dès qu’on en a pris l’habitude. Pour ma part, je les utilise depuis de nombreux projets, et je me surprends parfois à ne plus raisonner en pixels pour des padding
et autre margin
, mais directement en em
.
Cette intégration, à l’exception des images, est intégralement construite en em
, media-queries comprises ! Et le moins que je puisse dire, c’est que cela a des effets de bords… plutôt sympathiques !
Le premier est de permettre un zoom global ou un zoom texte sans aucun souci. Le site va très bien s’adapter si par exemple je zoome fortement sur mon navigateur desktop. Autrement dit, c’est un pur régal si on a des contraintes d’accessibilité où l’on doit permettre un zoom texte conséquent. Autre avantage non négligeable : le site s’accommode parfaitement de toutes les tailles de fonte définies ou différentes par défaut.
Ci-dessous un exemple de site en version zoomée à 200% :
Même si effectivement, les em
sont un peu plus simples à gérer avec un pré-processeur comme Sass, il ne faut pas hésiter, même sans Sass, cela se gère bien et ils apportent de nombreux avantages. Les em
, c’est sensass’, même sans Sass.
Optimisation retina
Histoire de faire les choses comme il faut, vu que le site cible clairement les mobiles, il eut été dommage de ne pas penser à l’optimisation aux écrans à haute densité de pixels, que j’appellerai retina par simple fainéantise ! :)
Comme le site utilise autant que possible du texte avec une webfont, de ce côté-là, pas de souci. Pour le logo du site, pas de souci, SVG a été choisi et est « fallbacké » avec un PNG.
Pour les icônes – le site en utilise énormément –, le choix d’un doublement de résolution a été préféré à SVG, cela a été plus simple à gérer pour tout le monde, y compris moi-même pour une histoire de sprites CSS, j’aborde ce point plus loin.
De ce que j’avais pu lire sur le sujet, le principe utilisé est souvent de charger d’abord les images normales, et seulement ensuite de charger les images de meilleure qualité. Comme l’objectif était clairement les mobiles, les navigateurs modernes et les écrans retina, j’ai pris le parti inverse : d’abord charger uniquement les images en « haute qualité », afin d’éviter des requêtes supplémentaires pour les mobiles retina. Les navigateurs modernes gérant parfaitement background-size
, le léger surpoids était très limité pour ces derniers, en tout cas, rien de comparable avec des requêtes HTTP supplémentaires.
Seuls les vieux navigateurs auront eu des images en taille normale en plus, autrement dit, IE7 et 8.
Considérations sur Flexbox et CSS3 multicolumn
Histoire de me faire plaisir, j’ai pu expérimenter l’utilisation de Flexbox pour quelques parties, disons-le tout net, ce positionnement de boîtes flexibles est un pur bonheur : surpuissant, très simple, ne nécessitant que peu de code… c’est gé-nial.
Sauuuuuf… quand on doit regarder chez les navigateurs qui ne le supportent pas, là ça devient la misère (les fallbacks ne sont franchement pas terribles, pour ne pas dire inexistants). C’est cela qui m’a conduit à en limiter l’usage là où je pouvais me raccrocher aux branches avec du table-layout avec des largeurs en pourcentages.
Certains éléments demandés m’ont été impossibles à styler sans CSS3 multi-column. Typiquement, la navigation secondaire (découvrir, attirer, etc.) sur la page portrait de Prezenz qui passe d’une colonne à deux, puis trois colonnes… impossible de faire cela autrement !
Comme Flexbox, le problème était la compatibilité sur les vieux navigateurs, qui a dit IE ? Heureusement, ces derniers n’ayant que faire des versions responsive et la version desktop s’affichant sur une colonne, au final, ce problème délicat s’est réglé en partie tout seul !
Pour la liste des services associés à une rubrique, par exemple le développement web, le problème de non-support était moins gênant : les navigateurs ne le supportant pas afficheront la liste sur une unique colonne.
Ce type de positionnement est vraiment à réserver pour des menus de navigation ou des listes, je l’imagine plutôt désagréable pour lire un texte ainsi morcelé.
Autre point faible, débrouillez-vous que pour le nombres de colonnes et d’éléments soient des multiples, sinon le résultat est catastrophique ! Je n’ai pas eu le problème avec les catégories de services (6 se divise bien par/en 2 et 3), mais pour la navigation secondaire de la partie portrait (5 éléments), tintin ! Du coup, j’ai rajouté un élément vide qui n’apparaît que quand il y a deux ou trois colonnes (autrement dit à partir des smartphones en paysage et sur les tablettes), afin de pallier ce petit problème.
Bref, des possibilités sympas, mais à utiliser avec grand discernement.
Une CSS réutilisable
Je continue de progresser en matière de CSS modulaires et réutilisables, et le moins que je puisse dire, c’est que cela rend beaucoup, mais alors vraiment beaucoup de services !
Typiquement, les demandes du genre « tu peux transformer ce bloc en lien » qui forcent parfois à replonger dans la CSS, se règlent instantanément. La CSS ne reposant pas sur une structure HTML donnée, elle reste très flexible.
Typiquement, pour les icônes passant de petite taille à grande taille dans certains menus, je me serais mal vu faire des classes spécifiques qui gèrent la même icône selon la résolution… multipliez ça par la gestion du retina et le nombre monstrueux d’icônes (une soixantaine), et c’eût été la Bérézina. Au final, j’ai opté pour un objet icône dans chaque taille (dépourvu d’infos de positionnement), que j’affiche ou non selon la résolution. D’une, cet objet a été réutilisable (ça m’a bien servi), et de deux c’était beaucoup plus simple à gérer.
Côté notation, chaque module avait ses objets, tous préfixés par le nom du module. Un changement de tag ? Rien à cirer, les styles sont appliqués sur les classes, pas sur le code. Un nouveau comportement JavaScript ? On s’en fout, les règles d’état sont là, et le JavaScript manipule des classes et non des styles en ligne.
Ajoutons à cela que les premières mises à jour pas prévues sont vite arrivées, et là, devoir replonger dans la CSS a été une étape dont je n’ai pas été mécontent… de me passer : pouvoir intégrer les nouvelles demandes uniquement grâce aux briques de RÖCSSTI, ce fut un gain de temps et de prises de tête.
Je crois avoir utilisé 4 !important
dans la CSS (dont un temporaire pour les fêtes de fin d’année), à bon escient bien sûr. :)
Des performances et des sprites
Vu le nombre monstrueux d’icônes, l’option sprites CSS a vite déboulé sur le projet. Tout le monde m’avait vanté les mérites des fonctions magiques de Sass pour les sprites… j’en ai été pour mes frais ! Non pas que ces fonctions ne soient pas bien (générer une image de sprite à partir de plein d’autres, c’est vraiment pratique), mais… elles ne convenaient pas du tout à mes besoins. Cela m’a même fait perdre du temps d’essayer d’utiliser à tout prix ces fonctions. J’ai une icône pour l’état de lien, une pour l’état survolé, et une pour une troisième utilisation à part.
Du coup, j’ai bricolé une fonction Sass à la main, histoire de permettre de générer le code CSS des sprites facilement, peu importe la taille de la grille des sprites. J’avais expliqué quelques aspects de cette fonction dans un précédent billet, donc je ne m’étendrai pas plus sur le sujet. Bref, DIY : Do It Yourself (faites-le vous-même).
Un regret néanmoins, la CSS aurait pu bénéficier d’une classe factorisant le tout comme :
[class*=icon-48]
{
…
}
J’ai pris connaissance de cette technique après avoir codé l’intégralité de la CSS… tant pis, je ferai encore mieux la prochaine fois pour les sprites, ou si je trouve le temps, je reviendrai dessus.
Côté performances, la règle d’or était : des sélecteurs courts ! Cela a d’ailleurs re-servi pour faciliter la surcharge CSS, donc pour la maintenabilité.
Des micro-datas
Afin d’avoir un contenu sémantisé, les microdatas ont été utilisées massivement. J’ai eu l’approche suivante : l’élément racine est l’agence web, comme les informations de cette dernière sont toujours juste avant le footer
, pas de souci. L’élément de référence sera donc sur le body
(body itemscope itemtype="http://schema.org/Corporation"
), et les autres éléments viendront se greffer sur cet élément.
Ensuite, chaque item qui dépendait de l’agence était indiqué dans le contenu par la relation MakesOffer
, comme les services sur une catégorie. C’est d’ailleurs cette relation qui indique que l’élément service est « enfant » de l’agence.
D’autres pages indiquent les personnes comme la page contact.
Curiosité, je pensais utiliser les meta
s du site pour stocker d’autres informations, malheureusement, il est impossible de balancer des id
sur une balise meta
, sinon le validateur ronchonne. Il ne faut d’ailleurs pas mettre d’attribut name
à tort et à travers à la balise meta
, sinon le validateur ronchonne un « meta name is not registered ». Par contre, il est possible de stocker des meta
dans le body
, sans que cela ne choque le validateur. Bizarre mais ça marche ! Comme illustré dans cette image.
Qu’il me soit encore permis de remercier Twikito qui les a beaucoup utilisées sur la page d’Opquast, cela m’a beaucoup aidé à comprendre comment faire.
Des petites astuces et considérations sur CSS par ci par là
Un box carré ?
Une demande particulièrement bête m’a donné du fil à retordre : certains blocs devaient être carrés, comme sur la page des services Web de Prezenz. Or, ces mêmes blocs étaient dimensionnés en pourcentages ou via Flexbox. Impossible donc de leur attribuer une hauteur.
J’ai bien glané quelques astuces sur le sujet, mais la plus simple m’a été inspirée par Nicolas Hoizey (entre Nicolas H. on se comprend) sur Twitter : utiliser une simple image carrée ! Du coup, j’ai créé une image carrée de 1 pixel de côté, et je lui ai donné une largeur de 100% de son conteneur. Ainsi mon bloc sera carré du fait de cette image. Les contenus seront positionnés en absolu dans ce bloc, qui lui sera donc en relatif.
Histoire de ne pas perdre bêtement une requête HTTP avec ce genre d’image rikikie, je les ai mises en Data-URI
. Bref, KISS : Keep It Simple and Smart (restez simple et élégant).
Classes atomiques
Autre point, le recours aux classes atomiques est légèrement moins systématique lors d’une approche mobile-first par rapport à une intégration desktop-first (je n’ai pas eu envie de rentrer dans le .w60desktop
et .w40mobile
, j’ai préféré rester simple). Mon micro-framework en version mobile-first a appris pas mal de choses : répéter certaines classes selon la media-query utilisée, répéter certains layout, etc.
Qu’on soit clair : je ne dis pas que le concept est à jeter en mobile-first, je dis juste que j’y ai eu un peu moins recours dans ce cas. À voir si cela se confirme sur mes prochaines intégrations en mobile-first.
Approches utilisées
J’avais beaucoup apprécié la lecture de SMACSS, dont j’ai réutilisé certains de ses principes comme les règles d’état, excellent pour éviter de manipuler des styles en ligne en JavaScript (autant manipuler des règles d’état). Côté OOCSS, j’ai repris parfois quelques un de ses principes à mon compte. Idem pour l’approche BEM, et l’approche atomes/molécules.
Même si je ne les ai pas appliquées stricto sensus (BEM était trop verbeux pour mes besoins par exemple), j’en ai repris à ma sauce certains éléments pratiques :
- les règles d’état .is-<état>, pratique et clair pour le JavaScript ;
- les modules ;
- quelques classes atomiques ;
- etc.
Complexité de la CSS
Ne le cachons pas, ce genre de CSS est très efficace pour les performances, etc., mais elle est parfois complexe, autant à créer qu’à maintenir.
Ne lésinez vraiment pas sur les commentaires ni sur le sectionnage de vos CSS. Pour donner un ordre d’idée, la version Sass pèse à peu près 65 ko, la version CSS non minifiée pèse 115 ko, et la version minifiée de la CSS pèse 65 ko, 14 ko après GZIP.
Quoi qu’on en dise, ça doit être rangé là-dedans, nom d’un gadget !
Autres
Un point central : le table-layout m’a énormément servi. Si vous n’utilisez pas ce positionnement, vous devriez sérieusement reconsidérer votre avis, il est vraiment magique pour de nombreux cas, et évite un paquet de flottants et de délires d’intégrations.
D’ailleurs, selon moi, intégrer un design non trivial en mobile-first nécessité de pouvoir utiliser des positionnements relativement modernes en CSS (bref, sortir des flottants), sinon c’est la crise de nerfs assurée.
En conclusion
Non seulement cette intégration a été un bon défi, mais en plus travailler pour son agence, c’est encore plus motivant. Ne laisser que peu de concessions et mettre tout ce que je connaissais dans cette réalisation, cela m’a permis de progresser.
Un autre billet parlera des « à coté » : Google Analytics, le côté back-end et l’apport qu’il a donné au front-end, et tous les développements qui sont arrivés en plus, car lancés à plein gaz, on ne s’est pas arrêté en si bon chemin !
Ajout : petit bonus
Si vous êtes curieux, vous pouvez étudier la CSS de Prezenz version Sass.
Retour d'expérience très intéressant et très riche, merci
Une question sur la problématique des icônes : pourquoi ne pas avoir fait le choix des webfonts ?
Cela aurait résolu ta problématique de retina et de variante par couleur des différentes icônes.
Au niveau poids je ne sais pas ce que ça pourrait donner mais on voit que la version actuelle à base de PNG consomme 220ko sur le first hit (http://www.webpagetest.org/result/131227_E0_NX9/1/details/) ce que je trouve énorme pour des icônes.
Qu'en penses-tu ?
Eric