programing tip

검색 주소창이 iOS / Android / Mobile Chrome을 숨기면 배경 이미지가 점프 함

itbloger 2020. 6. 1. 19:05
반응형

검색 주소창이 iOS / Android / Mobile Chrome을 숨기면 배경 이미지가 점프 함


현재 Twitter Bootstrap을 사용하여 반응 형 사이트를 개발 중입니다.

이 사이트에는 모바일 / 태블릿 / 데스크톱 전체 화면 배경 이미지가 있습니다. 이 이미지는 두 개의 div를 사용하여 각각 회전하고 페이드됩니다.

하나의 문제를 제외하고는 거의 완벽합니다. Android에서 iOS Safari, Android 브라우저 또는 Chrome을 사용하면 사용자가 페이지를 아래로 스크롤 할 때 배경이 약간 이동하여 주소 표시 줄이 숨겨집니다.

이 사이트는 다음과 같습니다 : http://lt2.daveclarke.me/

모바일 장치에서 방문하여 아래로 스크롤하면 이미지 크기 조정 / 이동이 표시됩니다.

백그라운드 DIV에 사용하는 코드는 다음과 같습니다.

#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;
}

모든 제안을 환영합니다-이것은 잠시 동안 내 머리를하고 있습니다!


이 문제는 URL 표시 줄이 축소 / 슬라이딩되고 # bg1 및 # bg2 div의 크기가 100 % 높이이고 "고정"되었기 때문에 크기가 변경되어 발생합니다. 배경 이미지가 "표지"로 설정되어 있기 때문에 포함 영역이 클수록 이미지 크기 / 위치가 조정됩니다.

사이트의 반응 특성에 따라 배경의 크기가 조정되어야합니다. 나는 두 가지 가능한 해결책을 즐긴다.

1) # bg1, # bg2 높이를 100vh로 설정하십시오. 이론적으로 이것은 우아한 솔루션입니다. 그러나 iOS에는 vh 버그가 있습니다 ( http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/ ). 문제를 방지하기 위해 최대 높이를 사용하려고했지만 여전히 남아 있습니다.

2) 자바 스크립트에 의해 결정될 때 뷰포트 크기는 URL 표시 줄의 영향을받지 않습니다. 따라서 Javascript를 사용하여 뷰포트 크기에 따라 # bg1 및 # bg2의 정적 높이를 설정할 수 있습니다. 이것은 순수한 CSS가 아니므로 페이지로드시 약간의 이미지 점프가 있기 때문에 최상의 솔루션은 아닙니다. 그러나 그것은 iOS의 "vh"버그를 고려한 유일한 해결책입니다 (iOS 7에서는 수정되지 않은 것으로 보입니다).

var bg = $("#bg1, #bg2");

function resizeBackground() {
    bg.height($(window).height());
}

$(window).resize(resizeBackground);
resizeBackground();

참고로, iOS 및 Android의 크기 조정 URL 막대와 관련된 많은 문제가 있습니다. 나는 그 목적을 이해하지만, 그들은 이상한 기능과 그들이 웹 사이트에 가져 오는 혼란을 통해 실제로 생각할 필요가있다. 최신 변경 사항은 더 이상 스크롤 트릭을 사용하여 iOS 또는 Chrome에서 페이지로드의 URL 막대를 "숨길"수 없다는 것입니다.

편집 : 위의 스크립트는 배경 크기 조정을 유지하기 위해 완벽하게 작동하지만 사용자가 아래로 스크롤하면 눈에 띄는 간격이 발생합니다. 배경의 크기를 화면 높이의 100 %에서 URL 표시 줄을 뺀 크기로 유지하기 때문입니다. 스위스가 제안한 것처럼 높이에 60px를 추가하면이 문제는 사라집니다. 즉, URL 표시 줄이있을 때 배경 이미지의 아래쪽 60px가 표시되지 않지만 사용자가 간격을 볼 수는 없습니다.

