检测移动浏览器

我正在寻找一个函数,如果用户使用移动浏览器或不返回布尔值。

我知道我可以使用navigator.userAgent并使用regex编写该函数,但是用户代理对于不同的平台来说太多样化了。我怀疑匹配所有可能的设备会很容易,我认为这个问题已经解决了很多次,所以应该有某种完整的解决方案来完成这样的任务。

我正在查看本网站,但遗憾的是脚本非常神秘,我不知道如何将其用于我的目的,即创建一个返回true/false的函数。

1433028 次浏览

使用正则表达式(来自detectmobilebrowsers.com):

这是一个使用超长且全面的正则表达式的函数,它返回truefalse值,具体取决于用户是否正在使用移动设备浏览。

window.mobileCheck = function() {let check = false;(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);return check;};

对于那些希望在此测试中包含平板电脑的人(尽管可以说,您不应该),您可以使用以下功能:

window.mobileAndTabletCheck = function() {let check = false;(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);return check;};

使用navigator.userAgentData

您也可以使用navigator.userAgentData.mobile,但userAgentData仍然是实验性的,因此不建议在生产中使用。

const isMobile = navigator.userAgentData.mobile; //resolves true/false

用户代理数据的兼容性图表


原始答案

您可以通过简单地运行设备列表并检查useragent是否匹配以下内容来做到这一点:

  function detectMob() {const toMatch = [/Android/i,/webOS/i,/iPhone/i,/iPad/i,/iPod/i,/BlackBerry/i,/Windows Phone/i];    
return toMatch.some((toMatchItem) => {return navigator.userAgent.match(toMatchItem);});}

然而,既然你认为这种方法是不可靠的,你可以假设任何分辨率为0或更低的设备也是移动设备,从而进一步缩小你的目标范围(尽管现在许多移动设备的分辨率都比这高得多)。

  function detectMob() {return ( ( window.innerWidth <= 800 ) && ( window.innerHeight <= 600 ) );}

参考:

这里有一个userAgent解决方案,比匹配更有效…

function _isMobile(){// if we want a more complete list use this: http://detectmobilebrowsers.com/// str.test() is more efficent than str.match()// remember str.test is case sensitivevar isMobile = (/iphone|ipod|android|ie|blackberry|fennec/).test(navigator.userAgent.toLowerCase());return isMobile;}
const 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) || navigator.userAgent.match(/WPDesktop/i);},any: function() {return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());}};

如何使用

if( isMobile.any() ) alert('Mobile');

要检查用户是否在特定的移动设备上:

if( isMobile.iOS() ) alert('iOS');

参考:http://www.abeautifulsite.net/blog/2011/11/detecting-mobile-devices-with-javascript

GitHub上的增强版:https://github.com/smali-kazmi/detect-mobile-browser

不如:

if (typeof screen.orientation !== 'undefined') { ... }

…因为智能手机通常支持此属性而桌面浏览器不支持。参见MDN

编辑1:正如@Gajus所指出的,window.orientation现在是已弃用,不应该被使用。

编辑2:您可以使用实验screen.orientation而不是不建议使用的window.orientation。参见MDN

编辑3:从window.orientation改为screen.orientation

功能检测比试图找出您使用的设备要好得多,并且很难跟上新设备的出现,像modnizr这样的库可以让您知道特定功能是否可用。

为了添加额外的控制层,我使用HTML5存储来检测它是使用移动存储还是桌面存储。如果浏览器不支持存储,我有一个移动浏览器名称数组,并将用户代理与数组中的浏览器进行比较。

这很简单。这是函数:

// Used to detect whether the users browser is an mobile browserfunction isMobile() {///<summary>Detecting whether the browser is a mobile browser or desktop browser</summary>///<returns>A boolean value indicating whether the browser is a mobile browser or not</returns>
if (sessionStorage.desktop) // desktop storagereturn false;else if (localStorage.mobile) // mobile storagereturn true;
// alternativevar mobile = ['iphone','ipad','android','blackberry','nokia','opera mini','windows mobile','windows phone','iemobile'];for (var i in mobile) if (navigator.userAgent.toLowerCase().indexOf(mobile[i].toLowerCase()) > 0) return true;
// nothing found.. assume desktopreturn false;}

