CSS 媒体查询 - 软键盘打破 css 方向规则 - 替代解决方案?

Posted

技术标签:

【中文标题】CSS 媒体查询 - 软键盘打破 css 方向规则 - 替代解决方案?【英文标题】:CSS Media Query - Soft-keyboard breaks css orientation rules - alternative solution? 【发布时间】:2012-02-11 13:55:39 【问题描述】:

我正在使用多个平板设备 - android ios。目前,我对所有平板电脑都有以下分辨率变化。

1280 x 800 1280 x 768 1024 x 768(显然是 iPad) - iPad 没有这个问题

应用基于设备方向的样式的最简单方法是使用以下语法使用媒体查询的方向。

@media all and (orientation:portrait)

  /* My portrait based CSS here */


@media all and (orientation:landscape)

  /* My landscape based CSS here */

这在所有平板设备上都可以正常工作。 但是,问题是,当设备处于纵向模式并且用户点击任何输入字段(例如搜索)时,软键盘会弹出 - 这会减少网页的可见区域并强制它在基于横向的 css 中渲染。在 android 平板设备上,它取决于键盘的高度。 所以,最终网页看起来坏了。因此,我不能使用 CSS3 的方向媒体查询来应用基于方向的样式(除非有更好的媒体查询来定位方向)。这是一个模仿这个的小提琴http://jsfiddle.net/hossain/S5nYP/5/ - 设备测试使用完整的测试页面 - http://jsfiddle.net/S5nYP/embedded/result/

这是从演示页面截取的行为截图。

那么,有没有其他方法可以解决这个问题,如果基于原生 CSS 的解决方案不起作用,我愿意接受基于 javascript 的解决方案。

我在http://davidbcalhoun.com/2010/dealing-with-device-orientation 上找到了一个 sn-p,它建议在此基础上添加类和目标。例如:

<html class="landscape">
  <body>
    <h1 class="landscape-only">Element Heading - Landscape</h1>
    <h1 class="portrait-only">Element Heading - Portrait</h1>
    <!-- .... more... ->

# CSS
.landscape .landscape-only  display:block; 
.landspace .portrait-only   display:none; 
.portrait .portrait-only    display:block; 
.portrait .landscape-only   display:none; 

你们怎么看这件事?你有更好的解决方案吗?

【问题讨论】:

刚刚发现,iPad NOT 有这个问题。只有安卓操作系统(蜂窝平板电脑)和手机有这个问题。 我的移动网站遇到了类似的问题。在几个 Android 设备上进行测试后,它似乎并不局限于任何特定的操作系统或移动/平板设备。它看起来主要是摩托罗拉和三星设备的问题。我无法在我们的 HTC 手机上重现该问题。 这个问题主要出现在安卓设备、手机/平板电脑上 - 重现此问题的唯一方法是安装高度较大的自定义键盘,这样当键盘显示时,webview 的可用高度小于可用宽度。只有这样,webview 才会触发方向更改。例如,在截图中,如果我可以禁用键盘顶部的建议层,那么这个问题就不存在了,因为 webview 的高度会大于宽度。但是,无论如何,我还没有任何优雅高效的解决方案。 只要意识到IOS 7.0.0全屏WebApp也有这种行为 See this answer for the solution 【参考方案1】:

我知道这已经晚了几年,但我找到了一个很好的解决方案

对于横向媒体:

@media screen and (min-aspect-ratio: 13/9)  /* landscape styles here */

对于肖像媒体:

@media screen and (max-aspect-ratio: 13/9)  /* portrait styles here */

完整的解决方案及其工作原理可以在这里找到Michael Barret - Android browser challenges

编辑:此链接现已过期,但可以在 Internet 存档中找到快照:Michael Barret - Android browser challenges

【讨论】:

它解决了问题,但对我来说在其他设备(主要是笔记本电脑和电脑)上产生了更多问题 很遗憾,此解决方案不适用于所有移动设备。 @StephanBijzitter 也许你可以使用'max-width'属性? 这个解决方案非常粗糙,在某些设备上不起作用。例如,我的手机在打开软键盘时大约为 17.7/9,而在许多其他设备上横向纵横比要小得多。 完整解决方案链接已损坏。【参考方案2】:

问题在于方向的计算方式:

http://www.w3.org/TR/css3-mediaqueries/#orientation

当“高度”媒体特征的值大于或等于“宽度”媒体特征的值时,“方向”媒体特征为“纵向”。否则“方向”就是“风景”。

由于高度/宽度是在可见视口上计算的,因此软键盘显然会导致方向翻转,因为视口宽度小于高度。一种解决方案是仅使用基于 width 的媒体查询。这使得它更灵活地跨设备而不考虑方向,更不用说宽度/高​​度比方向更广泛地支持。

如果你想考虑宽度而不是方向,我将以 iPhone 为例:

@media screen and (max-width: 320px) 
  /* rules applying to portrait */


@media screen and (max-width: 480px) 
  /* rules applying to landscape */

这种方法比方向更灵活,因为查询不仅限于支持方向的设备/用户代理,更不用说方向tells you very little 与宽度的对比了。

当然,如果您真的需要知道方向,似乎最初设置类并使用它可能是您的最佳选择。

【讨论】:

我了解浏览器是如何计算横向和纵向的。但是,需要替代和更好的方法来处理这个问题。另一个有趣的事情是,当键盘启动时,iPad 不会触发方向变化。我不知道为什么 **** android 必须这样实现。 我只是好奇为什么您特别需要设备的方向而不是宽度。您试图解决仅靠宽度无法解决的问题是什么? 我正在使用具有不同分辨率的多个设备。您能否举例说明如何将宽度用作方向的替代方法?关于方向变化的使用,方向变化有多种应用——通常不同方向的可用空间不同。因此,可以根据方向隐藏某些元素或调整其大小。感谢所有的帮助。 @HossainKhan @media all and (max-device-wdith:NNNpx)@media all and (min-device-wdith:NNNpx)@media all and (device-wdith:NNNpx) 最终通过删除and (orientation:portrait) 并应用最大和最小宽度解决了我的问题。!!!【参考方案3】:

另一种方法可能是使用device-aspect-ratio,它保持不变。但是,在 Webkit 中,旋转设备不会触发使用此查询更新 CSS 规则,即使 JavaScript 测试对于新的纵横比返回 true。这显然是due to a bug,但我找不到错误报告。使用orientationmin,max-device-aspect-ratio 的组合似乎可以正常工作:

@media screen and (max-device-aspect-ratio: 1/1) and (orientation: portrait)
@media screen and (min-device-aspect-ratio: 1/1) and (orientation: landscape)

orientation 的使用按预期触发更新,device-aspect-ratio 的使用将更新限制为实际的方向变化。

【讨论】:

不幸的是,这个功能现在被弃用了developer.mozilla.org/en-US/docs/Web/CSS/@media/… 2020 年中期,尽管已被弃用,但它仍然有效......很棒的解决方案,在我拥有的所有情况下,唯一真正为我工作的解决方案!【参考方案4】:

我研究了上面列出的选项,但没有一个能完全解决我的问题。我切换到使用 screen.availHeight,因为它提供了一致的高度结果,避免了键盘显示问题。

// Avoiding the keyboard in Android causing the portrait orientation to change to landscape. 
// Not an issue in IOS. Can use window.orientation.
var currentOrientation = function() 
  // Use screen.availHeight as screen height doesn't change when keyboard displays.  
  if(screen.availHeight > screen.availWidth)
    $("html").addClass('portrait').removeClass('landscape'); 
   else 
    $("html").addClass('landscape').removeClass('portrait'); 
  


// Set orientation on initiliasation
currentOrientation();
// Reset orientation each time window is resized. Keyboard opening, or change in orientation triggers this.
$(window).on("resize", currentOrientation);

【讨论】:

所以我已经对此进行了更多测试,但它并不是那么简单。 Android 设备需要使用 screen.availHeight 和 screen.availWidth。 IOS 在这些方面存在问题,因此请为 IOS 使用 window.orientation。桌面应使用 window.innerHeight、window.innerWidth,因为您希望窗口尺寸而不是屏幕尺寸。 我一直在用上面的代码撞墙。太挑剔了。我不支持这个应用程序的桌面,所以我使用 window.orientation 是 Android 和 IOS 的神奇解决方案。现在工作正常。 var 方向 = Math.abs(window.orientation) === 90 ? '风景' : '肖像';【参考方案5】:

对我来说,这成功了:

  @media screen and (max-device-aspect-ratio: 1/1), (max-aspect-ratio: 1/1)
        /*Portrait Mode*/
;

max-aspect-ratio 只需调整窗口大小即可触发纵向模式(对 PC 和其他仅横向设备很有用),max-device-aspect-ratio 有助于智能手机或其他具有可变方向的设备。而且因为我没有声明横向模式的特定设置,即使max-aspect-ratio 向系统报告>1,如果Android 设备以这种方式定向,纵向模式仍将由max-device-aspect-ratio 触发。

1/1 部分基本上表示如果比例

【讨论】:

键盘出现的时候呢? 当虚拟键盘出现在移动设备上时,没有任何变化,因为设备的纵横比 (max-device-aspect-ratio) 仅在您实际旋转设备或故意更改屏幕方向从纵向到横向,反之亦然。 是的,我最终自己实现并测试了它。我正在围绕这个开发一个包:npmjs.com/package/mobile-orientation 回来询问一件事:(max-aspect-ratio: 1/1)。看来我们只需要这个位来检测桌面上的肖像? 对。 1/1 是为了确保完美的正方形仍然触发纵向模式(这在允许调整窗口大小的系统中是可能的,例如桌面上的浏览器窗口)。没有它,奇怪的事情就会以这个精确的比例发生。【参考方案6】:

我已经浏览了上面的几个答案,但没有一个完全符合我的要求,即尽可能地模仿 iPhone 的功能。以下是现在在生产中为我工作的内容。

它通过将设备视口的窗口宽度和高度分配给数据属性以供将来检查。由于手机在拉起键盘时不会调整宽度,只有高度、检查比率和宽度与原始宽度可以告诉你键盘是否向上。我还没有找到失败的用例,但我相信我会的。如果你们都找到了,请告诉我。

我正在使用一些全局变量,例如 InitialRun 和 MobileOrientation,它们用于 js 切换,我还使用 html5 数据属性将信息存储在 DOM 中以进行 css 操作。

    var InitialRun = true; // After the initial bootstrapping, this is set to false;
    var MobileOrientation = 'desktop';
    function checkOrientation(winW, winH) // winW and winH are the window's width and hieght, respectively
        if (InitialRun)
            if (winW > winH)
                $('body').attr('data-height',winW);
                $('body').attr('data-width',winH);
                MobileOrientation = 'landscape';    
                $('body').attr('data-orientation','landscape'); 
            
            else
                $('body').attr('data-height',winH);
                $('body').attr('data-width',winW);
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
            
        
        else
            if (winW > winH && winW != $('body').data('width'))
                MobileOrientation = 'landscape';    
                $('body').hdata('orientation','landscape'); //TODO:uncomment
                $('body, #wrapper').css('height':"100%",'overflow-y':'hidden');
                //$('body').attr('data-orientation','portrait');
            
            else
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
                $('body, #wrapper').css('height':$('body').data('height'),'overflow-y':'auto');
            
        

    

【讨论】:

【参考方案7】:

我用了一个简单的技巧来解决这个问题

@media (max-width: 896px) and (min-aspect-ratio: 13/9)/* Landscape content*/

我发现 max-width: 896px 可用于所有移动设备。试试这个解决方案吧!

【讨论】:

你拯救了我的一天:),但是当它从横向返回到纵向时,页面的缩放被破坏了如何处理这个? 这依赖于当前移动设备的最大宽度,并且在改进技术时这些会发生变化。那么我们应该改变所有的媒体查询场景吗?我认为这是一个糟糕的主意。【参考方案8】:

看看这个链接: http://www.alistapart.com/articles/a-pixel-identity-crisis/ 不仅依靠方向,还依靠max-device-heightdevice-pixel-ratio 可能会有所帮助。无论如何,我没有测试它,所以不确定它是否会有所帮助。

【讨论】:

【参考方案9】:

想法:从你的媒体查询中去掉纵向参数,只保留一个最小宽度。在该媒体查询中为纵向模式执行正常样式。然后,为横向模式创建另一个媒体查询,其最小高度足够高,以便浏览器在键盘弹出时不会使用该查询。您必须尝试这个“足够高的最小高度”是什么,但这应该不会太难,因为大多数(如果不是全部)横向模式的高度都比键盘弹出时的高度要大。此外,您可以在横向查询中添加一个“最小宽度”,该查询比纵向视图中的大多数智能手机更大(即大约 400 像素)以限制查询范围。

这里有一个替代的(和脆弱的)解决方案: - 将一个空的任意元素添加到您的 html 中,该元素在纵向模式以外的任何内容中都将显示“显示:无”。 - 为 input:focus 创建一个 jquery 或 javascript 侦听器。单击输入时,您的 javascript 会检查任意元素的显示属性。如果它返回“块”或您在纵向模式下设置的任何内容,那么您可以使用 JS 将样式覆盖到纵向模式查询中。相反,您将有一个 input:blur 侦听器来清除您硬编码的元素的 style.cssText 属性。

我现在正在自己尝试这个 - 当我得到一些可靠且易于管理的东西时,我会发布代码。 (我的第一个解决方案似乎是最合理的)。

【讨论】:

【参考方案10】:

这对我来说很可靠。我正在使用 http://detectmobilebrowsers.com/ 作为 jQuery 扩展来检测 $.browser.mobile。

if ($.browser.mobile) 
  var newOrientationPortrait = true;

//Set orientation based on height/width by default
  if ($(window).width() < $(window).height())
      newOrientationPortrait = true;
  else
      newOrientationPortrait = false;

//Overwrite orientation if mobile browser supports window.orientation
if (window.orientation != null)
    if (window.orientation === 0)
        newOrientationPortrait = true;
    else
        newOrientationPortrait = false;

这是我根据方向修改视口的代码。此功能仅适用于移动设备,甚至平板电脑也不适用。这让我可以轻松地为 400 像素和 800 像素(纵向与横向)编写 CSS。

_onOrientationChange = function() 
    if (_orientationPortrait) 
        $("meta[name=viewport]").attr("content", "width=400,user-scalable=no");
    else 
        $("meta[name=viewport]").attr("content", "width=800");

由于我的需求性质,我无法单独在 CSS 媒体查询中执行此操作,因为 DOM 本身需要根据方向进行更改。不幸的是,在我的工作中,业务人员编写软件需求时没有先咨询开发。

【讨论】:

【参考方案11】:

我在 iPad 中遇到了完全相同的问题。 IE;当软键盘以纵向模式出现时,设备会被检测为横向,并且横向样式会应用于屏幕,从而导致视图混乱。

设备规格

设备:iPad Mini 4 操作系统:iOS 11.2.6 屏幕分辨率:1024 x 768

不幸的是,对我来说,这个解决方案没有奏效。

@media screen and (min-aspect-ratio: 13/9)  /* landscape styles here */
@media screen and (max-aspect-ratio: 13/9)  /* portrait styles here */

所以,我所做的是,我为我的肖像模式编写了这样的媒体查询。

@media only screen and (min-width : 300px) and (max-width : 768px) and (orientation : landscape) 
/* portrait styles, when softkeyboard appears, goes here */

即;当软键盘出现时,屏幕高度减小,但屏幕宽度保持在 768px,导致媒体查询将屏幕检测为横向。因此,上面给出了解决方法。

【讨论】:

【参考方案12】:

由于 iPhone 11 Pro Max 视口为 414 x 896 PX - 应该足以有方向:横向最小宽度:500 像素

【讨论】:

以上是关于CSS 媒体查询 - 软键盘打破 css 方向规则 - 替代解决方案?的主要内容,如果未能解决你的问题,请参考以下文章

CSS3 @Media 媒体查询

CSS3 @Media 媒体查询

如何使用 CSS 媒体查询检测设备方向?

CSS媒体查询重叠的规则是啥?

CSS媒体查询方向更改不起作用PhoneGap

媒体查询断点上的 CSS 重置值(调整窗口大小或方向更改)