iOS 8 a supprimé la propriété d'affichage «minimal-ui», existe-t-il d'autres solutions «plein écran souple»?


194

(Il s'agit d'une question en plusieurs parties, je ferai de mon mieux pour résumer le scénario.)

Nous construisons actuellement une application Web réactive (lecteur de nouvelles) qui permet aux utilisateurs de glisser entre les contenus à onglets, ainsi que de faire défiler verticalement à l'intérieur de chaque contenu à onglets.

Une approche courante du problème consiste à avoir un wrapper divqui remplit la fenêtre du navigateur, défini overflowsur hiddenou auto, puis fait défiler horizontalement et / ou verticalement à l'intérieur.

Cette approche est excellente mais présente un inconvénient principal: la hauteur du document étant exactement la même que celle de la fenêtre du navigateur, le navigateur mobile ne masquera pas la barre d'adresse / le menu de navigation .

Il existe de nombreux hacks et propriétés de fenêtre d' affichage qui nous permettent d'obtenir plus d'espace d'écran, mais aucun n'est aussi efficace que minimal-ui(introduit dans iOS 7.1).

La nouvelle est arrivée hier que iOS 8 beta4 avait été supprimé minimal-uide Mobile Safari (voir la section Webkit dans les notes de publication d'iOS 8 ), ce qui nous a laissé nous demander:

Q1. Est-il toujours possible de masquer la barre d'adresse sur Mobile Safari?

À notre connaissance, iOS 7 ne répond plus au window.scrollTopiratage, cela suggère que nous devons vivre avec le plus petit espace d'écran, à moins que nous n'adoptions une disposition verticale ou une utilisation mobile-web-app-capable.

Q2. Est-il toujours possible d'avoir une expérience de plein écran douce similaire?

Par plein écran doux, je veux vraiment dire sans utiliser la mobile-web-app-capablebalise meta.

Notre application Web est conçue pour être accessible, n'importe quelle page peut être mise en signet ou partagée à l'aide du menu du navigateur natif. En ajoutant, mobile-web-app-capablenous empêchons les utilisateurs d'invoquer un tel menu (lorsqu'il est enregistré sur l'écran d'accueil), ce qui déroute et contrarie les utilisateurs.

minimal-uiAuparavant, c'était le juste milieu, cachant le menu par défaut mais le gardant accessible d'un simple toucher - bien qu'Apple l'ait peut-être supprimé en raison d'autres problèmes d'accessibilité (tels que les utilisateurs ne sachant pas où appuyer pour activer le menu).

Q3. Une expérience plein écran en vaut-elle la peine?

Il semblerait qu'une API plein écran n'arrive pas bientôt sur iOS, mais même si c'est le cas, je ne vois pas comment le menu restera accessible (il en va de même pour Chrome sur Android).