function resizeBackground() {
    bg.height( $(window).height() + 60);
}

나는 Jason의 대답이 나에게 효과적이지 않다는 것을 알았고 여전히 점프하고 있습니다. 자바 스크립트는 페이지 상단에 간격이없는 것을 확인했지만 주소 표시 줄이 사라지거나 다시 나타날 때마다 배경이 여전히 튀어 나오고있었습니다. Javascript 수정뿐만 아니라 transition: height 999999sdiv에 적용 했습니다. 이렇게하면 지속 시간이 너무 길어 사실상 요소가 정지됩니다.


우리 웹 사이트의 헤더에 비슷한 문제가 있습니다.

html, body {
    height:100%;
}
.header {
    height:100%;
}

URL 막대를 숨기고 손가락을 화면에서 제거한 후 .header-container가 다시 조정되므로 안드로이드 크롬에서 스크롤링이 급격히 진행됩니다.

CSS 솔루션 :

다음 두 줄을 추가하면 URL 막대 숨기기 및 세로 스크롤이 여전히 가능하지 않습니다.

html {
    overflow: hidden;
}
body {
    overflow-y: scroll;
    -webkit-overflow-scrolling:touch;
}

이 문제는 미디어 쿼리와 약간의 수학으로 해결할 수 있습니다. portait 오리엔테이션을위한 솔루션은 다음과 같습니다.

@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%);
}

URL 표시 줄이 사라지면 vh가 변경되므로 다른 방법으로 높이를 결정해야합니다. 고맙게도 뷰포트의 너비는 일정하며 모바일 장치는 몇 가지 종횡비 만 제공됩니다. 너비와 종횡비를 결정할 수 있으면 약간의 수학으로 vh 작동 하는 것처럼 뷰포트 높이를 정확하게 얻을 수 있습니다. 과정은 다음과 같습니다

1) 타겟팅하려는 가로 세로 비율에 대한 일련의 미디어 쿼리를 만듭니다.

  • URL 막대가 사라질 때 후자의 크기가 조정되므로 aspect-ratio 대신 device-aspect-ratio를 사용하십시오.

  • 나는 가장 인기있는 사이에 발생하는 종횡비를 대상으로 장치 종횡비에 'max'를 추가했습니다. 정확하지는 않지만 소수의 사용자만을위한 것이며 여전히 적절한 vh에 가깝습니다.

  • horizontal / vertical을 사용하여 미디어 쿼리를 기억하므로 portait의 경우 숫자를 뒤집어 야합니다.

2) 각 미디어 쿼리에 대해 가로 세로 비율의 역수로 요소의 수직 높이 백분율을 vw로 곱하십시오.

  • 너비와 높이 대 너비의 비율을 알고 있으므로 원하는 % (경우에 100 %)에 높이 / 너비의 비율을 곱하면됩니다.

3) URL 막대 높이를 결정한 다음 높이에서 빼십시오. 정확한 측정 결과를 찾지 못했지만 가로 방향의 모바일 장치에는 9 %를 사용하며 상당히 잘 작동하는 것 같습니다.

이것은 매우 우아한 솔루션은 아니지만 다른 옵션은 다음과 같은 점을 고려할 때 좋지 않습니다.

  • 웹 사이트가 사용자에게 버그가있는 것처럼 보이면

  • 크기가 잘못된 요소가 있거나

  • 기본 스타일링에 자바 스크립트를 사용하면

단점은 일부 장치는 가장 인기있는 것과 다른 URL 막대 높이 또는 종횡비를 가질 수 있다는 것입니다. 그러나 소수의 장치 만 몇 픽셀을 더하거나 빼는 경우이 방법을 사용하면 스 와이프 할 때 웹 사이트 크기를 조정하는 모든 사람보다 나에게 훨씬 좋습니다.

더 쉽게하기 위해 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%);
  }
}

여기에있는 모든 답변은 window높이 를 사용 하며 URL 표시 줄의 영향을받습니다. 모두가 screen키를 잊어 버렸 습니까?

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