最好的应该是:

var isMobile = (/Mobile/i.test(navigator.userAgent));

但是就像Yoav Barnea说的…

// Seem legitvar isMobile = ('DeviceOrientationEvent' in window || 'orientation' in window);// But with my Chrome on windows, DeviceOrientationEvent == fct()if (/Windows NT|Macintosh|Mac OS X|Linux/i.test(navigator.userAgent)) isMobile = false;// My android have "linux" tooif (/Mobile/i.test(navigator.userAgent)) isMobile = true;

在这3个测试之后,我希望var isMobile是… ok

这是他的全部功能

function isMobile(){return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|android|ipad|playbook|silk/i.test(navigator.userAgent||navigator.vendor||window.opera)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test((navigator.userAgent||navigator.vendor||window.opera).substr(0,4)))}
jQuery.noConflict();jQuery(document).ready(function(){if(isMobile()) alert("Mobile"); else alert("Not Mobile");});

这里有一个来自Facebook的弹弓源代码的简单解决方案

const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);if (isMobile) {/* your code here */}

像这样的东西怎么样?

if((screen.width <= 640) ||(window.matchMedia &&window.matchMedia('only screen and (max-width: 640px)').matches)){// Do the mobile thing}

这是我对这个问题重新思考的解决方案。仍然不完美。唯一真正的解决方案是设备制造商开始认真对待“Mobile”和“Tablet”用户代理字符串。

window.onload = userAgentDetect;function userAgentDetect() {if(window.navigator.userAgent.match(/Mobile/i)|| window.navigator.userAgent.match(/iPhone/i)|| window.navigator.userAgent.match(/iPod/i)|| window.navigator.userAgent.match(/IEMobile/i)|| window.navigator.userAgent.match(/Windows Phone/i)|| window.navigator.userAgent.match(/Android/i)|| window.navigator.userAgent.match(/BlackBerry/i)|| window.navigator.userAgent.match(/webOS/i)) {document.body.className += ' mobile';alert('True - Mobile - ' + navigator.userAgent);} else {alert('False - Mobile - ' + navigator.userAgent);}if(window.navigator.userAgent.match(/Tablet/i)|| window.navigator.userAgent.match(/iPad/i)|| window.navigator.userAgent.match(/Nexus 7/i)|| window.navigator.userAgent.match(/Nexus 10/i)|| window.navigator.userAgent.match(/KFAPWI/i)) {document.body.className -= ' mobile';document.body.className += ' tablet';alert('True - Tablet - ' + navigator.userAgent);} else {alert('False - Tablet - ' + navigator.userAgent);}}

当Nexus 7平板电脑只有Android UA字符串时会发生什么?首先,Mobile变为true,然后Tablet也变为true,但Tablet会从主体标签中删除Mobile UA字符串。

css:

body.tablet { background-color: green; }body.mobile { background-color: red; }

alert为开发添加了行。Chrome控制台可以模拟许多手持设备。在那里测试。

编辑:

只是不要使用这个,而是使用特征检测。有这么多的设备和品牌,针对一个品牌永远不会是正确的解决方案。

没有完美的解决方案来检测JS代码是否在移动浏览器上执行,但在大多数情况下,以下两个选项应该可以工作。

选项1:浏览器嗅探

!function(a){var b=/iPhone/i,c=/iPod/i,d=/iPad/i,e=/(?=.*\bAndroid\b)(?=.*\bMobile\b)/i,f=/Android/i,g=/(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i,h=/(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i,i=/IEMobile/i,j=/(?=.*\bWindows\b)(?=.*\bARM\b)/i,k=/BlackBerry/i,l=/BB10/i,m=/Opera Mini/i,n=/(CriOS|Chrome)(?=.*\bMobile\b)/i,o=/(?=.*\bFirefox\b)(?=.*\bMobile\b)/i,p=new RegExp("(?:Nexus 7|BNTV250|Kindle Fire|Silk|GT-P1000)","i"),q=function(a,b){return a.test(b)},r=function(a){var r=a||navigator.userAgent,s=r.split("[FBAN");return"undefined"!=typeof s[1]&&(r=s[0]),s=r.split("Twitter"),"undefined"!=typeof s[1]&&(r=s[0]),this.apple={phone:q(b,r),ipod:q(c,r),tablet:!q(b,r)&&q(d,r),device:q(b,r)||q(c,r)||q(d,r)},this.amazon={phone:q(g,r),tablet:!q(g,r)&&q(h,r),device:q(g,r)||q(h,r)},this.android={phone:q(g,r)||q(e,r),tablet:!q(g,r)&&!q(e,r)&&(q(h,r)||q(f,r)),device:q(g,r)||q(h,r)||q(e,r)||q(f,r)},this.windows={phone:q(i,r),tablet:q(j,r),device:q(i,r)||q(j,r)},this.other={blackberry:q(k,r),blackberry10:q(l,r),opera:q(m,r),firefox:q(o,r),chrome:q(n,r),device:q(k,r)||q(l,r)||q(m,r)||q(o,r)||q(n,r)},this.seven_inch=q(p,r),this.any=this.apple.device||this.android.device||this.windows.device||this.other.device||this.seven_inch,this.phone=this.apple.phone||this.android.phone||this.windows.phone,this.tablet=this.apple.tablet||this.android.tablet||this.windows.tablet,"undefined"==typeof window?this:void 0},s=function(){var a=new r;return a.Class=r,a};"undefined"!=typeof module&&module.exports&&"undefined"==typeof window?module.exports=r:"undefined"!=typeof module&&module.exports&&"undefined"!=typeof window?module.exports=s():"function"==typeof define&&define.amd?define("isMobile",[],a.isMobile=s()):a.isMobile=s()}(this);
alert(isMobile.any ? 'Mobile' : 'Not mobile');

这个特定的浏览器嗅探代码是一个名为isMobile的库的代码。


备选案文2:window.orientation

测试是否定义了window.orientation

var isMobile = window.orientation > -1;alert(isMobile ? 'Mobile' : 'Not mobile');


说明

并非所有的触摸屏设备都是移动的,反之亦然。所以,如果你想专门为触摸屏实现一些东西,你不应该测试你的浏览器是否在移动设备上运行,而是测试这些设备是否支持触摸屏:

var hasTouchscreen = 'ontouchstart' in window;alert(hasTouchscreen ? 'has touchscreen' : 'doesn\'t have touchscreen');

这也可能是一个解决方案。

var isMobile = false; //initiate as false
// device detectionif(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))) isMobile = true;
console.log('Mobile device:'+isMobile);
var doc_h = $(document).height(); // returns height of HTML documentvar doc_w = $(document).width(); // returns width of HTML documentconsole.log('Height: '+doc_h);console.log('width: '+doc_w);
var iPadVertical = window.matchMedia("(width: 768px) and (height: 1024px) and (orientation: portrait)");var iPadHoricontal = window.matchMedia("(width: 1024px) and (height: 767px) and (orientation: landscape)");
console.log('Height: '+doc_h);console.log('width: '+doc_w);
if (iPadVertical.matches) {console.log('Ipad vertical detected');}else if (iPadHoricontal.matches){console.log('Ipad horicontal detected');}else {console.log('No Ipad');}

如果您使用这两种方法,您将获得检测不同设备的完美方法。

来到这里寻找一种简单,干净的方法来检测“触摸屏设备”,我将其归类为移动和平板电脑。在当前的答案中没有找到一个干净的选择,但确实解决了以下问题,这也可能对某人有所帮助。

var touchDevice = ('ontouchstart' in document.documentElement);

编辑:要同时支持带有触摸屏和手机的桌面,您可以使用以下功能:

var touchDevice = (navigator.maxTouchPoints || 'ontouchstart' in document.documentElement);
//true / falsefunction isMobile(){return (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent) );}

您也可以按照本教程来检测特定的移动设备。单击这里

我建议你检查http://wurfl.io/

简而言之,如果你导入一个很小的JS文件:

<script type='text/javascript' src="//wurfl.io/wurfl.js"></script>

您将留下一个JSON对象,如下所示:

{"complete_device_name":"Google Nexus 7","is_mobile":true,"form_factor":"Tablet"}

(当然,这是假设您使用的是Nexus 7),您将能够执行以下操作:

if(WURFL.form_factor == "Tablet"){//dostuff();}

这就是你正在寻找的。

免责声明:我为提供这项免费服务的公司工作。谢谢。

如何使用“window.screen.width”?

if (window.screen.width < 800) {// do something}

if($(window).width() < 800) {//do something}

我想这是最好的方法,因为每天都有新的移动设备!

(虽然我认为旧浏览器不支持,但试一试:))

这是一个ECMAScript 6解决方案(TypeScript就绪)

public isMobile(): boolean {let check = false;((a => {if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true;}))(navigator.userAgent || navigator.vendor);return check;}

在任何情况下,检查设备类型必须只调用一次:你的手机不能令人惊讶地停留在桌面上:)

因此,由userAgent检查的代码,建议在这里一段时间前,必须看起来像这样:

(function(a){window.isMobile = (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))})(navigator.userAgent||navigator.vendor||window.opera);
console.info('This is %s device', window.isMoblie ? 'mobile' : 'desktop');

请注意,大多数新一代移动设备现在具有大于600x400的分辨率。

测试证明:在这里运行了投票最多和最近的帖子,有一个可选的检查一次像这样运行:

(function(a){window.isMobile = (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))})(navigator.userAgent||navigator.vendor||window.opera);
alert("This browser was found to be a % browser.", window.isMobile ? 'mobile' : 'desktop');

不知何故,在以下浏览器应用程序上返回了以下结果。规格:iPhone6S,iOS10.3.1。

Safari(最新):将其检测为手机。

Chrome(最新):未将其检测为手机。

所以,我然后测试了Lantihttps://stackoverflow.com/a/31864119/7183483)的建议,它确实返回了正确的结果(所有iOS设备的移动设备,以及我的Mac的桌面)。因此,我继续编辑它,因为它会触发两次(对于手机和平板电脑)。然后,我注意到在iPad上测试时,它也作为手机返回,这是有道理的,因为Lanti使用的参数检查操作系统胜过任何东西。因此,我只是在移动检查中移动了平板电脑IF语句,这将返回移动平板电脑检查是否定的,平板电脑否则。然后,我为移动检查添加了else子句,以返回台式机/笔记本电脑,因为两者都符合条件,但随后注意到浏览器检测到CPU和操作系统品牌。所以我在那里添加了返回的内容,作为else if语句的一部分。为了限制它,我添加了一个警示性的其他语句,以防什么都没检测到。请参阅下面,将很快在Windows 10 PC上进行测试更新。

哦,我还添加了一个“调试模式”变量,可以轻松地在调试和正常编译之间切换。

免责声明:完全归功于Lanti,也没有在Windows平板电脑上测试…这可能会返回台式机/笔记本电脑,因为操作系统是纯Windows。一旦我找到一个使用它的朋友,我会检查的。

function userAgentDetect() {let debugMode = true;if(window.navigator.userAgent.match(/Mobile/i)|| window.navigator.userAgent.match(/iPhone/i)|| window.navigator.userAgent.match(/iPod/i)|| window.navigator.userAgent.match(/IEMobile/i)|| window.navigator.userAgent.match(/Windows Phone/i)|| window.navigator.userAgent.match(/Android/i)|| window.navigator.userAgent.match(/BlackBerry/i)|| window.navigator.userAgent.match(/webOS/i)) {if (window.navigator.userAgent.match(/Tablet/i)|| window.navigator.userAgent.match(/iPad/i)|| window.navigator.userAgent.match(/Nexus 7/i)|| window.navigator.userAgent.match(/Nexus 10/i)|| window.navigator.userAgent.match(/KFAPWI/i)) {window.deviceTypeVar = 'tablet';if (debugMode === true) {alert('Device is a tablet - ' + navigator.userAgent);}} else {if (debugMode === true) {alert('Device is a smartphone - ' + navigator.userAgent);};window.deviceTypeVar = 'smartphone';}} else if (window.navigator.userAgent.match(/Intel Mac/i)) {if (debugMode === true) {alert('Device is a desktop or laptop- ' + navigator.userAgent);}window.deviceTypeVar = 'desktop_or_laptop';} else if (window.navigator.userAgent.match(/Nexus 7/i)|| window.navigator.userAgent.match(/Nexus 10/i)|| window.navigator.userAgent.match(/KFAPWI/i)) {window.deviceTypeVar = 'tablet';if (debugMode === true) {alert('Device is a tablet - ' + navigator.userAgent);}} else {if (debugMode === true) {alert('Device is unknown- ' + navigator.userAgent);}window.deviceTypeVar = 'Unknown';}}

一旦元素获得焦点,你就会立即模糊它。Bootstrap-datepicker是一个非常受欢迎且维护良好的组件,在GitHub中拥有近10,000颗星,它使用这种方法:

if (window.navigator.maxTouchPoints || 'ontouchstart' in document) {this.input.blur();}

https://github.com/uxsolutions/bootstrap-datepicker

感谢跳跳虎的帮助。

根据MDN关于使用用户代理进行浏览器检测的文章,鼓励尽可能避免这种方法,并建议其他途径,如特征检测。

但是,如果必须使用用户代理作为检测设备是否移动的手段,他们建议:

总之,我们建议在文件中的任何地方查找字符串“Mobi”检测移动设备的用户代理。

因此,这一行就足够了:

const isMobileDevice = window.navigator.userAgent.toLowerCase().includes("mobi");

【更新】:

正如@zenw0lf在评论中建议的那样,使用正则表达式会更好:

const isMobileDevice = /Mobi/i.test(window.navigator.userAgent)

我通常发现检查仅在移动视图上可见的特定元素(例如汉堡图标)的可见性的更简单方法效果很好,并且比依赖非常复杂的正则表达式安全得多。这很难100%测试工作。

function isHidden(el) {return (el.offsetParent === null);}

这只是我在项目中使用的接受的答案的es6端口。请注意,这也包括平板电脑。

export const isMobile = () => {const vendor = navigator.userAgent || navigator.vendor || window.opera;
return !!(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(vendor) ||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(vendor.substr(0, 4)));};

有一个简单的技巧可以检测它是否是移动设备。只需检查ontouch start事件是否存在:

function isMobile(){return "ontouchstart" in window;}

检测移动或平板设备的一个非常好的方法是查看浏览器是否可以创建触摸事件。

纯JavaScript代码:

function isMobile() {try{ document.createEvent("TouchEvent"); return true; }catch(e){ return false; }}
if (isMobile()) {# do whatever you wanna do!}

这对我来说非常有效,但包括触摸屏显示器的笔记本电脑设备可能存在问题。

我不确定触摸屏笔记本电脑是否会被检测到是移动设备,因为我还没有测试过。

return 'ontouchstart' in window && window.screen.availWidth < 768

How about this, it expands on answer above but also checks the screen size

不要使用此方法,因为window.orientation已弃用!!!

function isMobile() {return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);};

正如许多人所说,依赖用户代理数据的移动目标是有问题的。计算屏幕大小也是如此。

我的方法是从css技术借来的,以确定接口是否为touch:

仅使用javascript(所有现代浏览器都支持),媒体查询匹配可以轻松推断设备是否为移动

function isMobile() {var match = window.matchMedia || window.msMatchMedia;if(match) {var mq = match("(pointer:coarse)");return mq.matches;}return false;}

取决于用例。所有移动设备都需要电池。如果您追求的是计算功率而不耗尽电池,请使用电池状态API

navigator.getBattery().then(battery => {battery.charging ? 'charging' : 'not charging';});

如果您要查找的是表示式使用#0,它返回一个布尔值:

if (window.matchMedia("(min-width: 400px)").matches) {/* the viewport is at least 400 pixels wide */} else {/* the viewport is less than 400 pixels wide */}

或者将它们结合起来,在平板设备上获得更好的用户体验。

我遇到过一些情况,上面的答案对我不起作用。所以我想到了这个。可能对某人有帮助。

if(/iPhone|iPad|iPod|Android|webOS|BlackBerry|Windows Phone/i.test(navigator.userAgent)|| screen.availWidth < 480){//code for mobile}

这取决于您的用例。如果您专注于屏幕,请使用screen.availWidth,或者如果您想基于文档呈现,您可以使用document.body.clientWidth

使用正则表达式(来自detectmobilebrowsers.com):

/* eslint-disable */export const IS_MOBILE = (function (a) {return (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))// @ts-ignore})(navigator.userAgent || navigator.vendor || window.opera)/* eslint-enable */

这是我使用的。我知道用户代理嗅探是不赞成的,但我的需求恰好是排除在外的一个!

<script>var brow = navigator.userAgent;if (/mobi/i.test(brow)) {alert('Mobile Browser');// Do something for mobile} else {alert('Not on Mobile');// Do something for non mobile}</script>
// Function returns true if current device is phonefunction isMobile() {
// regex from http://detectmobilebrowsers.com/mobilereturn /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(navigator.userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent)}
console.log({isMobile: isMobile()});

啊,是的,古老的问题…

这真的取决于你想做什么来回应知识。

1.您想更改UI以适应不同的屏幕尺寸吗?

使用媒体查询。

2.您想根据鼠标与触摸显示/隐藏内容或更改功能吗?

上面的答案会做但是,在某些情况下,用户可能同时拥有两者并进行切换。在这种情况下,当您检测到鼠标或触摸事件时,您可以切换一些JS变量和/或将类添加到文档正文

  window.addEventListener("mousemove", function () {isTouch = false;document.body.classList.add("canHover");});window.addEventListener("touchstart", function () {isTouch = true;document.body.classList.remove("canHover");});
body.canHover #aButtonOrSomething:hover {//css attributes}
  document.getElementById("aButtonOrSomething").addEventListener("mouseover", showTooltip);document.getElementById("aButtonOrSomething").addEventListener("click", function () {if (isTouch) showTooltip();});

3.你想做一些具体的知道他们有什么设备?

使用接受的答案。

这是Michael Zaporozhets回答的一个不那么模糊的版本。它还使用检查仅在第一次调用时构建正则表达式。有关从正则表达式数组构建字符串的技术,请参阅这个答案

var gRE = null;var gRE4 = null;
function PlatformIsMobile(){var e;    
if ( gRE == null ){e =[/(android|bb\d+|meego).+mobile|avantgo/,/bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile/,/ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox/,/netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker/,/pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone/,/wap|windows ce|xda|xiino|android|ipad|playbook|silk/];        
gRE = new RegExp(e.map( function( r ) { return r.source } ).join( "|" ), "i");}    
if ( gRE4 == null ){e =[/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa/,/abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)/,/aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan/,/be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)/,/c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw/,/da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)/,/el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)/,/g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)/,/haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)/,/i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris/,/ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)/,/le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx/,/m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)/,/mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]/,/n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph/,/o2im|op(ti|wv)|oran|owg1/,/p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g/,/qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek/,/r380|r600|raks|rim9|ro(ve|zo)/,/s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)/,/sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)/,/t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo/,/to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst/,/v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)/,/w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/];        
gRE4 = new RegExp(e.map( function( r ) { return r.source } ).join( "|" ), "i");}    
var key = navigator.userAgent || navigator.vendor || window.opera;    
return gRE.test( key ) ||gRE4.test( key.substr( 0, 4 ) );}