Dans ce cas, nous devrions peut-être laisser le safari mobile tel quel et tenir compte de la hauteur de la fenêtre (pour iPhone 5+, il s'agit de 460 = 568-108, où 108 comprend la barre du système d'exploitation, la barre d'adresse et le menu de navigation; pour iPhone 4 ou plus âgé, il est de 372).

J'adorerais entendre des alternatives (en plus de créer une application native).


voir stackoverflow.com/questions/18793072/ ... pour plus de détails sur les raisons pour lesquelles minimal-ui peut être crucial pour certaines applications.
bitinn

1
J'ai rencontré le même problème sur iOS 7, car nous cherchons à créer une application Web avec des événements de balayage / défilement, mais nous avons testé les événements onScroll sur iOS8 Beta 4 et .. ils fonctionnent. ios8-scroll-events.heroku.com Je ne sais pas si cela aide du tout mais .. vous avez cela pour vous.
Devin McInnis

Ran dans le même problème. Pour le moment, seul le javascript "fix", comme la fonction calc () ci-dessous est la seule réponse. Veuillez garder ce fil à jour, si vous connaissez une meilleure décision. Meilleures salutations.
A1exandr

Réponses:


88

La propriété viewport minimal-ui n'est plus prise en charge dans iOS 8. Cependant, le minimal-ui lui-même n'est pas parti. L'utilisateur peut entrer le minimal-ui avec un geste "toucher-glisser vers le bas".

Il existe plusieurs conditions préalables et obstacles pour gérer l'état d'affichage, par exemple pour que minimal-ui fonctionne, il doit y avoir suffisamment de contenu pour permettre à l'utilisateur de faire défiler; pour que minimal-ui persiste, le défilement de la fenêtre doit être décalé lors du chargement de la page et après le changement d'orientation. Cependant, il n'y a aucun moyen de calculer les dimensions du minimal-ui en utilisant la screenvariable, et donc aucun moyen de dire à l'avance quand l'utilisateur est dans le minimal-ui.

Ces observations sont le résultat de recherches menées dans le cadre du développement de Brim - gestionnaire de vues pour iOS 8 . L'implémentation finale fonctionne de la manière suivante:

Lorsque la page est chargée, Brim crée un élément de tapis roulant. L'élément du tapis roulant est utilisé pour donner à l'utilisateur de l'espace pour faire défiler. La présence de l'élément du tapis de course garantit que l'utilisateur peut accéder à la vue minimal-ui et qu'elle continue de persister si l'utilisateur recharge la page ou change l'orientation de l'appareil. Il est invisible pour l'utilisateur tout le temps. Cet élément a un ID brim-treadmill.

Lors du chargement de la page ou après avoir changé l'orientation, Brim utilise Scream pour détecter si la page est dans la vue minimal-ui (la page qui était auparavant en minimal-ui et qui a été rechargée restera dans le minimal-ui si la hauteur du contenu est supérieure à la hauteur de la fenêtre).

Lorsque la page est dans le minimal-ui, Brim désactivera le défilement du document (il le fait d'une manière sûre qui n'affecte pas le contenu de l'élément principal). La désactivation du défilement des documents empêche de quitter accidentellement le minimal-ui lors du défilement vers le haut. Selon la spécification iOS 7.1 d'origine, appuyez sur la barre supérieure pour ramener le reste du chrome.

Le résultat final ressemble à ceci:

Brim dans le simulateur iOS.

Dans un souci de documentation, et au cas où vous préférez écrire votre propre implémentation, il convient de noter que vous ne pouvez pas utiliser Scream pour détecter si le périphérique est en minimal-ui juste après l' événement orientationchange car les windowdimensions ne reflètent pas la nouvelle orientation tant que le l'animation de rotation est terminée. Vous devez attacher un écouteur à l' événement orientationchangeend .

Scream et orientationchangeend ont été développés dans le cadre de ce projet.


3
C'est beaucoup plus expansif que ma réponse originale, marquée comme nouvelle réponse jusqu'à ce qu'une solution encore meilleure arrive :)
bitinn

4
Ça a l'air bien! Puis-je forcer minimal-ui sans le défilement initial?
INT

53
C'est vraiment une histoire sans fin. Je suis un développeur de jeux en HTML et minimal-ui sous iOS 7.1 fonctionnait très bien - c'était le seul moyen d'avoir une application en plein écran ET en même temps de pouvoir toucher en bas de l'écran. Les solutions avec glissement de page sont bien, mais pas assez bonnes: (Apple, nous avons besoin d'une mise en œuvre correcte de l'API plein écran pour les jeux, s'il vous plaît.
Petr Urban

4
@ Petr: Je ne pourrais pas être plus d'accord. Lorsque ce correctif a été annoncé dans la version 7.1, nous avons rapidement déployé un nouveau flux d'achat de paiement qui épinglait le CTA principal au bas de l'écran ... cela a fonctionné et s'est très bien converti! C'était très "natif" et sans couture. Ce qui, je pense, est le problème exact. Si vous y réfléchissez, il n'est pas dans l'intérêt d'Apples que les applications Web se sentent natives. Il s'agit en fait d'un conflit d'intérêts direct avec leur monopole sur l'App Store. C'est, IMO, la seule raison valable pour laquelle une fonctionnalité qui a tant de sens a été corrigée puis supprimée intentionnellement. # my2Cents :)
Jose Browne

2
@PetrUrban Je suis convaincu qu'Apple préférerait que vous publiiez votre jeu en tant qu'application phonegap plutôt que de vous permettre de servir sur le Web. Leur récente décision d'autoriser les bloqueurs de publicités pour les safaris confirme cette idée.
Patrick Gunderson

20

Puisqu'il n'y a pas de moyen programmatique d'imiter minimal-ui, nous avons proposé une solution de contournement différente, en utilisant calc()et la hauteur de la barre d'adresse iOS connue à notre avantage:

La page de démonstration suivante ( également disponible sur l'essentiel, plus de détails techniques là-bas ) invitera l'utilisateur à faire défiler, ce qui déclenche alors un plein écran doux (masquer la barre d'adresse / menu), où l'en-tête et le contenu remplissent la nouvelle fenêtre.

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }

        html {
            background-color: red;
        }

        body {
            background-color: blue;
            margin: 0;
        }

        div.header {
            width: 100%;
            height: 40px;
            background-color: green;
            overflow: hidden;
        }

        div.content {
            height: 100%;
            height: calc(100% - 40px);
            width: 100%;
            background-color: purple;
            overflow: hidden;
        }

        div.cover {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.5);
            color: #fff;
            display: none;
        }

        @media screen and (width: 320px) {
            html {
                height: calc(100% + 72px);
            }

            div.cover {
                display: block;
            }
        }
    </style>
    <script>
        var timeout;

        window.addEventListener('scroll', function(ev) {

            if (timeout) {
                clearTimeout(timeout);
            }

            timeout = setTimeout(function() {

                if (window.scrollY > 0) {
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';
                }

            }, 200);

        });
    </script>
</head>
<body>

    <div class="header">
        <p>header</p>
    </div>
    <div class="content">
        <p>content</p>
    </div>
    <div class="cover">
        <p>scroll to soft fullscreen</p>
    </div>

</body>
</html>

10

Dis juste au revoir à minimal-ui (pour l'instant)

C'est vrai, cela minimal-uipourrait être à la fois utile et nuisible, et je suppose que le compromis a maintenant un autre équilibre, en faveur de nouveaux iPhones plus gros.

J'ai traité le problème en travaillant avec mon framework js pour les applications HTML5. Après de nombreuses tentatives de solutions, chacune avec ses inconvénients, j'ai renoncé à considérer que l'espace perdu sur les iPhones antérieurs à 6. Compte tenu de la situation, je pense que le seul comportement solide et prévisible est un comportement prédéterminé.

En bref, j'ai fini par empêcher toute forme d'interface utilisateur minimale , donc au moins la hauteur de mon écran est toujours la même et vous savez toujours quel espace réel vous avez pour votre application.

Avec l'aide du temps, suffisamment d'utilisateurs auront plus d'espace.


ÉDITER

Comment je fais

Ceci est un peu simplifié, à des fins de démonstration, mais devrait fonctionner pour vous. En supposant que vous ayez un conteneur principal

html, body, #main {
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.view {
  width: 100%;
  height: 100%;
  overflow: scroll;
}

Ensuite:

  1. puis avec js, je règle #mainla hauteur de la fenêtre sur la hauteur disponible. Cela aide également à gérer d'autres bogues de défilement trouvés dans iOS et Android. Cela signifie également que vous devez savoir comment le mettre à jour, notez simplement cela;

  2. Je bloque le sur-défilement lorsque j'atteins les limites du parchemin. Celui-ci est un peu plus profond dans mon code, mais je pense que vous pouvez également suivre le principe de cette réponse pour les fonctionnalités de base. Je pense qu'il pourrait flickr un peu, mais fera le travail.


Voir la démo (sur un iPhone)

Remarque: cette application peut également être mise en signet, car elle utilise un routage interne vers des adresses hachées, mais j'ai également ajouté une invite les utilisateurs iOS à ajouter à la maison. Je pense que cela aide à fidéliser et à revenir les visiteurs (et ainsi l'espace perdu est de retour).


Désactiver minimal-ui me semble très raisonnable. Veuillez inclure une brève description pour savoir comment procéder!
István Pálinkás

Vous avez raison, j'ai ajouté un petit guide. De nombreuses autres méthodes fonctionneront.
Francesco Frapporti

1
Votre démo ne fonctionne pas sur iOS8, selon mon iPhone 5.
dmr07

Merci de me l'avoir fait savoir, ça doit être une mise à jour car ça fonctionnait autrefois. Êtes-vous en safari? Que voulez-vous dire exactement par cela ne fonctionne pas?
Francesco Frapporti

7

Le moyen le plus simple que j'ai trouvé pour résoudre ce problème était de définir la hauteur du corps et des éléments html à 100,1% pour toute demande où l'agent utilisateur était un iPhone. Cela ne fonctionne qu'en mode Paysage, mais c'est tout ce dont j'avais besoin.

html.iphone, 
html.iphone body { height: 100.1%; }

Découvrez-le sur https://www.360jungle.com/virtual-tour/25


Merci @Stephen. hauteur: 100,1% m'a aidé. Cependant, lorsque j'ai ouvert 360jungle.com/virtual-tour/25 sur iPhone (iOS 11.1.1) Safari et cliqué sur les boutons en bas, l'adresse et la barre d'outils sont apparues. C'est parce que les boutons sont trop proches de la fin de l'affichage. Je suppose qu'il serait préférable de les déplacer ailleurs en mode mobile.
Téwa

2

Le problème racine ici semble que Safari iOS8 ne masquera pas la barre d'adresse lors du défilement vers le bas si le contenu est égal ou inférieur à la fenêtre d'affichage.

Comme vous l'avez déjà découvert, l'ajout d'un rembourrage en bas permet de contourner ce problème:

html {
    /* enough space to scroll up to get fullscreen on iOS8 */
    padding-bottom: 80px;
}
// sort of emulate safari's "bounce back to top" scroll
window.addEventListener('scroll', function(ev) {
    // avoids scrolling when the focused element is e.g. an input
    if (
        !document.activeElement
        || document.activeElement === document.body
    ) {
        document.body.scrollIntoViewIfNeeded(true);
    }
});

Le CSS ci-dessus doit être appliqué de manière conditionnelle, par exemple avec UA sniffing ajoutant une gt-ios8classe à<html> .


1
Que fait exactement ce JS?
pronebird

Si vous faites référence à scrollIntoViewIfNeeded, il s'agit d'une dérivation non standard de scrollIntoView( developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView ). Comme son nom l'indique, la méthode fait défiler l'élément dans la vue. trueLe paramètre dit d'aligner la vue avec le haut de l'élément. Cela devrait en effet vous empêcher de faire défiler. La mise en œuvre est cependant imparfaite.
Gajus

1

Je veux commenter / répondre partiellement / partager mes pensées. J'utilise la technique overflow-y: scroll pour mon grand projet à venir. Son utilisation présente deux avantages MAJEURS.

a) Vous pouvez utiliser un tiroir avec des boutons d'action depuis le bas de l'écran; si le document défile et que la barre inférieure disparaît, appuyer sur un bouton situé en bas de l'écran fera d'abord apparaître la barre inférieure, puis sera cliquable. En outre, la façon dont cela fonctionne pose des problèmes avec les modaux qui ont des boutons tout en bas.

b) Lors de l'utilisation d'un élément survolé, les seules choses qui sont repeintes en cas de changements majeurs css sont celles de l'écran visible. Cela m'a donné une énorme amélioration des performances lors de l'utilisation de javascript pour modifier le CSS de plusieurs éléments à la volée. Par exemple, si vous avez une liste de 20 éléments à repeindre et que seulement deux d'entre eux sont à l'écran dans l'élément survolé, seuls ceux-ci sont repeints tandis que les autres sont repeints lors du défilement. Sans cela, les 20 éléments sont repeints.

.. Bien sûr, cela dépend du projet et si vous avez besoin de l'une des fonctionnalités que j'ai mentionnées. Google utilise des éléments survolés pour que gmail utilise la fonctionnalité que j'ai décrite en a). Imo, ça vaut le coup, même compte tenu de la petite hauteur des anciens iPhone (372px comme vous l'avez dit).


