web-dev-qa-db-fra.com

Quelle est la meilleure méthode pour re-rendre une page Web sur le changement d'orientation?

J'ai une mise en page CSS fluide qui rend mal sur un iphone lorsque je change l'orientation. (Cela a l'air bien quand il est rafraîchi).

J'utilise le code ci-dessous pour actualiser la page sur le changement d'orientation, ce qui fonctionne bien - cela semble un peu faux de le faire. Y a-t-il un moyen d'y parvenir sans avoir à recharger toute la page? C'est un site mobile, je ne veux pas vraiment forcer l'utilisateur à charger la page deux fois.

var supportsOrientationChange = "onorientationchange" in window,
    orientationEvent = supportsOrientationChange ? "orientationchange" : "resize";

window.addEventListener(orientationEvent, function() {
    window.location.reload()
}, false);   

Modifier:

Les deux principaux problèmes lors des tests sur un iphone sont les suivants:

J'ai une largeur de 100%, avec une image d'arrière-plan alignée à droite. Lorsque je change l’orientation de portrait en paysage, la largeur du corps reste identique à celle du rendu en mode portrait et inversement. Il s’agit plus d’un problème de paysage en portrait car la page est trop large et il semble que les images soient rendues deux fois.

28
theorise

En supposant que votre CSS s'affiche déjà avec bonheur sur les écrans de différentes tailles, vous devez définir la fenêtre d'affichage dans la <tête> de votre modèle. 

Exemple, cela définit la largeur de la page comme étant la largeur de l'écran du périphérique et un zoom initial de 100%. Le zoom initial est appliqué au chargement de la page, mais pas lorsque l'orientation est modifiée.

<meta name="viewport" content="width=device-width, initial-scale=1.0">

En ajoutant un paramètre maximum-scale = 1.0 à la fenêtre d'affichage, vous obligerez l'iPad/iPhone à maintenir le niveau de zoom et à réorganiser la page en fonction du changement d'orientation. L'inconvénient est qu'il désactive le zoom. Toutefois, l’avantage est que vous pouvez effectuer des réglages d’agencement à l’aide de requêtes multimédia afin de présenter le contenu de manière appropriée pour l’orientation actuelle. Vous pouvez en savoir plus sur la fenêtre d'affichage ici: Choisir un ViewPort

Maintenant sur les requêtes des médias. Vous devez placer les requêtes de supports au bas de votre fichier CSS et dans l’ordre de la plus petite largeur à la plus grande largeur pour les largeurs d’écran. Par exemple, tiré de l'exemple Html5BoilerPlate CSS:

@media only screen and (min-width: 480px) {
  /* Style adjustments for viewports 480px and over go here */

}

@media only screen and (min-width: 768px) {
  /* Style adjustments for viewports 768px and over go here */

}

Ainsi, tous vos styles normaux sont supérieurs à celui-ci et appliqués en premier. Ensuite, si l'écran mesure 480px ou plus large, le bloc de styles suivant est appliqué, puis si l'écran mesure 768px ou plus large, le dernier bloc de styles est appliqué.

En combinant le niveau de zoom fixe à 1.0 et les requêtes des médias, vous pouvez redimensionner votre site en fonction de la réactivité en fonction de la taille et de l'orientation de l'écran sans JavaScript. Évidemment, vous devez vous assurer que le site est bien conçu pour que les utilisateurs n'aient pas besoin de zoomer. Si votre site est optimisé pour le mobile, cela ne devrait pas poser de problème.

Remarque: les autres navigateurs mobiles non-safari peuvent réorganiser la page sans définir l'échelle maximale dans la fenêtre. Mais ce comportement est incohérent et la plupart des développeurs semblent s’adapter aux appareils Apple même si la mise en œuvre est pire que d’autres appareils. Certains autres appareils conserveraient le niveau de zoom et recentreraient la fenêtre d'affichage lorsque l'orientation changerait. Mais tous les appareils sont corrects pour fixer le niveau de zoom à 1.0.

24
BenSwayne

Mise à jour 2015

Toutes les autres réponses sont incorrectes ou obsolètes. Voici ce qui fonctionne:

  window.addEventListener('orientationchange', function () {
    var originalBodyStyle = getComputedStyle(document.body).getPropertyValue('display');
    document.body.style.display='none';
    setTimeout(function () {
      document.body.style.display = originalBodyStyle;
    }, 10);
  });

Le code écoute l'événement orientationchange et force la redéfinition de l'élément body en le masquant et en lui indiquant 10 millisecondes plus tard. Cela ne dépend d'aucun tag <meta> ni de requête de média.

D'autres réponses suggéraient d'utiliser des requêtes multimédia, mais vous les utilisiez déjà, puisque vous avez dit "Ça a l'air bien quand il est rafraîchi".

Certains autres réponses suggèrent d'utiliser location.reload(). Ceci est très inefficace, car il faudra recharger toute la page, y compris les images, etc. Surtout sur mobile, vous ne voulez pas faire cela.

Pourtant, d’autres réponses suggèrent d’ajouter <meta name="viewport" content="width=device-width, initial-scale=1.0"> ou des variantes de celui-ci. Depuis Safari 7, cela ne fonctionne plus. Voici un demo . Pour vous assurer que cela ne fonctionne pas, commencez par l'iPad en mode paysage, chargez la page, puis faites-le pivoter. Notez que la page ne s’agrandit pas à pleine hauteur, malgré l’utilisation complète de la flexbox.

Comparez cela à cette page , où nous utilisons la technique de masquage/exposition du corps en production.

11
Dan Dascalescu

Utilisé une méthode qui provoque une nouvelle peinture et une refusion dans un seul cadre de pile javascript. N'aime pas les réponses spécifiques à la fenêtre d'affichage, car il est souvent nécessaire pour l'accessibilité de continuer à zoomer, etc.

$(window).on('orientationchange', function() {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
}); 

Ou équivalent non-jquery 

window.addEventListener('orientationchange', function () {
    document.body.style.display='none';
    document.body.offsetHeight; //cause a reflow
    document.body.style.display='block'; //cause a repaint
});
3
James Westgate

J'ai eu un problème similaire et voici comment je l'ai corrigé avec jQuery.

Dans mon cas, les styles ne changeaient pas correctement pour mon élément <nav>. J'ai utilisé une version modifiée du code de kidkaos77 associée à $.get() pour ne charger qu'une partie de la page:

$(window).bind("resize",function() {
    //on resize reload only nav & replace
    $.get("index.php" +  ' nav', function(data) {
        $("nav").replaceWith($(data).find("nav"));
    });
});

Avec cette méthode, vous n'avez pas besoin de recharger toute la page, mais vous devez spécifier exactement quels éléments sont affectés par le changement d'orientation. Dans votre cas, il semble que vous n'ayez besoin que d'une div.

0
Tommy DC