Web-apps op volledig scherm

Een van de eerste problemen bij het volledig opnieuw bouwen van een mobiele web-app is de hoeveelheid ruimte die wordt verbruikt door de adresbalk van de browser. Deze zelfstudie laat zien hoe u het scherm dat op een andere manier verloren is gegaan in de adresbalk terugwint, terwijl u rekening houdt met oriëntatiewijzigingen, problemen met de inhoudshoogte en interne documentkoppelingen.

Latere wijzigingen in technieken & software

Bepaalde aspecten van toepassingen of technieken die in deze zelfstudie worden gebruikt, zijn gewijzigd sinds de publicatie oorspronkelijk werd gepubliceerd. Dit maakt het misschien een beetje moeilijk om mee te volgen. We raden u aan deze meer recente zelfstudies over hetzelfde onderwerp te bekijken:

  • Mobiletuts + Web Apps-categorie

Het probleem definiëren

Een van de moeilijkste aspecten van ontwerpen voor mobiele apparaten is de beperkte hoeveelheid beschikbare schermruimte. Mobiele webapplicaties moeten gestroomlijnd en intuïtief zijn om te kunnen concurreren met native applicaties, en de aanwezigheid van de gebruikersinterface van de browser wordt vaak alleen afgetrokken van de gebruikerservaring en de esthetiek van de site als geheel.

Bekijk bijvoorbeeld de volgende schermafbeelding van een mobiele website:

De bovenstaande schermafbeelding is gemaakt op een iPhone 4 met zowel de adresbalk van de mobiele Safari als de werkbalk weergegeven.

Bekijk nu dezelfde schermafbeelding zonder de gebruikersinterface van de browser:

De iPhone-versie van de site kreeg 60 pixels door de adresbalk aan de bovenkant en 44 pixels te verwijderen door de knoppenbalk onderaan te verwijderen voor een totale winst van 104 logische pixels van verticale schermruimte (de hoeveelheid ruimte die wordt verdiend op Android-apparaten varieert , maar het resultaat is vergelijkbaar). Wanneer je probeert een meeslepende ervaring op te bouwen, kun je aan de hand van de screenshots eenvoudig zien wat een groot verschil zo'n kleine verandering kan maken.

Helaas hebben de belangrijkste mobiele webbrowsers ontwikkelaars nog geen eenvoudige en universele methode geboden om de gebruikersinterface van de browser in of uit te schakelen. Er zijn echter twee gemeenschappelijke benaderingen om de klus te klaren, en beide zullen in deze tutorial aan de orde komen.

De metatagbenadering

Als uw web-app alleen op iOS is gericht, dan is de ideale oplossing om de volgende metatag in te stellen in de gedeelte van uw HTML-document:

 

Als u dit doet, worden zowel de adresbalk van de browser als de werkbalk volledig verwijderd uit Mobile Safari, zoals wordt weergegeven in de tweede schermafbeelding hierboven.

In aanvulling op het feit dat deze code zal werkt alleen betrouwbaar op iOS-apparaten, er is nog een groot probleem met deze aanpak: het werkt alleen nadat de gebruiker de website heeft toegevoegd aan het startscherm en wanneer de gebruiker de site start, onafhankelijk van Mobile Safari.

Ik heb onbevestigde rapporten gelezen dat de metatagaanpak echt zal werken sommige Android-apparaten ook, maar het werkt zeker niet op mijn Nexus S en lijkt helemaal niet officieel door Android te worden ondersteund.

Dit is duidelijk minder dan ideaal. Het toevoegen van websites aan het startscherm van iOS is een enigszins obscure iOS-functie waarvan veel gebruikers niet eens weten dat het mogelijk is en die waarschijnlijk niet zullen worden gebruikt terwijl ze op internet surfen..

Misschien zullen browsers op een dag zich verenigen en een enkele platformonafhankelijke metatag leveren voor een fijnmazig beheer van de gebruikersinterface van de browser zonder de normale stroom van webbrowsertoepassingen te belemmeren (hoe het leven zou zijn als dit daadwerkelijk zou gebeuren). Tot die tijd zullen we de ouderwetse manier van werken in goede handen moeten nemen: door JavaScript te gebruiken.

