L'un des premiers problèmes rencontrés lors de la création d'une application Web mobile à partir de zéro est la quantité d'espace utilisée par la barre d'adresse du navigateur. Ce didacticiel montrera comment récupérer les éléments de l'écran qui seraient autrement perdus dans la barre d'adresse tout en tenant compte des changements d'orientation, des problèmes de hauteur du contenu et des liens de documents internes..
Certains aspects des applications ou techniques utilisées dans ce tutoriel ont changé depuis sa publication initiale. Cela pourrait le rendre un peu difficile à suivre. Nous vous recommandons de consulter ces didacticiels plus récents sur le même sujet:
L'un des aspects les plus difficiles de la conception pour les appareils mobiles est la quantité limitée d'écran disponible. Les applications Web mobiles doivent être rationalisées et intuitives pour concurrencer les applications natives, et la présence de l'interface utilisateur du navigateur ne soustrait souvent que l'expérience utilisateur et l'esthétique du site dans son ensemble..
Par exemple, considérons la capture d'écran suivante du site Web mobile:
La capture d'écran ci-dessus a été prise sur un iPhone 4 avec la barre d'adresse et la barre d'outils de Mobile Safari affichées..
Regardez maintenant la même capture d'écran sans l'interface utilisateur du navigateur:
La version iPhone du site a gagné 60 pixels en supprimant la barre d'adresse en haut et 44 pixels en supprimant la barre de boutons en bas pour un gain total de 104 pixels logiques d'espace d'écran vertical (la quantité d'espace gagné sur les appareils Android varie , mais le résultat est similaire). Lorsque vous essayez de créer une expérience immersive, il est facile de comprendre, à partir des captures d’écran ci-dessus, ce qu’une différence aussi importante peut apporter.
Malheureusement, les principaux navigateurs Web mobiles n’ont pas encore fourni aux développeurs une méthode simple et universelle permettant d’activer ou de désactiver simplement l’interface utilisateur du navigateur. Cependant, il existe deux approches communes pour faire le travail, et les deux seront abordés dans ce tutoriel..
Si votre application Web ne cible que iOS, alors la solution idéale consiste à définir la balise méta suivante dans le partie de votre document HTML:
Cela supprimera complètement la barre d'adresse du navigateur et la barre d'outils de Mobile Safari, comme indiqué dans la deuxième capture d'écran ci-dessus..
Outre le fait que ce code sera ne fonctionne de manière fiable que sur les appareils iOS, Cette approche pose un autre problème majeur: cela ne fonctionnera que lorsque l'utilisateur aura ajouté le site Web à l'écran d'accueil et qu'il l'utilisera indépendamment de Mobile Safari..
J'ai lu des rapports non confirmés selon lesquels l'approche des balises méta fonctionnerait réellement certains Les appareils Android également, mais cela ne fonctionne certainement pas sur mon Nexus S et ne semble pas du tout officiellement pris en charge par Android.
C'est évidemment moins qu'idéal. L'ajout de sites Web à l'écran d'accueil iOS est en quelque sorte une fonctionnalité obscure d'iOS que de nombreux utilisateurs ne savent même pas qu'il est possible et qu'il est peu probable d'utiliser lors d'une navigation simple sur le Web..
Peut-être qu'un jour les fournisseurs de navigateurs vont s'unir et fournir une seule balise méta multiplateforme pour un contrôle plus fin de l'interface utilisateur du navigateur sans gêner le flux normal des applications du navigateur Web (à quoi ressemblerait la vie si cela se produisait). Jusque-là, nous devrons prendre les choses en main de la manière la plus traditionnelle: en utilisant JavaScript.
Contrepoint: Autoriser les développeurs à contrôler la présence de la barre d'adresse et / ou de la barre d'onglets confère aux développeurs une liberté créative au détriment de la liberté de l'utilisateur final et de l'expérience de navigation globale. En l'absence d'un modèle UX cohérent permettant de revenir en arrière ou de saisir une nouvelle URL, les utilisateurs perdent la confusion lors de la navigation et sont parfois incapables de quitter le site sans avoir réinitialisé complètement le navigateur..
Contre-contrepoint: La création d’un nouveau modèle UX permettant aux développeurs de déterminer la présence ou non de contrôles du navigateur tout en maintenant le contrôle de la navigation par l’utilisateur final (peut-être par la combinaison d’un effet de fondu en entrée et du geste de double frappe ou obliger les applications plein écran à se lancer dans une nouvelle fenêtre) pourrait concilier les deux intérêts.
De nombreux frameworks d'applications web multiplates-formes maintenant disponibles s'appuient désormais sur ce qui est essentiellement un piratage JavaScript pour s'approcher le plus possible d'une expérience plein écran. Les frameworks suivants incluent tous une variante de la solution JavaScript que je vais démontrer dans ce tutoriel:
Pour ceux d'entre vous qui veulent juste le code sans le récit:
J'héberge le code ci-dessus sur GitHub: Gist, alors n'hésitez pas à insérer, modifier ou suggérer des modifications. Gardez simplement à l'esprit qu'il s'agit au mieux d'un hack dépendant du navigateur. Cela pourrait changer dans le futur. Cela peut ne pas couvrir tous les cas. Il n'a pas été testé sur Blackberry et Windows Phone 7.
UPDATE 9/3/2011:
Grâce aux commentaires de John Boxall ci-dessous, j'ai ajouté une condition supplémentaire dans l'écouteur d'événements "load". le hideAddressBar ()
la fonction ne sera maintenant appelée que si l'utilisateur n'a pas commencé à faire défiler avant le déclenchement de l'événement "load".
Pour ceux d'entre vous qui veulent savoir exactement comment et pourquoi cette astuce fonctionne, lisez la suite!
En gros, le problème est ce qui peut être condensé en une seule ligne de JavaScript:
window.scrollTo (0, 1);
le faire défiler
call est une méthode du la fenêtre
objet de navigateur avec la signature suivante:
scrollTo (x, y);
Le premier argument contrôle la distance pour faire défiler la fenêtre sur l'axe des x et le deuxième argument contrôle la distance pour faire défiler la fenêtre sur l'axe des y.
Le concept général est que, bien que nous ne puissions techniquement pas supprimer les commandes du navigateur du navigateur Web, nous pouvons faire défiler le contenu de la fenêtre d'affichage afin de supprimer la barre d'adresse de la fenêtre..
Alors, pourquoi ne déplacer que le pixel de l'axe des ordonnées 1? Ne devrait-il pas s'agir de 60 pixels pour l'iPhone? C'était aussi ma pensée initiale. Cependant, la barre d'adresse ne fait pas techniquement partie de la fenêtre de visualisation du document. Plutôt que de faire défiler le contenu de 60 pixels, nous profitons d’une particularité de WebKit (bug?) Qui supprime automatiquement la barre d’adresse lorsque le faire défiler
méthode est appelée. Lors de mes tests, j’ai pu obtenir l’effet souhaité sur iOS en définissant la valeur Y sur n’importe quel entier, y compris -10, 0, 1 ou 60. Toutefois, sous Android, seuls les entiers positifs produisaient l’effet souhaité, créant ainsi "1 "le meilleur offset à utiliser pour le piratage du navigateur.
La prochaine étape consiste à déterminer quand appeler le faire défiler
méthode. Idéalement, cela devrait se produire juste après le chargement de la page. Toutes les implémentations suivantes ont fonctionné lors de mes tests et sont répertoriées par ordre d'élégance:
Ajouter un écouteur d'événement:
window.addEventListener ("load", function () window.scrollTo (0, 1););
Ajout d'un écouteur d'événement en ligne:
Dans un embarqué scénario
tag (pour ceux qui se sentent rebelles):
Si vous essayez ces trois exemples sur Android, tout devrait fonctionner à merveille (même si le troisième exemple est particulièrement laid). Cependant, si vous essayez ce qui précède sur iOS, rien ne se passera..
Pour des raisons qui ne me semblent pas tout à fait claires, Mobile Safari sur iOS est incapable d'appliquer le piratage de défilement avec l'un des écouteurs d'événement ci-dessus uniquement..
Pour que cela fonctionne sur iOS, vous devez créer un léger délai entre le moment où l'écouteur se déclenche et le moment où le
faire défiler
la méthode s'exécute.
Cela peut être facilement fait avec le setTimeout
méthode démontrée:
window.addEventListener ("load", function () setTimeout (function () window.scrollTo (0, 1);, 100);
La signature de méthode pour le setTimeout
fonction est:
setTimeout (code, millisecondes, [lang])
Donc, dans mon exemple, j'ai fourni une fonction anonyme contenant le faire défiler
appel à exécuter après un délai de 100 millisecondes. Curieusement, ce qui précède fonctionnait toujours pour moi, quel que soit le nombre entier prévu pour le délai en millisecondes. Cela a fonctionné avec -100, 0 et 1 aussi bien que 100. Par conséquent, ma recommandation est d'utiliser 0 pour l'argument millisecondes..
À ce stade, notre barre d'adresse masquant l'extrait JavaScript devrait ressembler à l'un des exemples suivants:
Écouteur d'événement:
Test plein écran
Écouteur d'événements en ligne:
Génial! Alors maintenant, nous pouvons construire quelque chose d’utile, non? Malheureusement non. Il y a encore plusieurs problèmes spécifiques au navigateur qui peuvent encrasser ce hack.
Que faire si votre contenu n'est pas assez volumineux pour remplir tout l'écran? Dans ce cas, vous n’avez pas de barre de défilement verticale et l’astuce présentée ci-dessus ne fonctionnera pas. En plus d'ajouter simplement plus de contenu à votre page, il existe au moins trois autres méthodes moins restrictives que vous pouvez utiliser pour traiter ce problème..
Échelle initiale
La première approche consiste à modifier le échelle initiale
de votre page Web jusqu'à ce que votre contenu remplisse la totalité de la fenêtre d'affichage. Vous pouvez le faire avec la balise Meta suivante:
Vous devrez jouer avec la valeur d'échelle initiale jusqu'à ce que vous trouviez la quantité d'échelle / zoom correspondant à vos besoins spécifiques..
La deuxième approche consiste à utiliser un attribut CSS simple. Vous pouvez appliquer un suffisamment grand hauteur min
valeur à la corps
balise ou tout autre élément de niveau bloc sur votre page pour tenir compte de l’espace blanc vide. Cependant, vous devez faire attention ici pour deux raisons: la valeur exacte du pixel requise par le hauteur min
attribut variera en fonction de la échelle initiale
(c.-à-d. zoom) de la page et la valeur changera si l’utilisateur passe du mode portrait au mode paysage ou inversement. La syntaxe de base pour définir l'attribut min-height sur la balise body est indiquée ci-dessous:
corps min-height: 900px;
Encore une fois: la valeur de pixel réelle utilisée dépend de l'échelle / du zoom initial de votre site. Vous devrez peut-être aller assez haut ou assez bas.
La troisième approche consiste à vérifier de manière dynamique la document.height
propriété contre window.outerHeight
propriété, puis augmenter dynamiquement la taille de document.height
quand c'est nécessaire.
Suivre l'extrait de code JavaScript est une solution non-structurée à ce problème:
Aux lignes 5 ci-dessus, j'ai ajouté une quantité de remplissage apparemment arbitraire (+50). Cela était nécessaire pour que l'effet fonctionne à la fois sur iOS et sur Android. J'ai également dû repositionner l'appel à setTimeout
comme iOS ne produirait pas le défilement automatique immédiatement après le réglage document.body.style.height
. Ce que j’ai trouvé particulièrement étrange, c’est que non seulement je devais repositionner le setTimeout
appeler, mais pour iOS, je devais également ajouter un délai apparemment arbitraire de +50 si je venais de changer la hauteur du document. Ce n’était pas le cas initialement (lors de l’utilisation de la charge
écouteur sans définir une nouvelle valeur pour la hauteur du document).
Des variantes du piratage de navigateur ci-dessus sont déjà largement implémentées sur le Web. Cependant, il existe au moins un cas d'utilisation dans lequel forcer le navigateur à faire défiler la liste jusqu'à 0,1 correspond exactement à la mauvaise approche: les visiteurs accédant à votre site via un lien d'ancrage (a.k.a interne). Pour prendre en charge ce cas, il suffit d'appeler scrollTo (0, 1)
si la balise de hachage n'est pas présente dans l'URL. Pour mettre en œuvre cette approche, il suffit de vérifier la présence d’une valeur dans window.location.hash
et ensuite envelopper notre charge
écouteur d'événement dans ce conditionnel. Cela nous laisse avec quelque chose comme ce qui suit:
if (! window.location.hash) window.addEventListener ("load", function () if (document.height <= window.outerHeight + 10) document.body.style.height = (window.outerHeight + 50) +'px'; setTimeout( function() window.scrollTo(0, 1); , 50 ); else setTimeout( function() window.scrollTo(0, 1); , 0 ); );
Un autre problème que vous pouvez rencontrer concerne les changements d'orientation de l'appareil. Sur iOS, lorsqu'un utilisateur fait pivoter le téléphone du mode portrait au mode paysage, le décalage de défilement ne sera pas modifié automatiquement (Android ne semble pas souffrir de ce problème). Cela signifie que votre utilisateur sera laissé quelque part plus bas sur la page que prévu.
La solution à cela est de définir un écouteur d'événements sur window.onorinationchange
pour être averti lorsque l’orientation change, puis pour exécuter le window.scrollTo (0, 1)
rappeler après le changement.
Cela semble être un bon moment pour commencer à refactoriser le code en scindant le code chargé de cacher la barre d'adresse dans une fonction indépendante. Après cela, nous nous retrouvons avec ce qui suit:
fonction hideAddressBar () if (! window.location.hash) if (document.height <= window.outerHeight + 10) document.body.style.height = (window.outerHeight + 50) +'px'; setTimeout( function() window.scrollTo(0, 1); , 50 ); else setTimeout( function() window.scrollTo(0, 1); , 0 ); window.addEventListener("load", hideAddressBar ); window.addEventListener("orientationchange", hideAddressBar );
La solution ci-dessus semble bien fonctionner pour moi sur Android et iOS, mais il y a un autre problème qui peut ou peut ne pas être pertinent pour votre projet: que se passera-t-il si l'utilisateur a fait défiler de manière significative la page avant de modifier l'orientation de l'appareil? Dans ce cas, réinitialiser l'affichage à 0, 1 ferait perdre à l'utilisateur sa place dans le document. La comptabilisation dépend fortement de l'implémentation, mais l'essentiel consiste simplement à définir un seuil d'axe des y, puis à réinitialiser le décalage de défilement à 0, 1 si l'utilisateur n'a pas déjà fait défiler au-delà de ce seuil..
Certains frameworks, tels que SenchaTouch, verrouillent la barre d’adresses en dehors de l’écran en empêchant l’utilisateur de faire défiler au-delà d’un seuil donné de l’axe des y. C'est certainement possible, mais je ne discuterai pas comment le faire ici, car je trouve que cette solution pose un problème important de convivialité, en particulier sur Android. Cependant, si vous êtes déterminé à obtenir cet effet, vous devrez probablement expérimenter avec window.pageYOffset
attribut.
À ma connaissance, il n’existe actuellement aucune solution permettant de supprimer la barre d’outils / la barre de boutons sous iOS du bas de Safari mobile avec JavaScript uniquement. La seule façon dont je suis au courant pour obtenir cet effet est la méthode des balises méta expliquée au début de ce didacticiel. Corrige moi si je me trompe!
La manière de gérer les utilisateurs visitant un navigateur Web non mobile ou non pris en charge est un élément à prendre en compte dans l’approche susmentionnée. Il existe différentes méthodes pour déterminer quel navigateur accède actuellement à votre site. Si vous utilisez un langage de script côté serveur, vous souhaiterez peut-être déterminer si l'utilisateur se trouve sur un appareil mobile au moment de la génération de la page et ne fournir ce hack que lorsque cela sera nécessaire. Une approche plus robuste consisterait peut-être à effectuer les tests de manière dynamique avec JavaScript. L'application de cette considération dépasse le cadre de ce didacticiel, mais veuillez laisser vos suggestions dans les commentaires..
Les hacks de navigateur comme celui que j'ai décrit pour masquer la barre d'adresse défient les meilleures pratiques. L'implémentation que j'ai expliquée dans ce tutoriel a été testée sur un Android Nexus S, un iPhone 3GS et un iPhone 4, mais il est fort possible que j'ai raté un cas particulier. De plus, je ne suis pas du tout certain que la mise en œuvre affichée continuera à fonctionner telle quelle dans le futur. C’est pourquoi j’ai été assez surpris de trouver autant d’infrastructures Web primaires (par exemple, iUI, jQuery Mobile, SenchaTouch) et des sites Web (par exemple, Gmail, Yahoo, Apple) s’appuyant sur une variante personnalisée de ce hack. Je pense que la raison en est simple: il n’existe pas actuellement de meilleure solution non javascript..
J'avais trois intentions principales en écrivant un tutoriel aussi approfondi sur ce qui peut sembler une question triviale.
Tout d'abord, je souhaitais fournir un extrait de code JavaScript pur pour obtenir cet effet plus robuste que la plupart des autres que j'ai rencontrés. J'espère que j'ai réussi à le faire en tenant compte des changements d'orientation, des liens d'ancrage et des problèmes de contenu..
Deuxièmement, je voulais dissiper une partie de la magie derrière la manière dont des frameworks tels que SenchaTouch ou iUI ont rendu cet effet possible. Lorsque j'ai initialement décidé d'utiliser SenchaTouch pour un projet indépendant, il y a quelque temps, la "magie" du cadre permettant de faire remplir les applications de l'écran était l'un des principaux effets UX qui m'intéressait. Il est important de réaliser que ce même effet peut être facilement implémenté dans JS pur, que vous choisissiez ou non d'utiliser un framework JavaScript dans votre projet..
Enfin, la raison principale pour laquelle j'ai voulu aborder ce problème avec une telle précision est la prise de conscience de la versatilité de cette approche. Malgré le fait que des variantes de cette astuce ont été largement adoptées, je pense qu’il s’agit au mieux d’un kludge inélégant et, au pire, d’un hack peu fiable dépendant du navigateur et susceptible de ne pas continuer à fonctionner à l’avenir. Je voudrais exhorter les acteurs de l'industrie des navigateurs et de la communauté de développement Web / mobile dans leur ensemble à faire pression pour une approche plus indépendante, basée sur des standards JavaScript et plus indépendante, pour traiter cette considération UX. Je pense que la méthode de méta-tag mise en œuvre par Apple est un grand pas dans la bonne direction, mais, comme mentionné ci-dessus, elle ne répond pas suffisamment aux besoins de la communauté du développement..
La vraie question est: qu'en pensez-vous? Parlons-en dans la section commentaires ci-dessous.
Je ne doute pas que certains de nos lecteurs pourront peut-être améliorer le code que j'ai fourni dans ce tutoriel. Si vous voyez quelque chose dans ce message qui pourrait être optimisé ou amélioré, veuillez laisser vos commentaires ci-dessous! Vous pouvez également me joindre via Twitter (@markhammonds), bien que cela me prenne parfois de temps en temps de répondre à des tweets ou des DM. Le meilleur moyen de me joindre est soit dans les commentaires ci-dessous, soit via le formulaire de contact sur Mobileuts +. Si j'accepte l'une de vos suggestions d'amélioration, je mettrai à jour ce post et citerai votre nom ou votre pseudonyme.!
Je ne veux pas me croire sur parole?
Consultez les ressources suivantes sur lesquelles je suis tombé lors de la recherche sur ce poste: