La tête dans le Flux !

RSS

Posts tagged with "mobile"

Détecter le device-width en JavaScript, mission impossible ?

Suite à un billet récent constatant que le device-width (largeur d’écran d’un périphérique) diffère selon les navigateurs, j’ai souhaité pouvoir proposer un chargement conditionnel de mes feuilles de styles mobile voire de modifier la valeur de mon meta viewport.

Le principe est de détecter en JavaScript la valeur de device-width et de charger une feuille de style adaptée (par exemple : styles320.css, styles640.css, styles800.css, styles1024.css). Attention, je ne dis pas qu’il s’agit d’une bonne pratique, je souhaitais simplement tester cette possibilité d’adaptation.

Et là c’est le drame…

Car au final ni screen.width ni windows.innerWidth de JavaScript ne correspondent à device-width, c’est à dire la valeur indispensable pour s’adapter aux terminaux mobiles.

Pour parvenir à mes fins, j’ai rapidement créé une page HTML de test à laquelle il est possible d’accéder ici : http://bit.ly/device-width

Voici le contexte :

  1. application d’une meta viewport de valeur “width=device-width”
  2. détection du device-width à l’aide de CSS mediaqueries (@media (device-width) {})
  3. détection de screen.width ou windows.innerWidth via JavaScript et chargement d’une feuille de style correspondante (styles320.css, styles640.css, styles800.css ou styles1024.css)

J’ai pu constater que selon les terminaux, leur orientation et le navigateur employé, les deux valeurs ne coïncident pas ! Testez chez vous et n’hésitez pas à me faire vos retours.

Et si vous avez une solution magique, je suis preneur !

EDIT : Un nouveau challenger : window.matchMedia

Suite à la proposition d’Anthony, j’ai rajouté un troisième test dans la page : celui de window.matchMedia qui paraît prometteur puisqu’il correspond exactement à la valeur recherchée.

Le test en résumé ressemble à ça :

if (window.matchMedia("(min-width: 640px)").matches) {
document.write("device-width > 640px (window.matchMedia OK)");
} 

Aux dernières nouvelles, les navigateurs mobiles Safari, Firefox et Android 3+ semblent supporter window.matchMedia, ce qui n’est pas le cas d’Opera (ni mobile ni mini). Pour IE mobile, je n’ai pas encore de retours.

Les mobiles nous mentent !

Vous le savez sans doute : les périphériques mobiles disposent de trois types de largeurs différentes :

  • screen width : largeur physique de l’écran
  • device-width : largeur déclarée par le périphérique
  • viewport : largeur de fenêtre du navigateur

Ces données ne concernent que la largeur mais sont transposables pour la hauteur, et sont bien-sûr susceptibles de changer selon l’orientation !

J’ai toujours cru que la valeur de device-width était fixée pour chaque périphérique, par exemple que le device-width sur iPhone 3 et 4 était tout le temps de 320 pixels. Mais ça c’était avant d’avoir fait quelques tests utilisateurs.

En bas de cet article, vous trouverez l’ensemble des données récoltées.

Ces tests n’ont rien de scientifiques ni de révolutionnaires, mais ils m’ont permis de comprendre que device-width ne dépend pas forcément que du périphérique, mais également du navigateur utilisé.

En résumé, si vous appliquez le désormais célèbre <meta name=”viewport” content=”width=device-width”>, votre base de travail sera non seulement différente selon les différents périphériques (pas de surprise jusque là), mais elle sera aussi différente sur un même périphérique selon votre navigateur !

(Et si vous n’utilisez pas la valeur “width=device-width”… c’est pire !)

Trois points me semblent essentiels :

  • iPhone 3 et iPhone 4 ont le même device-width, malgré leur densité de pixels différente
  • Le device-width sur Safari est identique en portrait qu’en paysage (!)
  • Un device-width (en portrait) peut globalement varier de 240px à 640px selon les terminaux mobiles

De ce dernier point découle une conséquence logique : votre design, parfaitement affiché et votre navigation idéalement proportionnée pour iPhone (device-width 320px) seront comparativement deux fois plus réduits et donc potentiellement moins ergonomiques - voire inaccessibles - sur certains autres smartphones (device-width 480 à 640px).

Les données collectées