.css()부품을 추가하면 필연적으로 상단 정렬 된 절대 위치 요소가 하단 정렬로 변경되므로 점프가 전혀 없습니다. 비록 일반 CSS에 직접 추가하지 않는 이유는 없다고 생각합니다.

데스크톱의 화면 높이는 도움이되지 않으므로 사용자 에이전트 스니퍼가 필요합니다.

또한 이것은 #background창을 채우는 고정 위치 요소 라고 가정 합니다.

JavaScript 순수 주의자 (경고-미확인) :

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

편집 : 이것은 하나 이상의 배경으로 특정 문제에 직접 대답하지는 않습니다. 그러나 이것은 모바일에서 점프하는 고정 배경 의이 문제를 검색 할 때 첫 번째 결과 중 하나입니다.


전체 뷰포트를 덮는 입구 화면을 만들려고 할 때도이 문제가 발생했습니다. 안타깝게도 수락 된 답변이 더 이상 작동하지 않습니다.

1) 높이가 설정된 요소 100vh는 URL 표시 줄이 표시되지 않는 경우를 포함하여 뷰포트 크기가 변경 될 때마다 크기가 조정됩니다.

2) $(window).height()URL 막대의 크기에 영향을받는 값을 반환합니다.

한 가지 해결책은 AlexKempton의 답변transition: height 999999s 에서 제안한대로 요소를 "고정"시키는 입니다. 단점은 화면 회전으로 인한 변경을 포함하여 모든 뷰포트 크기 변경에 대한 적응을 효과적으로 비활성화한다는 것입니다.

그래서 내 솔루션은 JavaScript를 사용하여 수동으로 뷰포트 변경을 관리하는 것입니다. 그러면 URL 표시 줄로 인해 발생할 수있는 작은 변경 사항을 무시하고 큰 변경 사항에만 반응 할 수 있습니다.

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

편집 : 실제로이 기술을와 함께 사용 height: 100vh합니다. 페이지는 처음부터 올바르게 렌더링 된 다음 자바 스크립트가 시작되어 수동으로 높이 관리를 시작합니다. 이렇게하면 페이지가로드되는 동안 (또는 그 이후에도) 깜박임이 전혀 없습니다.


현재 사용중인 솔루션은 userAgent켜기 $(document).ready를 확인하여 문제가되는 브라우저 중 하나인지 확인하는 것입니다. 그렇다면 다음 단계를 수행하십시오.

  1. 관련 높이를 '100 %'가 아닌 현재 뷰포트 높이로 설정
  2. 현재 뷰포트 가로 값 저장
  3. 그런 다음에 $(window).resize수평 뷰포트 치수가 초기 값과 다른 경우에만 관련 높이 값을 업데이트하십시오.
  4. 새로운 가로 및 세로 값 저장

선택적으로 주소 표시 줄의 높이를 초과 할 때만 세로 크기 조정을 허용하는지 테스트 할 수도 있습니다.

아, 그리고 주소 표시 줄에 영향을 미칩니다 $(window).height. 참조 : 모바일 웹킷 브라우저 (크롬) 주소 표시 줄 변경 $ (window) .height (); JS- "창"너비 높이 대 "화면"너비 높이 마다 매번 배경 크기 : 커버 크기 조정 ?


Javascript를 사용하지 않고 정말 쉬운 해결책을 찾았습니다.

transition: height 1000000s ease;
-webkit-transition: height 1000000s ease;
-moz-transition: height 1000000s ease;
-o-transition: height 1000000s ease;

이 모든 것은 움직임을 지연 시켜서 눈에 띄지 않게 느리게합니다.


내 솔루션에는 약간의 자바 스크립트가 포함되었습니다. div에 100 % 또는 100vh를 유지하십시오 (이렇게하면 div가 초기 페이지로드에 나타나지 않게됩니다). 그런 다음 페이지가로드되면 창 높이를 잡고 해당 요소에 적용하십시오. 이제 div에 고정 높이가 있기 때문에 점프를 피하십시오.