Contrapunt: Door ontwikkelaars in staat te stellen de aanwezigheid van de adresbalk en / of tab-balk te beheren, krijgen ontwikkelaars creatieve vrijheid ten koste van de vrijheid van eindgebruikers en de algemene browse-ervaring. Zonder een consistent UX-patroon om terug te navigeren of een nieuwe URL in te voeren, raken gebruikers tijdens het browsen in verwarring en in sommige gevallen niet in staat om de site te verlaten zonder de browser volledig opnieuw in te stellen.

Counter-contrapunt: Een nieuw UX-patroon maken dat ontwikkelaars in staat stelt om de aanwezigheid of afwezigheid van browserbesturingselementen te bepalen en tegelijkertijd de controle door eindgebruikers over de navigatie te behouden (misschien door een combinatie van een fade-in-out effect en de 'double-tap'-beweging of misschien door dwingen om apps op volledig scherm te starten in een nieuw venster) zou een evenwicht kunnen vinden tussen beide interesses.

De JavaScript-benadering

Veel van de platformonafhankelijke webapp-frameworks die nu beschikbaar zijn, zijn gaan vertrouwen op wat in wezen een JavaScript-hack is om zo dicht mogelijk bij een volledig schermervaring te komen. De volgende frameworks bevatten allemaal een variatie op de JavaScript-oplossing die ik in deze tutorial zal demonstreren:

  • IUI
  • SenchaTouch
  • jQuery Mobile

Voor degenen onder u die gewoon de code willen zonder het verhaal:

Ik ontvang de bovenstaande code op GitHub: Gist, dus voel je vrij om te wijzigen, of wijzigingen aan te brengen. Houd er rekening mee dat dit op zijn best een browserafhankelijke hack is. Het kan in de toekomst veranderen. Het is mogelijk dat niet elke randbehuizing wordt bedekt. Het is niet getest op Blackberry en Windows Phone 7.

UPDATE 9/3/2011:
Dankzij de feedback van John Boxall hieronder, heb ik nog een voorwaardelijke toegevoegd in de listener van de "load" -gebeurtenis. De hideAddressBar () functie wordt nu alleen aangeroepen als de gebruiker niet is begonnen met scrollen voordat de gebeurtenis "load" wordt geactiveerd.

Voor degenen onder u die willen weten hoe en waarom dit handige trucje werkt, lees verder!

Venturing down the Rabbit Hole

In wezen komt de truc neer op wat kan worden samengevat in een enkele regel JavaScript:

 window.scrollTo (0, 1);

De scrollTo oproep is een methode van de venster browserobject met de volgende handtekening:

 scrollTo (x, y);

Het eerste argument bepaalt de afstand om door het venster op de x-as te schuiven en het tweede argument bepaalt de afstand om door het venster op de y-as te schuiven.

Het algemene concept is dat, hoewel we de bedieningselementen van de browser niet technisch van de webbrowser kunnen verwijderen, we de inhoud van het kijkvenster kunnen schuiven om de adresbalk uit het venster te verwijderen.

Dus waarom zou je alleen de Y-as 1 pixel verplaatsen? Moet het niet 60 pixels zijn voor de iPhone? Dat was ook mijn eerste gedachte. De adresbalk is echter technisch gezien geen onderdeel van het documentvenster. In plaats van de inhoud 60 pixels omlaag te scrollen, profiteren we eigenlijk van een eigenlijke WebKit-fout (bug?) Die de adresbalk automatisch verwijdert wanneer de scrollTo methode wordt genoemd. In mijn testen was ik in staat om het gewenste effect op iOS te bereiken door de Y-waarde in te stellen op een geheel getal, waaronder -10, 0, 1 of 60. Op Android bereikten echter alleen positieve gehele getallen het gewenste effect, waardoor "1 "de beste Y-offset om te gebruiken voor de browser-hack.

De volgende stap is om te bepalen wanneer de scrollTo methode. Idealiter zou dit moeten gebeuren net nadat de pagina is geladen. Alle volgende implementaties werkten in mijn testen en worden weergegeven in volgorde van elegantie:

Een gebeurtenislistener toevoegen:

 window.addEventListener ("load", function () window.scrollTo (0, 1););

Een inline gebeurtenislistener toevoegen:

 

Binnen een embedded script tag (voor degenen die zich rebels voelen):

   