Apple iPhone 3GS
  • Safari (portrait + paysage) : >180dpi / ratio >0.7 / device-width >320
Apple iPhone 4
  • Safari (portrait + paysage) : >320dpi / ratio >2 / device-width >320
  • Opera mini (portrait) : (NR resolution et ratio) / device-width >320
  • Opera mini (paysage) : (NR resolution et ratio) / device-width >480
  • iCab (portrait + paysage) : >320dpi / ratio >2 / device-width >320
  • Dolphin (portrait + paysage) : >320dpi / ratio >2 / device-width >320
Apple iPad 2
  • Safari (portrait + paysage) : >180dpi / device-width >640
  • Dolphin (portrait + paysage) : >180dpi / device-width >640
  • iCab (portrait + paysage) : >180dpi / device-width >640
HTC Sensation
  • IE mobile : >220dpi / ratio >1.1 / device-width >480
HTC HD7
  • IE mobile : (NR resolution et ratio) / device-width >480
HTC Incredible S
  • Android : >250dpi / ratio >1.5 / device-width >640
HTC Desire HD
  • Navigateur intégré (portrait + paysage) : >250dpi / ratio >1.5 / device-width >600
  • Firefox (portrait) : >220dpi / ratio >1.1 / device-width >480
  • Firefox (paysage) : >220dpi / ratio >1.1 / device-width >640
  • Android (portrait) : >250dpi / ratio >1.5 / device-width >320
  • Opera mini (portrait) : >220dpi / ratio >1.1 / device-width >380
  • Opera mobile (portrait) : >220dpi / ratio >1.1 / device-width >320
  • Opera mobile (paysage) >220dpi / ratio >1.1 / device-width >480
Galaxy Nexus
  • Android (portrait) : >320dpi / ratio >2 / device-width >640
Galaxy Note
  • Android (portrait) : >320dpi / ratio >2 / device-width >640
  • Firefox (portrait) : >320dpi / ratio >2 / device-width >640
  • Opera mobile (portrait) : >320dpi / ratio >2 / device-width >320
Samsung Nexus S
  • Android (portrait) : >250dpi / ratio >1.5 / device-width >480
  • Android (paysage) : >250dpi / ratio >1.5 / device-width >640
  • Firefox (portrait) : >220dpi / ratio >1.1 / device-width >480
  • Firefox (paysage) : >220dpi / ratio >1.1 / device-width >640
LG GT540
  • Android (portrait) : >180dpi / ratio >0.7 / device-width >640
LG Optimus One
  • Navigateur intégré (portrait) : >180dpi / ratio >0.7 / device-width >320
LG 2X
  • Navigateur intégré (portrait) : >250dpi / ratio >1.5 / device-width >640
  • Firefox (portrait) : >220dpi / ratio >1.1 / device-width >480
Nokia N8
  • Symbian (portrait) : >220dpi / ratio >1.1
Motorola Milestone
  • Android (portrait) : >250dpi / ratio >1.5 / device-width >640
Samsung Omnia 7
  • IE mobile (portrait) : (NR resolution et ratio) / device-width >480
Samsung 5800 GT
  • IE mobile (portrait) : >180dpi / ratio >0.7 / device-width >240

Our Mobile Planet

Statistiques détaillées sur l’utilisation des smartphones (sources Google, Ipsos et la MMA sur une période récente). Le gros avantage est qu’il est possible de créer ses propres graphiques selon des critères souhaités (taux de pénétration, usages, géographie, etc.)

Adaptation du menu de goetter.fr sur mobiles

Moyennement fan des menus de navigation occupant toute la place de nos chers petits écrans de mobiles, je me suis amusé ce week-end à concevoir un menu coulissant pour mon site perso Goetter.fr, ainsi l’espace demeure dédié au contenu.

Le principe est que le menu est hors du champ visuel (en haut) et seul une barre et un bouton “menu” permet de le repérer.

En appuyant sur le bouton “menu”, le menu coulisse vers le bas et apparaît.

Le menu a été testé sur Android, Windows Phone 7.5 et iOS (aussi avec l’outil de lecture vocale VoiceOver). Il ne fonctionne pas sur Opera Mini et n’a pas été testé sur Opera Mobile et Blackberry, mais vu les technologies CSS3 employées il ne fonctionnera que sur des smartphones récents.

