web-dev-qa-db-fra.com

Empêcher que l'image d'arrière-plan à position fixe: la couverture ne soit redimensionnée dans les navigateurs mobiles lorsque la barre d'adresse est masquée

Désolé pour le manque d'exemple sur celui-ci, mais je pense que c'est assez facile à comprendre.

J'ai un fond fixe sur mon site, qui est actuellement implémenté comme ceci:

#background {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: #28305e;
    background-image: url(../images/background.jpg);
    background-size: cover;
    -moz-background-size: cover;
    background-position: center center;
    z-index: -10;
}

<div id="background"></div>

C’est formidable dans tous les navigateurs jusqu’à présent, sauf pour les navigateurs mobiles où ils cachent la barre d’adresse lors du défilement. Lorsque la barre d'adresse est masquée, la fenêtre d'affichage se développe verticalement et l'image d'arrière-plan se redimensionne de manière saccadée. Sur ce site particulier, il est courant que les utilisateurs fassent défiler de haut en bas et l’effet est gênant.

Avez-vous des idées ou des stratégies pour contourner ce problème ou pour mettre en œuvre le contexte de manière différente?

Je pouvais envelopper tout le contenu dans un conteneur fixe et définir le débordement-y pour qu'il défile, ce qui empêche la barre d'adresses d'être masquée, mais je préférerais ne pas le faire (Google Glass ne peut pas faire défiler ces conteneurs, haha ... aimerais faire une démonstration là aussi).

J'ai essayé de penser à quelque chose qui fournit à la fonction image de fond: une fonctionnalité de couverture avec une sorte de tampon, de sorte qu'elle rende plus grand que la fenêtre d'affichage, et ne sera pas restituée à moins que la fenêtre d'affichage ne soit étendue au-delà de cette mémoire tampon. ne suis pas sûr de savoir comment mettre en œuvre cela. 

EDIT: J'ai effectivement implémenté ceci et détaillé le processus dans une réponse ci-dessous. Cependant, même avec cette configuration de tampon (qui étend la hauteur de l'image d'arrière-plan à plus de 60 pixels plus grande que la hauteur de la fenêtre), lorsque la barre d'adresse est masquée, il reste un segment de couleur d'arrière-plan vide qui est révélé et une fois arrêter de faire défiler, il restitue le reste de l'image d'arrière-plan.

Vous recherchez toujours un moyen de conserver la fonctionnalité de masquage de la barre d'adresse native (qui a été étendue à iOS Safari sur iPad sous iOS 8), ainsi qu'une image d'arrière-plan en plein écran qui restitue toujours intégralement même si la fenêtre d'affichage change de hauteur lors du masquage de l'adresse bar. Je commence à me demander si je devrais simplement faire un rapport de bogue pour tous les navigateurs ...

19
addMitt

Pour un safari mobile, vous devez, de manière non intuitive, attacher des arrière-plans fixes à l'élément html de la manière suivante.

html {
    background: url(../img/bg.jpg) no-repeat center center fixed;
    background-size: cover;
    height: 100%;
    overflow: hidden;
}

Ensuite, réglez le défilement sur le corps.

body {
    height: 100%;
    overflow: scroll;
}

Vous aurez toujours besoin de la division d'arrière-plan pour IE 8 car elle ne prend pas en charge la propriété background-size. Les navigateurs mobiles doivent donc la masquer. Pour ce faire, le moyen le plus simple consiste à exploiter l'incapacité de IE 8 à lire une requête multimédia.