Als je alle drie deze voorbeelden in Android uitprobeert, zou het probleemloos moeten werken (ook al is het derde voorbeeld bijzonder lelijk). Als u echter het bovenstaande probeert op iOS, gebeurt er niets.

Om redenen die mij niet helemaal duidelijk zijn, is Mobile Safari op iOS niet in staat om de scroll-hack toe te passen met een van de bovenstaande gebeurtenislisteners alleen.

Om dit op iOS te laten werken, moet u een kleine vertraging aanbrengen tussen het moment waarop de gebeurtenislistener begint te branden en wanneer scrollTo methode wordt uitgevoerd.

Dit kan eenvoudig worden gedaan met de setTimeout methode zoals aangetoond:

 window.addEventListener ("load", function () setTimeout (function () window.scrollTo (0, 1);, 100);

De methodehandtekening voor de setTimeout functie is:

 setTimeout (code, milliseconden, [taal])

Dus in mijn voorbeeld gaf ik een anonieme functie met de scrollTo oproep die moet worden uitgevoerd na een vertraging van 100 milliseconden. Vreemd genoeg werkte het bovenstaande nog steeds voor mij, ongeacht het gehele getal voor de vertraging van milliseconden. Het werkte met -100, 0 en 1 net zo goed als 100. Daarom is mijn aanbeveling om 0 te gebruiken voor het argument van milliseconden.

Op dit moment moet onze adresbalk die het JavaScript-fragment verbergt, er ongeveer uitzien als een van de volgende voorbeelden:

Evenement luisteraar:

  Fullscreen-test 

Inline gebeurtenislistener:

 

Super goed! Dus nu kunnen we doorgaan met het daadwerkelijk bouwen aan iets nuttigs, toch? Jammer genoeg niet. Er zijn nog steeds verschillende browserspecifieke problemen die deze hack kunnen verstoren.

Onvoldoende contenthoogte

Wat als uw inhoud niet groot genoeg is om het volledige scherm te vullen? In dat geval heeft u geen verticale schuifbalk en werkt de hierboven getoonde truc niet. Naast het eenvoudigweg toevoegen van meer inhoud aan uw pagina, zijn er minstens drie andere minder beperkende methoden die u kunt nemen om dit probleem op te lossen.

Optie 1: stel de Initial-Scale

De eerste benadering is om de eerste schaal van uw webpagina totdat uw inhoud het volledige venster vult. U kunt dit doen met de volgende metatag:

 

Je zult moeten spelen met de initiële schaalwaarde totdat je de schaal / zoomfactor vindt die overeenkomt met je specifieke behoeften.

Optie 2: een minimumhoogte instellen

De tweede benadering is om een ​​eenvoudig CSS-kenmerk te gebruiken. Je kunt een voldoende grote toepassen min-height waarde voor de lichaam tag of een ander blokniveau-element op uw pagina om rekening te houden met de lege witruimte. U moet hier echter om twee redenen voorzichtig zijn: de exacte pixelwaarde die nodig is voor de min-height attribuut zal variëren afhankelijk van de eerste schaal (d.w.z. zoom) van de pagina en de waarde zal veranderen als de gebruiker van staande naar liggende modus roteert of vice versa. De basissyntaxis voor het instellen van het kenmerk min-height op de body-tag wordt hieronder weergegeven:

 body min-height: 900px; 

Nogmaals: de werkelijke pixelwaarde die wordt gebruikt, is afhankelijk van de initiële schaal / zoom van uw site. Misschien moet je behoorlijk hoog of vrij laag gaan.

Optie 3: dynamisch de hoogte instellen met JavaScript

De derde benadering is om dynamisch de document.height eigendom tegen de window.outerHeight eigenschap en verhoog vervolgens dynamisch de grootte van document.height wanneer nodig.

Het volgen van JavaScript-codefragmenten is een niet-framework-oplossing voor dit probleem:

 

Op regels 5 hierboven heb ik een schijnbaar willekeurige hoeveelheid padding toegevoegd (+50). Dit was nodig om het effect op zowel iOS als Android te laten werken. Ik heb ook de oproep opnieuw moeten plaatsen setTimeout omdat iOS de automatische scroll niet meteen na het instellen zou produceren document.body.style.height. Wat ik vooral vreemd vond, was dat ik niet alleen het setTimeout call, maar voor iOS moest ik ook een schijnbaar willekeurige vertraging van +50 toevoegen als ik net de documenthoogte had veranderd. Dit was aanvankelijk niet het geval (bij gebruik van de laden luisteraar zonder een nieuwe waarde in te stellen voor de documenthoogte).

Interne / ankerlinks

Variaties op de bovenstaande browserhack zijn al op grote schaal geïmplementeerd op internet. Er is echter ten minste één use-case waarbij het dwingen van de browser om naar 0,1 te scrollen precies de verkeerde benadering is: bezoekers die naar uw site komen via een anker (interne a.k.a.) -link. Om deze edge case op te vangen, moet u alleen bellen scrollTo (0, 1) als de hash-tag niet aanwezig is in de URL. Om deze aanpak te implementeren, hoeven we alleen maar te kijken naar de aanwezigheid van een waarde in window.location.hash en pak dan onze laden gebeurtenislistener binnen dat voorwaardelijke. Als we dit doen, hebben we zoiets als het volgende:

 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 );   ); 