Menu rétracté :

Menu déroulé :

Qu’en pensez-vous (principe, ergonomie, accessibilité, compatibilité) ?

Quel type de navigation pour les sites mobiles ?

Les menus de navigation sont vraiment une plaie pour les périphériques mobiles, à commencer par le menu horizontal, et - le plus vicieux d’entre tous -, le menu déroulant… (même si nous proposons une solution pertinente sur Alsacréations.)

En y réfléchissant bien, chaque type de navigation est problématique dès lors que l’écran commence à se réduire : il faut non-seulement tenter de tout afficher sur une colonne, mais également agrandir la surface cliquable de chaque lien.

Et quand tout cela est enfin optimisé, il reste un dernier problème, et non des moindres : votre menu occupe à présent toute la taille de l’écran visible de votre page d’accueil !

Forcément, le menu de navigation parfait pour mobile n’existe pas, ou plutôt : il sera différent selon les cas de figure et besoins.

J’ai regroupé ici quelques idées de navigation “responsive” qui pourraient bien s’adapter à nos smartphones. Ils ont sans-doute chacun des avantages et des inconvénients…

Simple adaptation visuelle

goetter.fr

Principe :

Adaptation d’un menu classique pour le Web mobile pour obtenir un affichage sous forme de colonne avec grands boutons.

Réalisation :

Les CSS3 Media Queries sont nos amis pour appliquer une feuille de styles lorsque la taille d’écran se réduit.

Exemple en ligne :

Il y en a un peu partout, dès lors que le webdesigner a fait un premier effort de “responsive design”.

Menu poussé en bas de page

alsacréations

Principe :

La navigation est non seulement adaptée aux petits écrans, mais par un stratagème magique, elle est déplacée en bas du document. L’objectif d’afficher le contenu principal en priorité est atteint.

Réalisation :

Les techniques pour modifier l’ordre d’affichage des éléments HTML relèvent soient de spécifications en brouillon (CSS3 Flexible Model ou Grid Layout), ou de “bidouilles” telles que d’afficher un bloc comme un <tfoot> pour le reléguer en bas.

Exemple en ligne :

C’est cette dernière technique que nous avons utilisée pour http://www.alsacreations.fr

Menu remplacé par une liste select

select menu

Principe :

Le site CSS Tricks propose une idée intéressante : remplacer le menu classique par un élément HTML <select>. Ce type d’élément est généralement très ergonomique sur les smartphones.

Réalisation :

La page HTML contient les deux types d’éléments, tour à tour masqués en display none selon la largeur d’écran. Un coup de JavaScript est nécessaire pour lien les options du select aux pages correspondantes lors du pointage.

Exemple en ligne :

Un tutoriel de CSS Tricks dévoile cette technique : http://css-tricks.com/convert-menu-to-dropdown/

Menu rétractable

menu rétractable

Principe :

Une des solutions adaptée aux menus déroulants, l’idée est d’afficher le menu contracté par défaut, puis lors du clic sur un élément, de dévoiler les sous-menus afférents.

Réalisation :

Il est possible de réaliser ce type de comportement exclusivement en CSS (pour éviter une requête JavaScript ?) à l’aide de la pseudo-classe :target

Exemple en ligne :

Je me suis amusé à réaliser cet exemple : http://ie7nomore.com/fun/responsive-menu/

Menu coulissant latéral

menu coulissant

Principe :

La navigation est masquée (placée en haut ou sur le côté). Un bouton “menu” permet de faire apparaître en glissant la navigation vers la partie visible de l’écran.

Réalisation :

Le bloc de menu peut simplement être positionné en absolu ou relatif avec un décalage. Le clic sur le bouton “menu” modifie la valeur du décalage. Un petit coup de transition CSS3 et le tour est joué.

Exemple en ligne :

Voilà un exemple concret : http://ie7nomore.com/fun/responsive-menu/menu2.html

Menu coulissant vertical (ajout du 30 janvier)

Principe :

Une des (sans-doute) nombreuses variantes de la version précédente : la navigation est placée en haut de page. Seul un bandeau est visible et fixé en haut. Un bouton “menu” permet de faire apparaître en glissant la navigation vers la partie visible de l’écran.