@media only screen { #background { display: none; }}
2
Michael Morris

J'ai fini par créer une solution de contournement pour mobile. Cela ne se dégradera peut-être pas gracieusement, mais cela fonctionne bien pour le moment.

window.mobilecheck = function() {
  var check = false;
  (function(a){if(/(Android|bb\d+|meego).+mobile|Android|ipad|playbook|silk|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|Kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|Palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
  return check;
 }

 if (window.mobilecheck() == true) {
  var newHeight = $(window).height() + 70;
  $("#background").css("height", newHeight);
 }

J'ai trouvé que mobilecheck fonctionne sur Internet ( http://detectmobilebrowsers.com/ ). Si elle retourne la valeur true, je prends mon conteneur d'image d'arrière-plan fixe et ajoute 70 à sa hauteur. Ensuite, lorsque vous faites glisser l'écran vers le haut et que la barre d'adresse du navigateur Web se masque automatiquement (augmentant ainsi la hauteur de la fenêtre), la hauteur supplémentaire est suffisante pour que la taille de l'arrière-plan: la couverture ne soit pas obligée de redimensionner l'image de fond pour s'adapter à l'écran. .

J'aurais pu simplement mettre la page entière dans un conteneur fixe et empêcher les barres d'adresses mobiles de se cacher, mais je n'aime pas éviter une fonction par ailleurs soignée des navigateurs mobiles, et je sais que iOS n'est pas vraiment ravi des conteneurs fixes qui contiennent leurs propres barres de défilement (il existe des solutions de contournement bien sûr, mais je préférerais que mon contenu soit dans un conteneur plus standard).

EDIT: Cependant, cette solution de contournement introduit ce problème: CSS CHALLANGE: Image d’arrière-plan avec une hauteur de 100% - Espace blanc lors du défilement mobile

1
addMitt

Pour ceux qui cherchent encore une réponse, vous pouvez utiliser les nouveaux attributs vw et vh avec un élément qui est position: fixed.

Cela fait défiler pendant que la barre d'adresse se déplace/réduit/etc, puis reste fixe sur la page.

#bgimg {
  display: block;
  background: no-repeat url(bg.png);
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 120vh;
}
1
tjklemz

J'ai fabriqué ça. J'ai constaté que si vous ne faites jamais vraiment défiler le corps/la fenêtre, vous ne déclenchez pas le masquage automatique de Chrome. Alors enveloppez le contenu dans une plus grande div et faites-le simplement défiler et le masquage automatique ne se déclenchera jamais. MAIS AUSSI!!! Le masquage automatique ne se déclenche jamais. (La barre d'adresse est toujours là). Vous ne douteriez pas une seconde que vous puissiez cacher la barre d'adresse après cela, mais comment l'utilisateur peut-il récupérer la barre d'adresse?

html, body {
  height: 100%; 
  overflow: hidden;
}
body {
  height: 100%;
}
#background {
  position: fixed;
  left: 50%;
  bottom: 0px;
  min-width: 100%;
  min-height: 120%;
  z-index: 0;
  background: url('background.gif');
  margin-left: -50%;
  background-position: center center;
  background-attachment: fixed;  
  background-size: cover;
}
#main_container {
  width: inherit;
  height: inherit;
  overflow-y: scroll;
}
.block {
  position: relative;
  text-align: center;
  background: transparent;
  height: 100%;
  z-index: 9;
}
.block {
  width: 100%;
  height: 100%;
  background: rgba(224, 224, 224, 0.4);
}
.block::before {
  content: '';
  display: inline-block;
  height: 100%; 
  vertical-align: middle;
}
.centered {
  display: inline-block;
  vertical-align: middle;
}

<div id="main_container">
  <div class="block" >
    <div class="centered">
      <h1 class="circle">Some text</h1>
    </div>
  </div>
  <div class="block">  
    <div class="centered">
      <h1>Some text</h1>
    </div>
  </div>
  <div class="block">  
    <div class="centered">
      <h1>Some text</h1>
    </div>
  </div>
  <div class="block">  
    <div class="centered">
      <h1>Some text</h1>
    </div>
  </div>
  <div class="block" >
    <div class="centered">
      <h1>Some text</h1> 
    </div>
  </div>
</div>
<div id="bg"></div>
0
Mike Arledge

C'est difficile à dire sans exemple, mais il se peut que vous manquiez de width:100% qui devrait arrêter tout redimensionnement avec la barre de défilement. 

Une autre façon d'implémenter un arrière-plan fixe sur mobile consiste à avoir une division d'arrière-plan avec position: absolute et overflow: hidden et toutes vos autres implémentations d'arrière-plan, puis une div de contenu avec overflow-y:scroll; et de définir la hauteur de la div de contenu à l'aide de jquery ou de toute autre méthode choisie. obtenir la hauteur de la fenêtre avec. 

Découvrez ceci JS Fiddle pour un exemple. 

0
xno