Wijzigingen apparaatoriëntatie

Een ander probleem dat u kunt tegenkomen, heeft betrekking op veranderingen in de apparaatoriëntatie. Op iOS, wanneer een gebruiker de telefoon van de portretmodus naar de liggende modus roteert, wordt de scroll-offset niet automatisch gewijzigd (Android lijkt dit probleem niet te hebben). Dit betekent dat uw gebruiker ergens anders op de pagina wordt achtergelaten dan bedoeld.

De oplossing hiervoor is om een ​​gebeurtenislistener in te stellen window.onorientationchange om op de hoogte gebracht te worden wanneer de oriëntatie verandert, en dan om de window.scrollTo (0, 1) bel opnieuw nadat de wijziging heeft plaatsgevonden.

Dit lijkt een goed moment om te beginnen met het herschrijven van de code door de code te splitsen die verantwoordelijk is voor het daadwerkelijk verbergen van de adresbalk in een onafhankelijke functie. Nadat we dit gedaan hebben, blijven we achter met het volgende:

 function 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 );

De bovenstaande oplossing lijkt goed voor mij te werken op zowel Android als iOS, maar er is nog een probleem dat al dan niet relevant is voor uw project: wat als de gebruiker aanzienlijk naar beneden is gescrold op de pagina voordat de apparaatoriëntatie werd gewijzigd? In dat geval zou het resetten van het display naar 0, 1 ervoor zorgen dat de gebruiker zijn plaats in het document verliest. De boekhouding hiervoor is zeer specifiek voor de implementatie, maar de essentie is om eenvoudig een y-asdrempel in te stellen en vervolgens de schuifoffset alleen naar 0, 1 te resetten als de gebruiker nog niet voorbij die drempel heeft gescrold.

Vergrendelen van de adresbalk buiten beeld

Sommige frameworks, zoals SenchaTouch, vergrendelen de adresbalk feitelijk van het scherm af door te voorkomen dat de gebruiker voorbij een bepaalde y-asdrempel scrolt. Dit is zeker mogelijk, maar ik zal hier niet bespreken hoe dit te doen, omdat ik deze oplossing als een aanzienlijk gebruiksprobleem vind, vooral op Android. Als u echter vastbesloten bent dit effect te bereiken, moet u waarschijnlijk met het experiment experimenteren window.pageYOffset attribuut.

Hoe zit het met de knoppenbalk op iOS?

Bij mijn weten is er momenteel geen oplossing voor het verwijderen van de werkbalk / knoppenbalk op iOS vanaf de onderkant van Mobile Safari met alleen JavaScript. De enige manier waarop ik me bewust ben om dit effect te bereiken, is de metatagbenadering die aan het begin van deze tutorial is uitgelegd. Verbeter mij als ik het fout heb!

Het voorwaardelijk maken

Een overweging met de bovenstaande benadering die nog niet is besproken, is hoe om te gaan met gebruikers die een niet-mobiele of niet-ondersteunde webbrowser bezoeken. Er zijn een aantal verschillende methoden om te bepalen welke browser momenteel toegang tot uw site heeft. Als u met een scriptingtaal aan de serverzijde werkt, wilt u misschien bepalen of de gebruiker zich op een mobiel apparaat bevindt op het moment dat de pagina wordt gegenereerd en deze hack indien nodig alleen aanbieden. Misschien is een meer robuuste aanpak om de tests dynamisch met JavaScript uit te voeren. Het toepassen van deze overweging valt buiten het bestek van deze zelfstudie, maar laat uw suggesties achter in de opmerkingen.

