我正在经历一种非常奇怪和独特的问题。
由于项目的性质,所有我的页面都使用vh和vw CSS单位而不是px。
问题:在Android平板电脑上,当您触摸输入字段时,默认键盘会推动视口,导致页面及页面中的所有元素缩小。
在iPad上不存在此问题,因为键盘重叠在屏幕上并且不会推动屏幕。
寻找任何解决方案以避免Android键盘推动浏览器视口并保持原始大小。
注意:我唯一的选择是避免键盘推动视口,我将无法更改CSS单位或使用xml、manifest。这些是出现此问题的Web页面。
我正在经历一种非常奇怪和独特的问题。
由于项目的性质,所有我的页面都使用vh和vw CSS单位而不是px。
问题:在Android平板电脑上,当您触摸输入字段时,默认键盘会推动视口,导致页面及页面中的所有元素缩小。
在iPad上不存在此问题,因为键盘重叠在屏幕上并且不会推动屏幕。
寻找任何解决方案以避免Android键盘推动浏览器视口并保持原始大小。
注意:我唯一的选择是避免键盘推动视口,我将无法更改CSS单位或使用xml、manifest。这些是出现此问题的Web页面。
我知道这是一个老问题,但是我的应用程序中也遇到了完全相同的问题。我发现的解决方案非常简单。(我的应用程序是在Angular中,所以我将它放在了app.component
的ngOnInit
函数中,但是document.ready()
或任何其他“初始化完成”的回调都可以通过适当的实验正常工作)
setTimeout(function () {
let viewheight = $(window).height();
let viewwidth = $(window).width();
let viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute("content", "height=" + viewheight + "px, width=" + viewwidth + "px, initial-scale=1.0");
}, 300);
这将强制 viewport meta 明确设置视口高度,而硬编码则不会
<meta name="viewport"
content="width=device-width, height=device-height, initial-scale=1">
当Android软键盘打开时,设备的宽度和高度会发生变化,因此不起作用。
window.innerHeight
和window.innerWidth
(或$(window).height()
和$(window).width()
)的值不会被正确设置。因此,如果您正在使用此工具进行开发,请在代码运行于开发浏览器中时查询window.visualViewport.height
和window.visualViewport.width
。 - Merlin Denker根据Tyler的问题,这是一个纯净版的脚本:
addEventListener("load", function() {
var viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
})
如果您在元标记声明后使用它,甚至可以摆脱那个addEventListener
:
var viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
这里有一个考虑到屏幕方向变化的更完整的解决方案:
// Original viewport definition, note the "id" that I use to modify the viewport later on:
<meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<script>
// Global boolean variable that holds the current orientation
var pageInPortraitMode;
// Listen for window resizes to detect orientation changes
window.addEventListener("resize", windowSizeChanged);
// Set the global orientation variable as soon as the page loads
addEventListener("load", function() {
pageInPortraitMode = window.innerHeight > window.innerWidth;
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
})
// Adjust viewport values only if orientation has changed (not on every window resize)
function windowSizeChanged() {
if (((pageInPortraitMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraitMode === false) && (window.innerHeight > window.innerWidth))) {
pageInPortraitMode = window.innerHeight > window.innerWidth;
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
}
}
</script>
最近我也遇到了同样的问题,花费了一些时间才找到一个不错的解决方案。我正在使用html5、css3和angularjs设计cordova应用程序。但是更重要的是,我希望我的应用程序适合每个屏幕,而不需要编写大量媒体查询和最终难以阅读的css。我从viewport和vh开始,但是键盘破坏了一切。
因此,您只需要使用一点javascript(这里是jquery),如下所示:
$("html").css({"font-size": ($(window).height()/100)+"px"});
现在你可以像使用“vh”一样使用“rem”,但视口不会影响字体大小。“rem”仅设置在html根字体大小上,我们只需使用jquery将其设置为屏幕高度的1%。
希望这能有所帮助!
编辑1: 我刚遇到一个新问题,所以在这里提供我的解决方案。大多数时候,智能手机都有最小字体大小限制。 您必须更改所有的rem值,并将其除以3或4。 然后,您需要更改javascript代码:
$("html").css({"font-size": ($(window).height()/25)+"px"}); /*(this is if you divide with 4)*/
如果您使用SASS,那么更容易实现,您可以创建一个rem函数,它会为您执行除法运算。
var docwidth = window.innerWidth;
var docheight = window.innerHeight;
function pheigt_init() {
pheigt_set_prevent_height();
window.onresize = function() {
if (docwidth !== window.innerWidth || docheight < window.innerHeight) {
pheigt_upd_prevent_height();
}
};
}
function pheigt_set_prevent_height() {
document.querySelectorAll('.pheight').forEach(function(node) {
node.style.height = node.offsetHeight + 'px';
});
}
function pheigt_upd_prevent_height() {
document.querySelectorAll('.pheight').forEach(function(node) {
node.style.removeProperty('height');
});
setTimeout(function(){ pheigt_set_prevent_height(); }, 100);
docheight = window.innerHeight;
docwidth = window.innerWidth;
}
document.addEventListener('DOMContentLoaded', pheigt_init());
在Angular 4+中
import {Meta} from "@angular/platform-browser";
constructor(private metaService: Meta){}
ngOnInit() {
this.metaService.updateTag({
name: 'viewport',
content: `height=${this.height}px, width=${this.width}px, initial-scale=1.0`
},
`name='viewport'`
);
}
您可以使用 %,它似乎不受此问题的影响,或者使用 vw(由于明显的原因)即使是对于高度也不受影响。
我正在创建一个PWA,其中禁用了所有滚动和缩放功能,对我来说问题是,我使用视口单位来精确计算我的布局。通过事件设置视口有所帮助,但是当Android键盘出现时,window.onresize
事件也会被调用。我的解决方案是通过检查document.activeElement
是否为文本区域或输入字段来判断是否使用了键盘。
唯一的缺点是,当用户在使用键盘时更改屏幕方向(这并不常见)时,视口调整大小会失败。为了防止这种情况发生,元素会失焦,从而关闭键盘,以避免布局破坏。虽然不太用户友好,但这可以被认为是一个相当罕见的边缘情况。
最终代码:
window.onresize = () => {
if(document.activeElement.tagName !== 'TEXTAREA' && document.activeElement.tagName !== 'INPUT'){
setViewportSize();
}
}
window.onorientationchange = () => {
// check if keyboard is used
if(document.activeElement.tagName === 'TEXTAREA' || document.activeElement.tagName === 'INPUT'){
document.activeElement.blur();
}
setViewportSize();
}
function setViewportSize(){
document.documentElement.style.setProperty('--screen-width', `${window.innerWidth}px`);
document.documentElement.style.setProperty('--screen-height', `${window.innerHeight}px`);
}
请记住,window.onorientationchange
已被弃用,可能在某些时候无法使用
也许需要使用一个函数来刷新视口高度(或仅高度)?
const reference = useRef();
function avoidKeyboard(){
setTimeout(
()=>{reference.current.querySelector("#win").style.height = "calc(100vh)"}
,2000)
}
return (
<ref={reference} div>
<input type="text" id="win" onFocus={avoidKeyboard} onBlur={avoidKeyboard}/>
</div>
)
同样的问题让我失去了信心。我没有找到任何CSS解决方案或变通方法来解决这个问题。
然而,如果你可以使用jQuery(或几乎任何JavaScript),我有一些代码可以帮助你解决它。
var viewportHeight = $(window).height();
var viewportWidth = $(window).width();
$('body,html').css("height",viewportHeight); //if vh used in body/html too
$('.someClass').css("height",viewportHeight*0.12);// or whatever percentage you used in vh
$('#someId').css("width",viewportWidth*0.12);
好的,这只是一个例子,你可以使用百分比、jQuery标识符等等。
提示:把代码放在HTML的最后或者$(document).ready(function() {};中,并且如果你需要响应式设计,在orientationchange事件中也要添加;就像这样。
$(window).on("orientationchange",function(event){ window.setTimeout(function(){
var viewportHeight = $(window).height();
var viewportWidth = $(window).width();
$('body,html').css("height",viewportHeight);
$('.someClass').css("height",viewportHeight*0.12);
$('.someClass').css("width",viewportWidth*0.09);
$('#someId').css("height",viewportHeight*0.1);
}}, 450);});
我放了一个450毫秒的定时器,因为设备进行方向更改时有延迟。
对不起我的英语, 干杯
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
- thdoan