区分手持设备和台式机上的纵向模式
Posted
技术标签:
【中文标题】区分手持设备和台式机上的纵向模式【英文标题】:Differentiating between portrait mode on handheld devices and desktops 【发布时间】:2012-11-06 00:12:08 【问题描述】:我正在寻找一个可靠的媒体查询规则:
If desktop width < 720px AND devices in portrait mode
(也就是说,随着桌面上宽度的减小,媒体查询会在 720 像素处启动。在手机上,这只会在纵向模式下发生 - 横向不应应用媒体查询)
问题是:如何将目标设备与桌面分开。
问题存在是因为:@media handheld
不受支持
另外max-width
影响一切,因此不能与max-device-width AND portrait
结合使用
好像我只能定位其中一个:
-
所有设备都低于/在设置宽度之间
仅限设备(使用 javascript shim 修复媒体查询)低于/介于设置宽度和方向之间。
不能单独处理设备和桌面。
是否有现有的 JavaScript 解决方案可以满足我的需求?
注意我在 LESS 中编写我的 CSS,媒体查询嵌套在其中。
背景
我正在开发的网站是响应式的并使用网格系统。在 720px 宽度(当前测试宽度)下,较小设备/分辨率的列使用会发生变化。然而,经过测试,该站点(720px 宽度的完整站点)在横向上可读性很好,即使在我的小屏幕 HTC Desire 上也是如此。当我删除网站的某些部分以便更好地使用媒体查询时,我想为什么不让网站通常可以横向访问。
在没有修改元素列跨度的情况下,在桌面上使用 720 像素会看到一个非常崩溃的网站。但是,由于移动设备的较小性质,它看起来并非如此。然而,随着列跨度的修改,特定元素(例如标题)在手机横向(由于浏览器的高度大大降低)时完全不成比例。
简而言之,仅根据浏览器宽度更改设计并不能像我在其他网站上设法实现的那样在所有设备上均等。
我正在使用以下元标记:
<meta name="viewport" content="width=device-width,
initial-scale=1,
maximum-scale=1,
user-scalable=no" />
尝试过什么
方向与桌面无关。它会根据用户窗口设置、分辨率等而变化。
我已尝试以下方法来定位手机/两者:
@media handheld and (orientation:portrait)
似乎没有手机利用 handheld
属性,至少 100% 没有 - 所以它毫无价值。
@media screen and (max-device-width:720px) and (orientation:portrait)
会很好用,但 android 2.2 和 2.3(可能还有其他操作系统,更不用说其他操作系统了?)max-device-width
无法正常工作。
@media screen and (max-width:720px) and (orientation:portrait)
适用于高分辨率显示器(因为随着窗口宽度的减小,高度会迅速变为 > 宽度)和手机,但不适用于较小的显示器,因为窗口在 720 像素宽度时不会是纵向的(网站不断压缩超过我的限制)想要)。
@media screen and (max-width:720px), screen and (orientation:portrait)
先做任何事。没用。
@media screen and (max-width:720px), screen and (max-width:500px) and (orientation:portrait)
和
@media screen and (max-width:720px)
@media screen and (max-width:500px) and (orientation:portrait)
一切都只是使用较大的max-width
。
我也对min/max-height
进行了一次尝试,但也没有成功。
【问题讨论】:
只是一个先见之明。但是所有现代手持设备都有 html5 标准。因此,如果设备不支持 css3 prop,那么它可能是桌面 【参考方案1】:为了完整起见,这里解释如何使用 CSS 选择器来限定在嵌套 LESS 上下文中使用媒体查询。
@enginefree 的回答和以下 cmets 解释了如何检查移动设备、它的方向以及根据结果操作元素属性。
以下代码说明了如何使用 LESS &
和 CSS3 :not
选择器在我们正在寻找的属性或类未检测到时显示我们的媒体查询:
body
/* this has the possible class or data attribute of 'mobile' */
/* this is not included in the nest as you can't climb at will */
/* the class or attribute (via our JavaScript) could be applied
to any element that sits above and outside of `#level-1` in
this example */
#level-1
#level-2
#level-3
#level-4
body:not(.mobile) &
/* produces the following CSS */
/* body:not(.mobile) #level-1 #level-2 #level-3 #level-4 */
/* rules in this block will only be executed if body does not have a mobile class */
@media screen and (max-width:)
body:not([data-device=mobile]) &
/* produces the following CSS */
/* body:not([data-device="mobile"]) #level-1 #level-2 #level-3 #level-4 */
/* rules in this block will only be executed if body does not have a mobile data-device attribute */
@media screen and (max-width:)
如果body
元素是该嵌套的一部分,您最终会得到以下 CSS,这应该可以解释为什么该元素必须存在于嵌套范围之外以及它之上:
body:not(.mobile) body #level-1 #level-2 #level-3 #level-4
Read more about the &
operator
【讨论】:
【参考方案2】:我认为最好的方法是,根据 MDN(Mozilla 开发者网络)使用 window.innerHeight
文档 here 和 window.innerWidth
文档 here 在其中测量 浏览器 的宽度和高度像素来确定方向。
//Detect mobile platform
var isMobile =
Android: function()
return navigator.userAgent.match(/Android/i);
,
BlackBerry: function()
return navigator.userAgent.match(/BlackBerry/i);
,
ios: function()
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
,
Opera: function()
return navigator.userAgent.match(/Opera Mini/i);
,
Windows: function()
return navigator.userAgent.match(/IEMobile/i);
,
any: function()
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
;
if ( isMobile.any() )
if (window.innerHeight > window.innerWidth)
console.log("Orientation is in portrait");
else
console.log("Orientation is in landscape");
else
console.log("Mobile platform not detected.");
;
更多关于mobile平台的文档。
【讨论】:
+1 虽然认为这将是一个很好的起点,但最好使用 Detect Mobile Browser JavaScript 插件,它非常轻巧且功能强大。更多信息请参见SO Answer w/ jsFiddle DEMO。干杯! 现在我该如何从这一点出发 - 能够使用 JavaScript 检测移动设备 - 能够使用媒体查询和最大宽度在桌面上创建响应式站点,并在移动时忽略此规则检测到人像?为了使它更难,我在 LESS 中编码,并且媒体查询是嵌套的:D @Patrick:回答你的问题,我认为最简单的方法是让 javascript 在检测到时将一个类添加到body
标记(如 mobPort
),然后让你的媒体查询有他们在 CSS 选择器字符串中使用body:not(.mobPort) ...[your other selectors]
进行了限定,因此当它检测到该类时,它确实不应用媒体查询更改。
@Patrick:除了 ScottS 的评论,您还可以看到这个 SO Answer,它展示了如何根据条件设置选择 metatags
,并使用 LESS
调整该过程。
好主意@ScottS,虽然我需要研究旧桌面浏览器的兼容性...【参考方案3】:
您应该查看Modernizr。它包括对几乎所有有用的现代浏览器功能的功能检测/推断,特别是通过对Modernizr.touch
进行简单的布尔检查,包括设备是否基于触摸。从那里,您可以通过比较 document.width 和 document.height 来避免测试纵向/横向,例如:
if(Modernizr.touch)
// is touch device
if(document.height > document.width)
// is in portrait
else
// is in landscape
else
// not touch device
请注意,正如您所发现的,没有完美的触控/桌面测试,因此,如果您合并了 Modernizr 触控测试(或自己动手),最好咨询page that explains which touch tests are reliable, when。
【讨论】:
【参考方案4】:一个很棒的 JavaScript 库是 css3-mediaqueries-js。
【讨论】:
【参考方案5】:这三个规则涵盖了大多数移动设备
@media only screen and (min-width: 768px) and (max-width: 959px) @media only screen and (min-width: 480px) and (max-width: 767px) @media only screen and (max-width: 479px)
或者尝试使用 Skeleton Responsive 框架
【讨论】:
以上是关于区分手持设备和台式机上的纵向模式的主要内容,如果未能解决你的问题,请参考以下文章
为啥在较新的 Android 设备上预检失败,但在较旧的设备和台式机上却没有?