触摸屏和定向解决方案在某些PC上不起作用。

有些笔记本电脑有触摸屏,希望将来会更多。虽然我自己无法测试,但一些用作屏幕的图形平板电脑具有触摸屏功能。

检测方向也不起作用。一些PC,如Microsoft Surface Books,具有可拆卸的屏幕,使其像平板电脑一样工作,包括方向支持。但它仍然是一台真正的PC。

如果您必须检测和区分PC和移动设备,请阅读用户代理。
我不喜欢它,但它仍然是最好的方式。

仅使用MatchMedia的IE10+解决方案:

const isMobile = () => window.matchMedia('(max-width: 700px)').matches

isMobile()返回一个布尔值

我没有看到有人建议:

window.navigator.connection.type

这只存在于移动设备上,而不存在于桌面浏览器上。检查该属性的存在更简单,即if(window && window.navigator && window.navigator.connection && window.navigator.connection.type) => then it is mobile

注:这是实验

编辑(07.2022):该功能被视为潜在的跟踪漏洞利用,因此将从最新版本中删除。换句话说,不要使用这个!

功能检测

const isMobile = localStorage.mobile || window.navigator.maxTouchPoints > 1;

在CHROME+SAFARI中工作,截至2022-02-07:: 结合功能检测并尝试此线程和其他站点中的一切。localStorage.mobile适用于Chrome移动设备;后者适用于Safari移动设备。在打开开发工具和/或移动模拟器的情况下不会触发桌面浏览器。在撰写本文时,它会触发真正的移动浏览器,但不会触发桌面。

