如何使 <div> 准确填充浏览器 window,包括截至 2019 年的 Mobile Safari
How to make a <div> exactly fill the browser window, including Mobile Safari as of 2019
我正在开发一个单页网络应用程序,该应用程序最常用于移动设备。它的特点之一是地图模式,可以暂时接管整个浏览器window;距离标尺和一些控件附加到地图的四个角。这是地图的小截图,所以你可以知道我在说什么:
地图实现为 <div>
,position: fixed
,所有四个坐标均为零;我还临时将 <body>
设置为 overflow: hidden
,而地图是可见的,以处理底层应用程序显示从原点滚动的情况。这足以使地图在桌面浏览器上完全按照我想要的方式工作。移动浏览器还要求我提供一个像 "width=device-width,user-scalable=no"
这样的元视口标签,以使 window 的可见区域与视口完全对应。
几年前,当我最初编写这个应用程序时,这一切都非常好,但在某个地方iOS Safari 停止尊重涉及的任何元视口选项缩放 - 显然有太多网站误用了标签,导致文本小得难以阅读,但也无法缩放。目前,如果您在此浏览器上启用地图,您可能会看到稍微放大的视图,这会切断右侧和底部的按钮 - 而您对此无能为力,因为所有触摸都被解释为地图的 zoom/pan 手势,而不是浏览器滚动。如果没有通过这些按钮访问的功能,地图就不会非常有用 - 如果没有右上角的按钮,您甚至无法关闭地图。唯一的出路是重新加载页面,这可能会导致未保存的数据丢失。
我肯定会添加 history.pushState
/onpopstate
的使用,这样地图叠加层就像一个单独的页面。您可以使用浏览器的后退按钮退出地图模式 - 但这并不能解决由于缺少按钮而导致的其余功能损失。
我考虑过使用 .requestFullscreen()
来实现地图叠加层,但并非所有地方都支持该应用程序,否则该应用程序将可用。特别是,它显然在 iPhone 上根本不起作用,而在 iPad 上你会得到一个状态栏和一个巨大的 'X' 按钮覆盖你的内容 - 我的距离标尺可能不再可读。无论如何,这在语义上不是我真正想要的——我需要完整的 window,而不是全屏。
如何在现代浏览器上获得完整的window 显示?我能找到的关于该主题的所有信息都在谈论使用 meta viewport 标签,但正如我所提到的,它不再有效。
试试这个:
<meta name="viewport" content="width=device-width, height=device-height ,
initial-scale=1.0,user-scalable=no, shrink-to-fit=yes" />
你试过这些吗?
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
因为我不能评论,我想补充一点,你应该检查你的 body 标签是否是浏览器的高度。您可能还想检查一下:Chrome / Safari not filling 100% height of flex parent
您需要将 body 和 html 的高度都设置为 100%
html, body {
width: 100%;
height: 100%;
margin: 0;
}
解决方案
使用 JavaScript 将全屏 div 的高度设置为 window.innerHeight
,然后在 window 调整大小时更新它。
同样的问题:
更多信息:
这是一个旧的解决方案,解决了一个紧密相关但不完全相同的问题,所以我不确定它是否适用:
https://github.com/gajus/brim
应该是类似于minimal-ui的解法。
这是引用此答案的另一个问题:
iOS 8 removed "minimal-ui" viewport property, are there other "soft fullscreen" solutions?
如果这有帮助,请告诉我。
尝试使用以下代码 div
.class{height:100vh;}
如果您使用 position: fixed
,只需使用已经存在多年的标准 CSS 方法。
.divFixedClass{
position: fixed;
top:0;
left:0;
right:0;
bottom:0;
}
这只会使 div 自动调整为视口的完整大小,并且使用固定位置无论它们滚动多少都会锁定到位,如果需要,您可以禁用主体滚动
html.noScroll, html.noScroll > body{
overflow:none;
}
因此,如果您只是将 noScroll class 添加到 html 标记,它将禁用滚动。然后当你想允许再次滚动时你可以。
您可以使用地图控件和地图图层的两层结构来实现这一点。这意味着您实际上不需要任何 javascript
来实现您想要的(尽管问题中没有给出编码示例)。您可以使用 CSS
操作视口,这就是 vw
和 vh
的实际含义,以便回答您的评论 100vw/100vh 应该如何提供帮助?,它可以提供帮助,因为 v
代表视口。
例如,请参见代码段。
A better example (being more accurate on specific parameters that might be missed) could be provided if some coding was present in the question.
PS: 地图图层由滚动时放大的图像模拟。
function zoom(event) {
event.preventDefault();
scale += event.deltaY * -0.01;
// Restrict scale
scale = Math.min(Math.max(.125, scale), 4);
if (scale < 1) {
scale = 1;
}
// Apply scale transform
el.style.transform = `scale(${scale})`;
}
let scale = 1;
const el = document.getElementById('map');
el.onwheel = zoom;
.container {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
overflow: hidden;
width: 100vw;
height: 100vh;
background-color: transparent;
}
#map {
width: 100vw;
height: 100vh;
background-repeat: no-repeat;
background-position: center center;
background-image: url(https://picsum.photos/800/500.webp);
z-index: 1;
}
#main {
display: grid;
position: absolute;
background-color: transparent;
top: 0;
left: 0;
grid-template-columns: 6rem auto 6rem;
grid-template-rows: 3rem auto 3rem;
width: 0;
height: 0;
z-index: 2;
}
.t-l {
background: #fc0;
position: fixed;
z-index: 2;
color: #000;
top; 0;
left: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 1;
grid-column-end: column1-end;
grid-row-start: 1;
grid-row-end: row1-end;
}
.t-r {
background: #0cf;
position: fixed;
z-index: 2;
color: #000;
top; 0;
left: calc(100vw-6rem);
right: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 3;
grid-column-end: column3-end;
grid-row-start: 1;
grid-row-end: row1-end;
}
.b-l {
background: #c0f;
position: fixed;
z-index: 2;
color: #000;
bottom: 0;
top: calc(100vh-3rem);
left: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 1;
grid-column-end: column1-end;
grid-row-start: 3;
grid-row-end: row3-end;
}
.b-r {
background: #cf0;
position: fixed;
z-index: 2;
color: #000;
top: calc(100vh-3rem);
left: 100vw;
margin-left: -6rem;
bottom: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 3;
grid-column-end: column3-end;
grid-row-start: 3;
grid-row-end: row3-end;
}
<div class="container">
<div id="main">
<button class="t-l">top left control</button>
<button class="t-r">top right control</button>
<button class="b-l">bottom left control</button>
<button class="b-r">bottom right control</button>
</div>
<div id="map"></div>
</div>
我正在开发一个单页网络应用程序,该应用程序最常用于移动设备。它的特点之一是地图模式,可以暂时接管整个浏览器window;距离标尺和一些控件附加到地图的四个角。这是地图的小截图,所以你可以知道我在说什么:
地图实现为 <div>
,position: fixed
,所有四个坐标均为零;我还临时将 <body>
设置为 overflow: hidden
,而地图是可见的,以处理底层应用程序显示从原点滚动的情况。这足以使地图在桌面浏览器上完全按照我想要的方式工作。移动浏览器还要求我提供一个像 "width=device-width,user-scalable=no"
这样的元视口标签,以使 window 的可见区域与视口完全对应。
几年前,当我最初编写这个应用程序时,这一切都非常好,但在某个地方iOS Safari 停止尊重涉及的任何元视口选项缩放 - 显然有太多网站误用了标签,导致文本小得难以阅读,但也无法缩放。目前,如果您在此浏览器上启用地图,您可能会看到稍微放大的视图,这会切断右侧和底部的按钮 - 而您对此无能为力,因为所有触摸都被解释为地图的 zoom/pan 手势,而不是浏览器滚动。如果没有通过这些按钮访问的功能,地图就不会非常有用 - 如果没有右上角的按钮,您甚至无法关闭地图。唯一的出路是重新加载页面,这可能会导致未保存的数据丢失。
我肯定会添加 history.pushState
/onpopstate
的使用,这样地图叠加层就像一个单独的页面。您可以使用浏览器的后退按钮退出地图模式 - 但这并不能解决由于缺少按钮而导致的其余功能损失。
我考虑过使用 .requestFullscreen()
来实现地图叠加层,但并非所有地方都支持该应用程序,否则该应用程序将可用。特别是,它显然在 iPhone 上根本不起作用,而在 iPad 上你会得到一个状态栏和一个巨大的 'X' 按钮覆盖你的内容 - 我的距离标尺可能不再可读。无论如何,这在语义上不是我真正想要的——我需要完整的 window,而不是全屏。
如何在现代浏览器上获得完整的window 显示?我能找到的关于该主题的所有信息都在谈论使用 meta viewport 标签,但正如我所提到的,它不再有效。
试试这个:
<meta name="viewport" content="width=device-width, height=device-height ,
initial-scale=1.0,user-scalable=no, shrink-to-fit=yes" />
你试过这些吗?
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
因为我不能评论,我想补充一点,你应该检查你的 body 标签是否是浏览器的高度。您可能还想检查一下:Chrome / Safari not filling 100% height of flex parent
您需要将 body 和 html 的高度都设置为 100%
html, body {
width: 100%;
height: 100%;
margin: 0;
}
解决方案
使用 JavaScript 将全屏 div 的高度设置为 window.innerHeight
,然后在 window 调整大小时更新它。
同样的问题:
更多信息:
这是一个旧的解决方案,解决了一个紧密相关但不完全相同的问题,所以我不确定它是否适用: https://github.com/gajus/brim
应该是类似于minimal-ui的解法。
这是引用此答案的另一个问题: iOS 8 removed "minimal-ui" viewport property, are there other "soft fullscreen" solutions?
如果这有帮助,请告诉我。
尝试使用以下代码 div
.class{height:100vh;}
如果您使用 position: fixed
,只需使用已经存在多年的标准 CSS 方法。
.divFixedClass{
position: fixed;
top:0;
left:0;
right:0;
bottom:0;
}
这只会使 div 自动调整为视口的完整大小,并且使用固定位置无论它们滚动多少都会锁定到位,如果需要,您可以禁用主体滚动
html.noScroll, html.noScroll > body{
overflow:none;
}
因此,如果您只是将 noScroll class 添加到 html 标记,它将禁用滚动。然后当你想允许再次滚动时你可以。
您可以使用地图控件和地图图层的两层结构来实现这一点。这意味着您实际上不需要任何 javascript
来实现您想要的(尽管问题中没有给出编码示例)。您可以使用 CSS
操作视口,这就是 vw
和 vh
的实际含义,以便回答您的评论 100vw/100vh 应该如何提供帮助?,它可以提供帮助,因为 v
代表视口。
例如,请参见代码段。
A better example (being more accurate on specific parameters that might be missed) could be provided if some coding was present in the question.
PS: 地图图层由滚动时放大的图像模拟。
function zoom(event) {
event.preventDefault();
scale += event.deltaY * -0.01;
// Restrict scale
scale = Math.min(Math.max(.125, scale), 4);
if (scale < 1) {
scale = 1;
}
// Apply scale transform
el.style.transform = `scale(${scale})`;
}
let scale = 1;
const el = document.getElementById('map');
el.onwheel = zoom;
.container {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
overflow: hidden;
width: 100vw;
height: 100vh;
background-color: transparent;
}
#map {
width: 100vw;
height: 100vh;
background-repeat: no-repeat;
background-position: center center;
background-image: url(https://picsum.photos/800/500.webp);
z-index: 1;
}
#main {
display: grid;
position: absolute;
background-color: transparent;
top: 0;
left: 0;
grid-template-columns: 6rem auto 6rem;
grid-template-rows: 3rem auto 3rem;
width: 0;
height: 0;
z-index: 2;
}
.t-l {
background: #fc0;
position: fixed;
z-index: 2;
color: #000;
top; 0;
left: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 1;
grid-column-end: column1-end;
grid-row-start: 1;
grid-row-end: row1-end;
}
.t-r {
background: #0cf;
position: fixed;
z-index: 2;
color: #000;
top; 0;
left: calc(100vw-6rem);
right: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 3;
grid-column-end: column3-end;
grid-row-start: 1;
grid-row-end: row1-end;
}
.b-l {
background: #c0f;
position: fixed;
z-index: 2;
color: #000;
bottom: 0;
top: calc(100vh-3rem);
left: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 1;
grid-column-end: column1-end;
grid-row-start: 3;
grid-row-end: row3-end;
}
.b-r {
background: #cf0;
position: fixed;
z-index: 2;
color: #000;
top: calc(100vh-3rem);
left: 100vw;
margin-left: -6rem;
bottom: 0;
width: 6rem;
height: 3rem;
display: block;
grid-column-start: 3;
grid-column-end: column3-end;
grid-row-start: 3;
grid-row-end: row3-end;
}
<div class="container">
<div id="main">
<button class="t-l">top left control</button>
<button class="t-r">top right control</button>
<button class="b-l">bottom left control</button>
<button class="b-r">bottom right control</button>
</div>
<div id="map"></div>
</div>