theme - La imagen de fondo salta cuando la barra de direcciones oculta iOS/Android/Mobile Chrome
cual es el motor de busqueda de google chrome (18)
Creé una solución vainilla de javascript para usar unidades VH. El uso de VH prácticamente en cualquier lugar se ve afectado por barras de direcciones que minimizan el desplazamiento. Para arreglar el jank que muestra cuando la página se vuelve a dibujar, tengo este js aquí que tomará todos tus elementos usando unidades VH (si les das la clase .vh-fix
), y les darás alturas de píxeles en línea. Esencialmente congelarlos a la altura que queremos. Puede hacer esto en rotación o en el cambio de tamaño de la ventana gráfica para mantenerse receptivo.
var els = document.querySelectorAll(''.vh-fix'')
if (!els.length) return
for (var i = 0; i < els.length; i++) {
var el = els[i]
if (el.nodeName === ''IMG'') {
el.onload = function() {
this.style.height = this.clientHeight + ''px''
}
} else {
el.style.height = el.clientHeight + ''px''
}
}
Esto ha resuelto todos mis casos de uso, espero que ayude.
Actualmente estoy desarrollando un sitio receptivo usando Twitter Bootstrap.
El sitio tiene una imagen de fondo de pantalla completa en dispositivos móviles / tabletas / computadoras de escritorio. Estas imágenes giran y se desvanecen a través de cada una, usando dos divs.
Es casi perfecto, excepto un problema. Al usar iOS Safari, Android Browser o Chrome en Android, el fondo salta ligeramente cuando un usuario se desplaza hacia abajo de la página y hace que la barra de direcciones se oculte.
El sitio está aquí: http://lt2.daveclarke.me/
Visítelo en un dispositivo móvil y desplácese hacia abajo y verá que la imagen cambia de tamaño / movimiento.
El código que estoy usando para el fondo DIV es el siguiente:
#bg1 {
background-color: #3d3d3f;
background-repeat:no-repeat;
background-attachment:fixed;
background-position:center center;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover; position:fixed;
width:100%;
height:100%;
left:0px;
top:0px;
z-index:-1;
display:none;
}
Todas las sugerencias son bienvenidas, ¡esto ha estado haciéndolo por un tiempo!
Descubrí que la respuesta de Jason no estaba funcionando para mí y todavía estaba recibiendo un salto. El Javascript garantizaba que no había ningún espacio en la parte superior de la página, pero el fondo seguía saltando cuando la barra de direcciones desaparecía o reaparecía. Entonces, además de la corrección de Javascript, apliqué la transition: height 999999s
al div. Esto crea una transición con una duración tan larga que virtualmente congela el elemento.
El problema se puede resolver con una consulta de medios y algo de matemática. Aquí hay una solución para una orientación de retrato:
@media (max-device-aspect-ratio: 3/4) {
height: calc(100vw * 1.333 - 9%);
}
@media (max-device-aspect-ratio: 2/3) {
height: calc(100vw * 1.5 - 9%);
}
@media (max-device-aspect-ratio: 10/16) {
height: calc(100vw * 1.6 - 9%);
}
@media (max-device-aspect-ratio: 9/16) {
height: calc(100vw * 1.778 - 9%);
}
Como vh cambiará cuando la barra de direcciones desaparezca, deberá determinar la altura de otra manera. Afortunadamente, el ancho de la ventana gráfica es constante y los dispositivos móviles solo vienen en algunas relaciones de aspecto diferentes; Si puede determinar el ancho y la relación de aspecto, un poco de matemática le dará la altura de la vista exactamente como debe funcionar vh. Aquí está el proceso
1) Cree una serie de consultas de medios para las relaciones de aspecto que desea orientar.
utilice la relación de aspecto del dispositivo en lugar de la relación de aspecto porque este último cambiará de tamaño cuando la barra de direcciones desaparezca
Agregué ''max'' a la relación de aspecto del dispositivo para apuntar a cualquier relación de aspecto que se encuentre entre las más populares. No serán tan precisos, pero serán solo para una minoría de usuarios y seguirán estando muy cerca del vh adecuado.
recuerda la consulta de medios utilizando horizontal / vertical, por lo que para portait tendrás que voltear los números
2) para cada consulta de medios multiplique cualquier porcentaje de altura vertical que desee que el elemento esté en vw por el reverso de la relación de aspecto.
- Como conoces el ancho y la relación de ancho a alto, simplemente multiplicas el% que deseas (100% en tu caso) por la relación de alto / ancho.
3) Debe determinar la altura de la barra de la url, y luego menos la altura. No he encontrado medidas exactas, pero uso 9% para dispositivos móviles en paisaje y parece funcionar bastante bien.
Esta no es una solución muy elegante, pero las otras opciones tampoco son muy buenas, considerando que son:
Tener su sitio web parece fallar para el usuario,
tener elementos de tamaño incorrecto, o
Usando javascript para un estilo básico ,
El inconveniente es que algunos dispositivos pueden tener diferentes alturas de barra de url o proporciones de aspecto que las más populares. Sin embargo, si utilizo este método si solo una pequeña cantidad de dispositivos sufre la suma / resta de unos pocos píxeles, eso me parece mucho mejor que el hecho de que todos los que tienen un sitio web cambian de tamaño al deslizar.
Para hacerlo más fácil, también creé un mixin SASS:
@mixin vh-fix {
@media (max-device-aspect-ratio: 3/4) {
height: calc(100vw * 1.333 - 9%);
}
@media (max-device-aspect-ratio: 2/3) {
height: calc(100vw * 1.5 - 9%);
}
@media (max-device-aspect-ratio: 10/16) {
height: calc(100vw * 1.6 - 9%);
}
@media (max-device-aspect-ratio: 9/16) {
height: calc(100vw * 1.778 - 9%);
}
}
Encontré una solución realmente fácil sin el uso de Javascript:
transition: height 1000000s ease;
-webkit-transition: height 1000000s ease;
-moz-transition: height 1000000s ease;
-o-transition: height 1000000s ease;
Todo lo que hace es retrasar el movimiento, por lo que es increíblemente lento y no se nota.
Esta es la mejor solución (la más simple) sobre todo lo que he intentado.
... ¡Y esto no mantiene la experiencia nativa de la barra de direcciones !
Puede establecer la altura con CSS al 100%, por ejemplo, y luego establecer la altura en 0,9 * del alto de la ventana en px con javascript, cuando se carga el documento.
Por ejemplo con jQuery:
$("#element").css("height", 0.9*$(window).height());
)
Desafortunadamente, no hay nada que funcione con CSS puro: P, pero también es importante que vh
y vw
tengan errores en los iPhones: use porcentajes.
Establecí mi elemento de ancho, con javascript. Después de configurar el de vh.
html
<div id="gifimage"><img src="back_phone_back.png" style="width: 100%"></div>
css
#gifimage {
position: absolute;
height: 70vh;
}
javascript
imageHeight = document.getElementById(''gifimage'').clientHeight;
// if (isMobile)
document.getElementById(''gifimage'').setAttribute("style","height:" + imageHeight + "px");
Esto funciona para mí No uso jquery ect. porque quiero que se cargue lo antes posible.
Este problema se debe a que las barras de URL se contraen o se deslizan fuera del camino y cambian el tamaño de los divs # bg1 y # bg2, ya que son 100% altos y "fijos". Como la imagen de fondo está configurada para "cubrir", ajustará el tamaño / posición de la imagen ya que el área que lo contiene es más grande.
En función de la naturaleza receptiva del sitio, el fondo debe escalar. Entretengo dos posibles soluciones:
1) Establezca la altura de # bg1, # bg2 a 100vh. En teoría, esta es una solución elegante. Sin embargo, iOS tiene un error de vh ( http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/ ). Intenté usar una altura máxima para evitar el problema, pero se mantuvo.
2) El tamaño de la ventana gráfica, cuando lo determina Javascript, no se ve afectado por la barra de URL. Por lo tanto, Javascript se puede utilizar para establecer una altura estática en el # bg1 y # bg2 según el tamaño de la ventana gráfica. Esta no es la mejor solución ya que no es CSS puro y hay un ligero salto de imagen en la carga de la página. Sin embargo, es la única solución viable que veo teniendo en cuenta los errores "vh" de iOS (que no parecen estar solucionados en iOS 7).
var bg = $("#bg1, #bg2");
function resizeBackground() {
bg.height($(window).height());
}
$(window).resize(resizeBackground);
resizeBackground();
En una nota lateral, he visto tantos problemas con estas barras de URL de cambio de tamaño en iOS y Android. Entiendo el propósito, pero realmente necesitan pensar en la extraña funcionalidad y los estragos que traen a los sitios web. El último cambio es que ya no se puede "esconder" la barra de URL en la página cargada en iOS o Chrome usando los trucos de desplazamiento.
EDITAR: Si bien la secuencia de comandos anterior funciona perfectamente para evitar que el fondo cambie de tamaño, causa un espacio notable cuando los usuarios se desplazan hacia abajo. Esto se debe a que mantiene el fondo del tamaño al 100% de la altura de la pantalla menos la barra de URL. Si agregamos 60px a la altura, como sugiere Swiss, este problema desaparece. Significa que no podemos ver los 60 píxeles inferiores de la imagen de fondo cuando está presente la barra de URL, pero impide que los usuarios vean un espacio.
function resizeBackground() {
bg.height( $(window).height() + 60);
}
Estoy usando esta solución alternativa: Arregle la altura de bg1 en la carga de la página por:
var BG = document.getElementById(''bg1'');
BG.style.height = BG.parentElement.clientHeight;
A continuación, conecte un detector de eventos de tamaño a Window que hace esto: si la diferencia de altura después del cambio de tamaño es menor que 60px (más que la altura de la barra de URL), entonces no haga nada y si es mayor que 60px ¡entonces configure la altura de bg1 nuevamente a la altura de sus padres! código completo:
window.addEventListener("resize", onResize, false);
var BG = document.getElementById(''bg1'');
BG.style.height = BG.parentElement.clientHeight;
var oldH = BG.parentElement.clientHeight;
function onResize() {
if(Math.abs(oldH - BG.parentElement.clientHeight) > 60){
BG.style.height = BG.parentElement.clientHeight + ''px'';
oldH = BG.parentElement.clientHeight;
}
}
PD: ¡Este error es tan irritante!
La solución que estoy usando actualmente es verificar el userAgent
en $(document).ready
para ver si es uno de los navegadores ofensores. Si es así, sigue estos pasos:
- Establezca las alturas correspondientes a la altura de la ventana gráfica actual en lugar de ''100%''
- Almacenar el valor horizontal de la ventana gráfica actual
- Luego, en
$(window).resize
, solo actualice los valores de altura relevantes si la nueva dimensión de ventana horizontal es diferente de su valor inicial - Almacene los nuevos valores horizontales y verticales
Opcionalmente, también puede probar el permiso para cambiar el tamaño vertical solo cuando están más allá de la altura de la (s) barra (s) de direcciones.
Ah, y la barra de direcciones afecta $(window).height
. Ver: La barra de direcciones del navegador Mobile Webkit (Chrome) cambia $ (ventana) .height (); Hacer fondo: ¿cambiar la escala de la cubierta cada vez que JS "Ventana" ancho-altura frente a "pantalla" ancho-alto?
La solución que surgió cuando tuve un problema similar fue establecer la altura del elemento en window.innerHeight
cada vez que se touchmove
evento touchmove
.
var lastHeight = '''';
$(window).on(''resize'', function () {
// remove height when normal resize event is fired and content redrawn
if (lastHeight) {
$(''#bg1'').height(lastHeight = '''');
}
}).on(''touchmove'', function () {
// when window height changes adjust height of the div
if (lastHeight != window.innerHeight) {
$(''#bg1'').height(lastHeight = window.innerHeight);
}
});
Esto hace que el elemento abarque exactamente el 100% de la pantalla disponible en todo momento, ni más ni menos. Incluso durante la ocultación o presentación de la barra de direcciones.
Sin embargo, es una pena que tengamos que idear ese tipo de parches, donde la position: fixed
simple position: fixed
debería funcionar.
Mi solución implicó un poco de javascript. Mantenga el 100% o 100vh en el div (esto evitará que el div no aparezca en la carga inicial de la página). Luego, cuando la página se cargue, tome la altura de la ventana y aplíquela al elemento en cuestión. Evita el salto porque ahora tienes una altura estática en tu div.
var $hero = $(''#hero-wrapper''),
h = window.innerHeight;
$hero.css(''height'', h);
Para aquellos a los que les gustaría escuchar la altura interna real y el desplazamiento vertical de la ventana mientras el navegador móvil Chrome transiciona la barra de URL de la que se muestra a la oculta y viceversa, la única solución que encontré es establecer una función de intervalo, y mida la discrepancia de window.innerHeight
con su valor anterior.
Esto introduce este código:
var innerHeight = window.innerHeight;
window.setInterval(function ()
{
var newInnerHeight = window.innerHeight;
if (newInnerHeight !== innerHeight)
{
var newScrollY = window.scrollY + newInnerHeight - innerHeight;
// ... do whatever you want with this new scrollY
innerHeight = newInnerHeight;
}
}, 1000 / 60);
Espero que esto sea útil. ¿Alguien sabe una mejor solución?
Similar a @AlexKempton respuesta. (No pude comentar lo siento)
He estado usando largas demoras de transición para evitar el cambio de tamaño del elemento.
p.ej:
transition: height 250ms 600s; /*10min delay*/
La compensación con esto es que evita el cambio de tamaño del elemento, incluso en el dispositivo en rotación, sin embargo, puede utilizar algunos JS para detectar orientationchange
cambiar y restablecer la altura si esto fuera un problema.
También me encontré con este problema cuando intentaba crear una pantalla de entrada que cubriera toda la ventana gráfica. Lamentablemente, la respuesta aceptada ya no funciona.
1) Los elementos con la altura establecida en 100hv
se 100hv
tamaño cada vez que cambia el tamaño de la ventana 100hv
, incluidos los casos en los que se produce al aparecer (des) la barra de URL.
2) $(window).height()
devuelve valores que también se ven afectados por el tamaño de la barra de URL.
Una solución es "congelar" el elemento usando transition: height 999999s
como se sugiere en la respuesta de AlexKempton . La desventaja es que esto efectivamente desactiva la adaptación a todos los cambios en el tamaño de la ventana gráfica, incluidos los causados por la rotación de la pantalla.
Entonces mi solución es administrar los cambios de ventana manualmente usando JavaScript. Eso me permite ignorar los pequeños cambios que probablemente sean causados por la barra de URL y reaccionar solo en los grandes.
function greedyJumbotron() {
var HEIGHT_CHANGE_TOLERANCE = 100; // Approximately URL bar height in Chrome on tablet
var jumbotron = $(this);
var viewportHeight = $(window).height();
$(window).resize(function () {
if (Math.abs(viewportHeight - $(window).height()) > HEIGHT_CHANGE_TOLERANCE) {
viewportHeight = $(window).height();
update();
}
});
function update() {
jumbotron.css(''height'', viewportHeight + ''px'');
}
update();
}
$(''.greedy-jumbotron'').each(greedyJumbotron);
EDITAR: De hecho, uso esta técnica junto con la height: 100hv
. La página se representa correctamente desde el principio y luego el JavaScript entra en acción y comienza a administrar la altura manualmente. De esta manera, no hay ningún parpadeo mientras la página se está cargando (o incluso después).
Tengo un problema similar en un encabezado de nuestro sitio web.
html, body {
height:100%;
}
.header {
height:100%;
}
Esto terminará en una experiencia de desplazamiento en Android cromo, porque el .header-container cambiará de tamaño una vez que la barra de direcciones se oculte y el dedo se quite de la pantalla.
Solución CSS:
Agregar las siguientes dos líneas, evitará que la url-bar se oculte y el desplazamiento vertical aún es posible:
html {
overflow: hidden;
}
body {
overflow-y: scroll;
-webkit-overflow-scrolling:touch;
}
Todas las respuestas aquí usan la altura de la window
, que se ve afectada por la barra de URL. ¿Ha olvidado todo el mundo la altura de la screen
?
Aquí está mi solución jQuery:
$(function(){
var $w = $(window),
$background = $(''#background'');
// Fix background image jump on mobile
if ((/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
$background.css({''top'': ''auto'', ''bottom'': 0});
$w.resize(sizeBackground);
sizeBackground();
}
function sizeBackground() {
$background.height(screen.height);
}
});
Agregar la parte .css()
está cambiando el elemento de posición absoluta inevitablemente alineado a la parte superior a la alineación inferior, por lo que no hay salto en absoluto. Aunque, supongo que no hay razón para no agregar eso directamente al CSS normal.
Necesitamos el rastreador de agente de usuario porque la altura de la pantalla en los escritorios no sería útil.
Además, todo esto supone que #background
es un elemento de posición fija que llena la ventana.
Para los puristas de JavaScript (advertencia - no probado):
var background = document.getElementById(''background'');
// Fix background image jump on mobile
if ((/Android|iPhone|iPad|iPod|BlackBerry/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
background.style.top = ''auto'';
background.style.bottom = 0;
window.onresize = sizeBackground;
sizeBackground();
}
function sizeBackground() {
background.style.height = screen.height;
}
EDIT: siento que esto no responde directamente a tu problema específico con más de un fondo. Pero este es uno de los primeros resultados al buscar este problema de fondos fijos saltando en el móvil.
Tomó algunas horas entender todos los detalles de este problema y descubrir la mejor implementación. Resulta que a partir de abril de 2016, solo iOS Chrome tiene este problema. Intenté con Android Chrome y iOS Safari: ambos estaban bien sin esta solución. Entonces la solución para iOS Chrome que estoy usando es:
$(document).ready(function() {
var screenHeight = $(window).height();
$(''div-with-background-image'').css(''height'', screenHeight + ''px'');
});
esta es mi solución para resolver este problema, he agregado comentarios directamente sobre el código. He probado esta solución y funciona bien. Espero que seamos útiles para que todos tengan el mismo problema.
//remove height property from file css because we will set it to first run of page
//insert this snippet in a script after declarations of your scripts in your index
var setHeight = function() {
var h = $(window).height();
$(''#bg1, #bg2'').css(''height'', h);
};
setHeight(); // at first run of webpage we set css height with a fixed value
if(typeof window.orientation !== ''undefined'') { // this is more smart to detect mobile devices because desktop doesn''t support this property
var query = window.matchMedia("(orientation:landscape)"); //this is is important to verify if we put
var changeHeight = function(query) { //mobile device in landscape mode
if (query.matches) { // if yes we set again height to occupy 100%
setHeight(); // landscape mode
} else { //if we go back to portrait we set again
setHeight(); // portrait mode
}
}
query.addListener(changeHeight); //add a listner too this event
}
else { //desktop mode //this last part is only for non mobile
$( window ).resize(function() { // so in this case we use resize to have
setHeight(); // responsivity resisizing browser window
});
};