1

C'est possible, en utilisant quelque chose comme l'exemple ci-dessous que j'ai mis en place avec l'aide du travail de ( https://gist.github.com/bitinn/1700068a276fb29740a7 ) qui n'a pas tout à fait fonctionné sur iOS 11:

Voici le code modifié qui fonctionne sur iOS 11.03, veuillez commenter si cela a fonctionné pour vous.

La clé est d'ajouter une certaine taille à BODY pour que le navigateur puisse faire défiler, ex: height: calc (100% + 40px);

Exemple complet ci-dessous et lien à afficher dans votre navigateur (veuillez tester!)

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CodeHots iOS WebApp Minimal UI via Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }
        html {
            background-color: red;
        }
        body {
            background-color: blue;
            /* important to allow page to scroll */
            height: calc(100% + 40px);
            margin: 0;
        }
        div.header {
            width: 100%;
            height: 40px;
            background-color: green;
            overflow: hidden;
        }
        div.content {
            height: 100%;
            height: calc(100% - 40px);
            width: 100%;
            background-color: purple;
            overflow: hidden;
        }
        div.cover {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.5);
            color: #fff;
            display: none;
        }
        @media screen and (width: 320px) {
            html {
                height: calc(100% + 72px);
            }
            div.cover {
                display: block;
            }
        }
    </style>
    <script>
        var timeout;

        function interceptTouchMove(){
            // and disable the touchmove features 
            window.addEventListener("touchmove", (event)=>{
                if (!event.target.classList.contains('scrollable')) {
                    // no more scrolling
                    event.preventDefault();
                }
            }, false); 
        }

        function scrollDetect(event){
            // wait for the result to settle
            if( timeout ) clearTimeout(timeout);

            timeout = setTimeout(function() {
                console.log( 'scrolled up detected..' );
                if (window.scrollY > 35) {
                    console.log( ' .. moved up enough to go into minimal UI mode. cover off and locking touchmove!');
                    // hide the fixed scroll-cover
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';

                    // push back down to designated start-point. (as it sometimes overscrolls (this is jQuery implementation I used))
                    window.scrollY = 40;

                    // and disable the touchmove features 
                    interceptTouchMove();

                    // turn off scroll checker
                    window.removeEventListener('scroll', scrollDetect );                
                }
            }, 200);            
        }

        // listen to scroll to know when in minimal-ui mode.
        window.addEventListener('scroll', scrollDetect, false );
    </script>