Réalisation :

Le bloc de menu doit avoir une hauteur connue et positionné en “fixed”, puis décalé de sa hauteur. Le clic sur le bouton “menu” modifie la valeur du décalage.

Exemple en ligne :

J’ai appliqué ce principe sur mon site personnel Goetter.fr

Et sinon ?

Cette liste des “bonnes idées” de menus pour mobiles est certainement loin d’être exhaustive.
Je suis preneur d’autres bonnes suggestions, et surtout de vos retours d’expériences, notamment en ce qui concerne la compatibilité ou l’accessibilité (ARIA ?) de toutes ces techniques.

Test perso : hacks CSS et performances des sélecteurs

Avec l’émergence du “Web mobile”, le concept de performance web est en pleine ébullition : on peut comprendre que chaque milliseconde de perdue sur une connexion 3G est un désatre.

Parmi les thèmes où l’on entend tout et son contraire, on trouve l’idée de “Sélecteurs CSS efficients” qui prône l’usage de certains types de sélecteurs au détriment d’autres censés être plus coûteux en performance.

On en vient à diaboliser certains sélecteurs autrefois propres sur eux, voire certaines méthodes de commentaires conditionnels.

J’ai voulu procéder à une petite expérience personnelle pour en tirer quelques conclusions qui n’engagent que moi…

Le test

Le test se déroule ainsi : je crée 4 fichiers HTML composés d’un div de class=”lol” dans lequel se trouve un paragraphe.

Par ailleurs, au sein d’une feuille de styles externe, j’applique la propriété border-radius (reconnue pour être assez gourmande) sur le paragraphe. Le tout répété 1000 fois dans le fichier CSS !

Les seules différences entre les 4 feuilles de styles est le type de déclaration :

  1. fichier CSS 1 : 1000x un sélecteur existant + propriété existante :
    .lol p {border-radius: 1337px;}
  2. fichier CSS 2 : 1000x un sélecteur introuvable + propriété existante :
    .ie7 p {border-radius: 1337px;}
  3. fichier CSS 3 : 1000x un sélecteur existant + propriété inexistante (hack) :
    .lol p {*border-radius: 1337px;}
  4. fichier CSS 4 : 1000x un sélecteur introuvable + propriété inexistante (hack) :
    .ie7 p {*border-radius: 1337px;}

Le but du jeu est de vérifier qu’il existe bel et bien une différence de performances selon les types de sélecteurs et les propriétés.

Résultats

1 : .lol p {border-radius: 1337px;} x1000
  • Chargement des styles : 266ms
  • (Chargement total : 518ms)
  • (Chargement total sur mobile iPhone4 : 2.83s)
2 : .ie7 p {border-radius: 1337px;} x1000
  • Chargement des styles : 265ms
  • (Chargement total : 468ms)
  • (Chargement total sur mobile iPhone4 : 2.79s)
3 : .lol p {*border-radius: 1337px;} x1000
  • Chargement des styles : 360ms
  • (Chargement total : 568ms)
  • (Chargement total sur mobile iPhone4 : 2.49s)
4 : .ie7 p {*border-radius: 1337px;} x1000
  • Chargement des styles : 265ms
  • (Chargement total : 504ms)
  • (Chargement total sur mobile iPhone4 : 2.5s)

Interprétation personnelle

Ce petit test amateur ne prétend pas jouer dans la cour des grands, je n’ai déployé que de maigres moyens (Firebug pour les temps de chargement bureau, et Blaze.io pour le mobile).

Cependant, s’il n’y avait qu’une seule conclusion à en tirer, c’est que les inégalités de latence entre les sélecteurs paraîssent bien minimes, voire négligeables !

A quelques exceptions près, quel que soit le sélecteur (que le navigateur le trouve ou non) et quelle que soit la propriété (hack ou non), le temps de chargement est quasiment identique, en tout cas pour des feuilles CSS de 1000 lignes et environ 34ko.

De très légères disparités apparaissent pour les cas suivants : il semble qu’une propriété “hack” appliquée à un sélecteur existant (cas n°3) soit un peu plus coûteuse en performance pour le navigateur.

J’espère que les conditions d’expérience n’étaient pas trop biaisées et que mes déductions n’en sont pas complètement fausses.