请考虑

我还在Win10上的联想X1 Yoga(键盘或平板电脑模式)上测试了这一点

  1. localStorage.mobile就是undefined,不管怎样
  2. 当笔记本电脑处于键盘模式时:
    window.navigator.maxTouchPoints1
    →isMobile是false
  3. 当键盘向后翻转并且笔记本电脑处于平板模式时:
    window.navigator.maxTouchPoints10
    →isMobile是true

这就是您如何找出用户使用的设备。

if (/ipad|tablet/i.test(navigator.userAgent)) {console.log("it's a Ipad"); // your code here}else if (/mobile/i.test(navigator.userAgent)) {console.log("it's a Mobile");} else {console.log("it's a Desktop");}

我搜索了Replit的代码(因为它在整个网站上都有错误),直到我看到:

(function (isTouchDevice) {if (!isTouchDevice) return;var isTouchClass = 'is-touch-device';var docElement = document.documentElement;docElement.className = docElement.className ? [docElement.className, isTouchClass].join(' ') : isTouchClass;})(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);

所以我把它修改成这样:

function isTouchDevice() {if (!(("ontouchstart" in window) || (window.DocumentTouch && document instanceof DocumentTouch))) {return false}return true}

来自不同用户代理的值:

  • Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36false
  • Mozilla/5.0 (Linux; Android 10; Mi A2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Mobile Safari/537.36true
  isMobile() {if ('maxTouchPoints' in navigator) return navigator.maxTouchPoints > 0;
const mQ = matchMedia?.('(pointer:coarse)');if (mQ?.media === '(pointer:coarse)') return !!mQ.matches;    
if ('orientation' in window) return true;    
return /\b(BlackBerry|webOS|iPhone|IEMobile)\b/i.test(navigator.userAgent) ||/\b(Android|Windows Phone|iPad|iPod)\b/i.test(navigator.userAgent);}

不建议使用navigator.userAgent嗅探,因为它不可靠并且差异很大。正如您在此处看到的:https://developers.whatismybrowser.com/useragents/explore/navigator.userAgent字符串在同一浏览器的版本之间可能会有很大差异。

这篇MDN文章可以支持以下语句:https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#avoiding_user_agent_detection

上面的答案是对建议的移动检测解决方案的重构,该解决方案来自于著名的MDN文章。它首先依赖于功能检查,然后回退作为navigator.userAgent嗅探的最后手段。

编码愉快!<3

我认为这是真正的保护解决方案。

测试在Chrome和Firefox,移动和桌面上。

var ___isMobileDevice;const isMobileDeviceCheck = () => {const mobileOsRegExp = "(Android|webOS|iPhone|iPod)";if(screen.width < 500 || navigator.userAgent.match('/'+mobileOsRegExp+'/i')) {___isMobileDevice = true;}if (___isMobileDevice) {if (typeof window.orientation === "undefined") {___isMobileDevice = false;}}if (typeof navigator.userAgentData != "undefined" && !navigator.userAgentData.mobile) {___isMobileDevice = false;}if ( typeof window.orientation !== "undefined" && ___isMobileDevice ) {if (window.navigator.maxTouchPoints > 1 && (navigator.userAgentData.mobile || localStorage.mobile || 'ontouchstart' in document)) {// mobile device foundconsole.log('Is mobile device!');}}}window.onresize = () => {isMobileDeviceCheck();}isMobileDeviceCheck();

PS:作为浏览器扩展的用户代理切换器不能用此代码欺骗您。

这是我发现的在所有情况下工作的最好方法。

Array.isArray(navigator.userAgent.match(/Android/i)||navigator.userAgent.match(/iPhone /i))