</head>
<body>

    <div class="header">
        <p>header zone</p>
    </div>
    <div class="content">
        <p>content</p>
    </div>
    <div class="cover">
        <p>scroll to soft fullscreen</p>
    </div>

</body>

Exemple de lien complet ici: https://repos.codehot.tech/misc/ios-webapp-example2.html


1

Il est possible de faire fonctionner une application Web en plein écran à la fois sous iOS et Android, cela s'appelle une PWA et après un travail acharné de mucha, c'était le seul moyen de contourner ce problème.

Les PWA ouvrent un certain nombre d'options de développement intéressantes à ne pas manquer. J'en ai déjà fait quelques-uns, consultez ce manuel d'appel d'offres public et privé pour les concepteurs (espagnol). Et voici une explication en anglais du site CosmicJS


-3

Je n'ai pas fait de conception Web pour iOS, mais d'après ce que je me souviens avoir vu dans les sessions WWDC et dans la documentation, la barre de recherche de Mobile Safari et les barres de navigation dans le système d'exploitation seront désormais automatiquement redimensionnées et réduites pour afficher davantage de votre contenu.

Vous pouvez tester cela dans Safari sur un iPhone et remarquer que, lorsque vous faites défiler vers le bas pour voir plus de contenu sur une page, la barre de navigation / recherche est automatiquement masquée.

