javascript Android 键盘使用 CSS 中的单位 vh 缩小视口和元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32963400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:57:31  来源:igfitidea点击:

Android Keyboard shrinking the viewport and elements using unit vh in CSS

javascriptandroidhtmlcss

提问by Manu

I am experiencing a very strange and unique issue.

我遇到了一个非常奇怪和独特的问题。

All my pages are using vh and vw CSS units instead of px due to the nature of the project.

由于项目的性质,我所有的页面都使用 vh 和 vw CSS 单位而不是 px。

Issue: On Android tablets, when you touch the input field the default keyboard pushes the view port which is causing the page and all the elements in the page to shrink.

问题:在 Android 平板电脑上,当您触摸输入字段时,默认键盘会推送导致页面和页面中所有元素缩小的视口。

On ipad this issue does not exist since the keyboard overlaps the screen and does not push the screen.

在 ipad 上不存在此问题,因为键盘与屏幕重叠并且不会推动屏幕。

Looking for any solution to avoid the Android keyboard not to push the viewport of the browser and keep the original size.

寻找任何解决方案来避免Android键盘不推送浏览器的视口并保持原始大小。

Note: The only option i am left with is to avoid keyboard to push viewport, i won't be able to change the CSS units or use xml, manifest. These are web pages which experiencing this issue.

注意:我剩下的唯一选择是避免使用键盘推送视口,我将无法更改 CSS 单位或使用 xml、manifest。这些是遇到此问题的网页。

回答by Tyler Merle

I know this is an old question, but I had the exact same problem in my app. The solution I found was fairly simple. (My app is in Angular so I put this in the app.component's ngOnInitfunction, but document.ready()or any other "initialization complete" callback should work just fine with the proper experimentation)

我知道这是一个老问题,但我的应用程序中遇到了完全相同的问题。我找到的解决方案相当简单。(我的应用程序在 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);

This forces the viewport meta to explicitly set viewport height, whereas hardcoding

这会强制视口元显式设置视口高度,而硬编码

<meta name="viewport" 
content="width=device-width, height=device-height, initial-scale=1">

doesn't work because the device-width and device-height change when Android's soft keyboard is opened.

不起作用,因为当 Android 的软键盘打开时,设备宽度和设备高度会发生变化。

回答by MatWer

Nearly a year to late, but I want also to share my solution to this more and more important problem.

快一年了,但我也想分享我对这个越来越重要的问题的解决方案。

I created a small JS function SET which is loaded after the DOM is completed.

我创建了一个小的 JS 函数 SET,它在 DOM 完成后加载。

Every Element assigned to a special class (In this case ".pheight") doesn't resized when the viewport height decreases. It is only allowed to resize if the viewport height increases or the viewport width changes.

当视口高度降低时,分配给特殊类(在本例中为“.pheight”)的每个元素都不会调整大小。只有在视口高度增加或视口宽度改变时才允许调整大小。

So in my Applications it works perfectly!

所以在我的应用程序中它完美地工作!

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

回答by Mayous

I faced the same problem recently, and it took me time to find a nice solution. I am designing a cordova app using html5, css3 and angularjs. But moreover, I want my app to fit every screen without writing tones of media queries and finally unreadable css. I started with viewport and vh, but the keyboard broke eveything.

我最近遇到了同样的问题,我花了很长时间才找到一个好的解决方案。我正在设计一个使用 html5、css3 和 angularjs 的cordova 应用程序。但此外,我希望我的应用程序适合每个屏幕,而无需编写媒体查询的音调,最终不可读的 css。我从视口和 vh 开始,但键盘破坏了一切。

So what you have to use is just a little javascript (here is jquery) like this :

所以你必须使用的只是一个像这样的小 javascript(这里是 jquery):

$("html").css({"font-size": ($(window).height()/100)+"px"});

Here you go, now you can use "rem" exactly the same way you are using "vh", except that the viewport will not affect font-size. "Rem" is set on html root font-size only and we just set it with jquery to 1% of the screen height.

好了,现在您可以使用与使用“vh”完全相同的方式使用“rem”,只是视口不会影响字体大小。“Rem”仅在 html root font-size 上设置,我们只是使用 jquery 将其设置为屏幕高度的 1%。

Hope this will help!

希望这会有所帮助!

EDIT 1 : I just faced a new problem, so I give my solution here. Most of the time, smartphones have a minimum limit for font-size. You have to change all your rem value, and divide it by 3 or 4. Then, you have to change the javascript with :

编辑 1:我刚遇到一个新问题,所以我在这里给出我的解决方案。大多数时候,智能手机都有字体大小的最小限制。您必须更改所有 rem 值,并将其除以 3 或 4。然后,您必须使用以下内容更改 javascript:

$("html").css({"font-size": ($(window).height()/25)+"px"}); /*(this is if you divide with 4)*/

It is even easier if you are using SASS, you can create a rem function which will do division for you.

如果您使用的是 SASS,那就更容易了,您可以创建一个 rem 函数来为您进行除法。

回答by Foxel

Based on Tyler's question, this is a vanilla version of the script which seems to be a bit cleaner:

基于 Tyler 的问题,这是脚本的香草版本,似乎更简洁一些:

addEventListener("load", function() {
    var viewport = document.querySelector("meta[name=viewport]");
    viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);
})

If you use it after the meta tag declaration you can even get rid of that addEventListener:

如果您在元标记声明之后使用它,您甚至可以摆脱它addEventListener

var viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute("content", viewport.content + ", height=" + window.innerHeight);

回答by Joe Keene

In Angular 4+

在 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'`
);
}

回答by Ced

You could use % which doesn't seems to be affected by this issue or vw (not affected for obvious reason) even for height.

您可以使用 % ,它似乎不受此问题或 vw (由于明显原因不受影响)的影响,即使是高度也是如此。

回答by MagiK

The same problem put me off my stride. I don't found any css solution or workaround in order to solve the problem.

同样的问题让我大吃一惊。我没有找到任何 css 解决方案或解决方法来解决问题。

However, if you can use JQuery (or almost JavaScript), I have some code you can use to resolve it.

但是,如果您可以使用 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);

Well, this is just an example, you can use the percentage, jQuery identifiers you need to.

嗯,这只是一个例子,你可以使用百分比,你需要的 jQuery 标识符。

PD: there's one tip for your info. put the code at the final of your html or inside $(document).ready(function() { });, and if you need responsive design, put it also inside orientationchange event; this way.

PD:有一个提示可以提供您的信息。把代码放在你的 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);});

I put a 450ms Timer above because of the delay of devices doing the orientationchange.

由于设备执行方向更改的延迟,我在上面放置了一个 450ms 计时器。

Sorry for my english, cheers

对不起我的英语,干杯