問題描述
我正在使用 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 欄縮小/滑動導致的,因為它們是 100%的高度,而且改變了#bg2 和#bg2 div 的大小,而且”fixed” 。由於背景圖像設置為”cover”,因為包含區域較大,所以將調整圖像尺寸/位置。
根據網站的反應性質,背景必須擴大。我接受兩種可能的解決方案:
1) 將#bg1,#bg2 的高度設置為 100vh 。在理論上,這是一個優雅的解決方案。但是,iOS 有一個 vh bug(http://thatemil.com/blog/2013/06/13/viewport-relative-unit-strangeness-in-ios-6/) 。我嘗試使用 max-height 來防止問題,但仍然存在。
2) 視口尺寸 (由 JavaScript 確定) 不受 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 中看到了這些調整大小的網址欄的許多問題。我明白目的,但他們真的需要考慮到他們帶給網站的奇怪的功能和破壞。最新的變化是,您不能再在”hide” 上使用滾動技巧在 iOS 或 Chrome 上加載網頁欄。
編輯:雖然上述腳本非常適合保持背景調整大小,但當用户向下滾動時,會導致明顯的差距。這是因為它將背景大小保留到屏幕高度的 100%減去 URL 欄。如果我們添加 60px 的高度,如瑞士所説,這個問題消失了。這意味着當 URL 欄存在時,我們不會看到背景圖片的底部 60px,但它阻止用户看到差距。
function resizeBackground() {
bg.height( $(window).height() + 60);
}
次佳解決方案
我發現傑森的回答對我來説不是很有效,而且我還是跳起來。 Javascript 確保頁面頂部沒有間隙,但是當地址欄消失/重新出現時,背景仍然跳動。所以以及 Javascript 修復,我將 transition: height 999999s
應用到 div 。這將創建一個持續時間過長的轉換,以使其幾乎凍結該元素。
第三種解決方案
我在網站的標題上有類似的問題。
html, body {
height:100%;
}
.header {
height:100%;
}
這將導致 Android Chrome 上的滾動滾動體驗,因為.header-container 將在 url-bar 隱藏後重新縮放,手指從屏幕上移除。
CSS-Solution:
添加以下兩行,將防止 url-bar 隱藏,並且垂直滾動仍然可能:
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%);
}
由於 vh 會在 URL 欄消失時發生變化,您需要以另一種方式確定高度。幸運的是,視口的寬度是恆定的,移動設備只有幾種不同的寬高比; 如果您可以確定寬度和寬高比,一點點數學就會使您的視口高度正好與 vh 一樣工作。這是這個過程
1) 創建一系列要定位的寬高比的媒體查詢。
-
使用 device-aspect-ratio 而不是 aspect-ratio,因為後者將在 url bar 消失時調整大小
-
我將’max’ 添加到 device-aspect-ratio 中,以便將最受歡迎的任何縱橫比定位到最接近的位置。這不會那麼精確,但是他們只會為少數用户使用,並且仍然會非常接近正確的呃。
-
記住使用水平/垂直的媒體查詢,因此對於 portait,您需要翻轉數字
2) 對於每個媒體查詢乘以垂直高度的任何百分比,您希望元素在 vw 中與寬高比相反。
-
由於您知道寬度和寬度與高度的比例,因此您只需將所需的百分比 (您的情況下為 100%) 乘以高度/寬度的比例。
3) 你必須確定 URL 欄的高度,然後從該高度減去。我沒有發現確切的測量,但是我在景觀上使用 9%的移動設備,這似乎工作得很好。
這不是一個非常優雅的解決方案,但其他選項也不是很好,考慮到它們是:
-
讓你的網站看起來很漂亮的用户,
-
或者
-
使用 javascript 進行一些基本樣式,
缺點是一些設備可能具有與最受歡迎的不同的網址高度或寬高比。然而,如果只有少數設備遭受加法/減法的幾個像素,那麼使用這種方法,對於我來説,這顯然比刷新網站大小的人都好。
為了更容易,我還創建了一個 SASS mixin:
@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()
部件正在將 top-aligned 絕對定位元件不可避免地改變為底部對齊,所以根本沒有跳轉。雖然,我想沒有理由不直接添加到正常的 CSS 。
我們需要用户代理嗅探器,因為桌面上的屏幕高度不會有所幫助。
此外,這是假設 #background
是填充窗口的 fixed-position 元素。
對於 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;
}
編輯:對不起,這不直接回答您的具體問題與多個背景。但是,這是搜索固定背景在手機上跳躍的問題的第一個結果之一。
第六種方案
我目前使用的解決方案是檢查 $(document).ready
上的 userAgent
,看看它是否是一個違規的瀏覽器。如果是,請按照下列步驟操作:
-
將相關高度設置為當前視口高度而不是’100%’
-
存儲當前視口水平值
-
然後,在
$(window).resize
上,如果新的水平視口尺寸與初始值不同,則僅更新相關的高度值 -
存儲新的水平& 垂直值
或者,您還可以測試允許垂直調整大小,只有當它們超出地址欄的高度時。
哦,地址欄確實影響 $(window).height
。參見:Mobile Webkit browser (chrome) address bar changes $(window).height(); making background-size:cover rescale every time JS “Window” width-height vs “screen” width-height?
第七種方案
當我嘗試創建一個覆蓋整個視口的入口屏幕時,我遇到了這個問題。不幸的是,接受的答案不再有效。
1) 高度設置為 100hv
的元素在每次視口大小更改時都被調整大小,包括由 (dis) 出現的 URL 欄引起的情況。
2)$(window).height()
返回值也受到 URL 欄大小的影響。
一個解決方案是”freeze” 的元素使用 transition: height 999999s
建議在 the answer by AlexKempton 。缺點是,這有效地禁用了適應所有視口大小的變化,包括由屏幕旋轉引起的變化。
所以我的解決方案是使用 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: 100hv
一起使用這種技術。該頁面從一開始就可以正常渲染,然後 JavaScript 會手動啓動並開始管理高度。這樣,頁面正在加載 (甚至之後) 就完全沒有閃爍。
第八種方案
我發現一個非常簡單的解決方案,而不使用 Javascript:
transition: height 1000000s ease;
-webkit-transition: height 1000000s ease;
-moz-transition: height 1000000s ease;
-o-transition: height 1000000s ease;
所有這一切都是延遲運動,所以它是非常緩慢,這是不明顯的。
第九種方案
我的解決方案涉及到一些 javascript 。保持 100%或 100vh 在 div(這將避免 div 不出現在初始頁面加載) 。然後當頁面加載時,抓住窗口高度並將其應用到相關元素。避免跳躍,因為現在你的 div 上有一個靜態高度。
var $hero = $('#hero-wrapper'),
h = window.innerHeight;
$hero.css('height', h);
參考文獻
注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。