var $hero = $('#hero-wrapper'),
    h     = window.innerHeight;

$hero.css('height', h);

VH 단위를 사용하는 바닐라 자바 ​​스크립트 솔루션을 만들었습니다. VH를 거의 어느 곳에서나 사용하면 스크롤 막대를 최소화하는 주소 표시 줄이 영향을받습니다. 페이지를 다시 그릴 때 표시되는 정크를 수정하기 위해 VH 단위를 사용하여 모든 요소를 ​​가져 .vh-fix와서 인라인 픽셀 높이를 제공하는 이 js가 있습니다 . 본질적으로 우리가 원하는 높이로 냉동합니다. 회전하거나 뷰포트 크기를 변경하여 반응을 유지할 수 있습니다.

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'
  }
}

이것은 모든 유스 케이스를 해결했으며 도움이되기를 바랍니다.


이것은이 문제를 해결하기위한 솔루션입니다. 코드에 직접 주석을 추가했습니다. 이 솔루션을 테스트했으며 정상적으로 작동합니다. 모두 같은 문제가 있기를 바랍니다.

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

이것은 내가 시도한 모든 것보다 가장 좋은 솔루션입니다.

...And this does not keep the native experience of the address bar!

You could set the height with CSS to 100% for example, and then set the height to 0.9 * of the window height in px with javascript, when the document is loaded.

For example with jQuery:

$("#element").css("height", 0.9*$(window).height());

)

Unfortunately there isn't anything that works with pure CSS :P but also be minfull that vh and vw are buggy on iPhones - use percentages.


I set my width element, with javascript. After I set the 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");

This works for me. I don't use jquery ect. because I want it to load as soon as posible.


It took a few hours to understand all the details of this problem and figure out the best implementation. It turns out as of April 2016 only iOS Chrome has this problem. I tried on Android Chrome and iOS Safari-- both were fine without this fix. So the fix for iOS Chrome I'm using is:

$(document).ready(function() {
   var screenHeight = $(window).height();
   $('div-with-background-image').css('height', screenHeight + 'px');
});

Simple answer if your background allows, why not set background-size: to something just covering device width with media queries and use alongside the :after position: fixed; hack here.

IE: background-size: 901px; for any screens <900px? Not perfect or responsive but worked a charm for me on mobile <480px as i'm using an abstract BG.


I am using this workaround: Fix bg1's height on page load by:

var BG = document.getElementById('bg1');
BG.style.height = BG.parentElement.clientHeight;

Then attach a resize event listener to Window which does this: if difference in height after resizing is less than 60px (anything more than url bar height) then do nothing and if it is greater than 60px then set bg1's height again to its parent's height! complete code:

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

PS: This bug is so irritating!


Similar to @AlexKempton answer. (couldn't comment sorry)

I've been using long transition delays to prevent the element resizing.

eg:

transition: height 250ms 600s; /*10min delay*/

The tradeoff with this is it prevents resizing of the element including on device rotating, however, you could use some JS to detect orientationchange and reset the height if this was an issue.


For those who would like to listen to the actual inner height and vertical scroll of the window while the Chrome mobile browser is transition the URL bar from shown to hidden and vice versa, the only solution that I found is to set an interval function, and measure the discrepancy of the window.innerHeight with its previous value.

This introduces this code:

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

I hope that this will be handy. Does anyone knows a better solution?


The solution I came up with when having similar problem was to set height of element to window.innerHeight every time touchmove event was fired.

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

This makes the element span exactly 100% of the available screen at all times, no more and no less. Even during address bar hiding or showing.

Nevertheless it's a pity that we have to come up with that kind of patches, where simple position: fixed should work.

참고URL : https://stackoverflow.com/questions/24944925/background-image-jumps-when-address-bar-hides-ios-android-mobile-chrome

반응형