Peut-être que laisser la barre d'adresse / barre de navigation telle quelle et ne pas créer une expérience plein écran est ce qu'il y a de mieux. Je ne vois pas Apple faire cela de sitôt. Et tout au plus, ils ne contrôlent pas automatiquement le moment où la barre d'adresse s'affiche / se cache.

Bien sûr, vous perdez de l'espace d'écran, en particulier sur un iPhone 4 ou 4S, mais il ne semble pas y avoir d'alternative à partir de la Bêta 4.


1
Je connaissais cette fonctionnalité d'iOS7 +, mais voir mon explication ci-dessus: puisque la hauteur du document est exactement la même que celle de la fenêtre du navigateur, le navigateur mobile ne masquera pas la barre d'adresse / le menu de navigation , car aucun défilement n'a lieu au niveau du document.
bitinn

1
Cela peut être une limitation maintenant que la bêta 4 a supprimé cette fonctionnalité. Il est possible et probable qu'Apple contrôle automatiquement la barre d'adresse et empêche les développeurs d'y accéder.
iFeli

8
I haven't done web design for iOS- si vous faites de la conception Web, vous le faites pour chaque plate-forme. Parce que le Web est sur toutes les plateformes.
ProblemsOfSumit

4
@Sumit Je sais que travailler sur le Web est universel, mais chaque navigateur et ses frameworks sous-jacents ont des attributs CSS spécifiques. Ainsi, Chrome peut avoir certains attributs non disponibles pour Safari et FireFox, et vice versa.
iFeli
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.