Waarschuwing Emptor!

Browser-hacks zoals ik heb beschreven om de best practices van de adresbalk te verbergen. De implementatie die ik in deze tutorial heb uitgelegd, is getest op een Android Nexus S, iPhone 3GS en een iPhone 4, maar het is goed mogelijk dat ik ergens een randcase heb gemist. Ik ben er ook helemaal niet zeker van dat de weergegeven implementatie gewoon zal blijven werken in de toekomst. Daarom was ik behoorlijk verrast dat ik zoveel van de primaire webframeworks (bijv. IUI, jQuery Mobile, SenchaTouch) en prominente websites (bijv. Gmail, Yahoo, Apple) die afhankelijk zijn van een aangepaste variant van deze hack. De reden, denk ik, is simpel: er bestaat op dit moment geen betere, niet-javascript-oplossing.

Afronden

Ik had drie hoofdintenties bij het schrijven van een dergelijke diepgaande zelfstudie over wat een triviaal probleem lijkt.

Ten eerste wilde ik een puur JavaScript-fragment leveren om dit effect te bereiken dat robuuster is dan de meeste anderen die ik ben tegengekomen. Ik hoop dat ik dat heb bereikt door tegemoet te komen aan oriëntatiewijzigingen, ankerkoppelingen en problemen met inhoudslengte.

Ten tweede wilde ik een deel van de magie achterhalen waarom frameworks zoals SenchaTouch of iUI dit effect mogelijk hebben gemaakt. Toen ik in eerste instantie besloot om SenchaTouch enige tijd geleden voor een freelance-project te gebruiken, was de 'magie' van het framework voor het vullen van apps het scherm dat een van de primaire UX-effecten was die me aansprak. Het is belangrijk om te beseffen dat ditzelfde effect eenvoudig kan worden geïmplementeerd in pure JS, ongeacht of u ervoor kiest om een ​​JavaScript-framework in uw project te gebruiken.

Ten slotte was de belangrijkste reden dat ik dit probleem zo gedetailleerd wilde bespreken, het verhogen van het bewustzijn voor hoe wispelturig deze benadering werkelijk is. Ondanks het feit dat variaties van deze truc op grote schaal zijn aangenomen, geloof ik dat het op zijn minst een onelegant kludge is en in het slechtste geval een onbetrouwbare browserafhankelijke hack die in de toekomst wel of niet kan blijven werken. Ik zou graag degenen in de browsergemeenschap en de web / mobiele ontwikkelgemeenschap als geheel willen aansporen om te streven naar een meer op standaarden gebaseerde, JavaScript-onafhankelijke benadering voor het omgaan met deze UX-overweging. Ik denk dat de metatag-methode die Apple heeft geïmplementeerd een grote stap in de goede richting is, maar, zoals hierboven vermeld, het voldoet niet voldoende aan de behoeften van de ontwikkelingsgemeenschap.

De echte vraag is: wat denk je? Laten we erover praten in het commentaargedeelte hieronder.

Verbeter deze code

Ik twijfel er niet aan dat sommige van onze lezers mogelijk de code die ik in deze tutorial heb verstrekt, kunnen verbeteren. Als je iets in dit bericht ziet dat kan worden geoptimaliseerd of verbeterd, laat je feedback hieronder staan! Je kunt me ook bereiken via Twitter (@markhammonds), hoewel het me soms een tijdje kost om op Tweets of DM's te reageren. De beste manier om mij te bereiken is in de onderstaande opmerkingen of met het contactformulier op Mobileuts +. Als ik een van uw suggesties voor verbetering accepteer, zal ik deze post bijwerken en uw naam of behandeling citeren!

Referenties

Ik wil mijn woord niet geloven voor wat dan ook?

Bekijk de volgende bronnen die ik tegenkwam tijdens het onderzoeken van dit bericht:

  • Webtoepassingen configureren, Safari Developer Library
  • "Mobifying" Uw HTML5-site, Eric Bidelman
  • Verberg de adresbalk in Mobile Web Applications, David Walsh
  • iPhone WebApps 101: Safari uit de weg, Niels Leenheer