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

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

我正在看这个网站,但不幸的是,脚本是如此神秘,我不知道如何使用它为我的目的,这是创建一个返回true/false的函数。


使用Regex:

这里有一个函数,它使用了一个疯狂的长而全面的正则表达式,根据用户是否使用手机浏览,返回一个true或false值。

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。但是userAgentData仍然是实验性的,所以不建议在生产中使用。

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

userAgentData的兼容性图


最初的答案

你可以通过简单地运行一个设备列表并检查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);
    });
}

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

i.e

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

参考:

用javascript检测浏览器和设备


这是一个比匹配更有效的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 sensitive
    var 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指出的,窗口。Orientation现在已弃用,不应该使用。

编辑2:您可以使用实验屏幕。Orientation而不是弃用的window.orientation。在MDN中见。

编辑3:从窗口更改。朝向屏幕。朝向


功能检测比试图弄清楚你在使用哪个设备要好得多,而且很难跟上新设备的步伐,像Modernizr这样的库可以让你知道某个特定功能是否可用。


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

这很简单。函数如下:

// Used to detect whether the users browser is an mobile browser
function 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 storage 
        return false;
    else if (localStorage.mobile) // mobile storage
        return true;

    // alternative
    var 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 desktop
    return false;
}

最好的一定是:

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

但是就像Yoav Barnea说的…

// Seem legit
var 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" too
if (/Mobile/i.test(navigator.userAgent)) isMobile = true;

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


这是他的全部功能

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
}

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

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会从body标签中删除Mobile UA字符串。

CSS:

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

为开发添加了警报线。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

测试如果窗口。定义方向:

var isMobile = window.orientation > -1; alert(isMobile ?“移动设备”:“非移动设备”);


Note

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

var hasTouchscreen = 'ontouchstart'在窗口; 警报(hasTouchscreen ?'有触摸屏':'没有触摸屏');


这也是一种解决方案。

var isMobile = false; //initiate as false

  // device detection
  if(/(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 document
  var doc_w = $(document).width(); // returns width of HTML document
  console.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 / false
function 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怎么样?宽度”?

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

or

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。例如,一部iPhone 6....

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

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

不知何故,在以下浏览器应用程序上返回了以下结果。配置:iPhone 6S, iOS 10.3.1。

Safari(最新):将其作为移动设备检测。

Chrome(最新):没有检测到它作为一个移动。

SO, i then tested the suggestion from Lanti (https://stackoverflow.com/a/31864119/7183483), and it did return the proper results (mobile for all iOS devices, and desktop for my Mac). Therefore, i proceeded to edit it a little since it would fire twice (for both mobile and Tablet). I then noticed when testing on an iPad, that it also returned as a mobile, which makes sense, since the Parameters that Lanti uses check the OS more than anything. Therefore, i simply moved the tablet IF statement inside the mobile check, which would return mobile is the Tablet check was negative, and tablet otherwise. I then added the else clause for the mobile check to return as desktop/laptop, since both qualify, but then noticed that the browser detects CPU and OS brand. So i added what is returned in there as part of else if statement instead. To cap it, I added a cautionary else statement in case nothing was detected. See bellow, will update with a test on a Windows 10 PC soon.

哦,我还添加了一个'debugMode'变量,以便在调试和正常编译之间轻松切换。

Dislaimer:这完全是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");

(更新):

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

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

有一个简单的技巧来检测它是否是一个移动设备。检查ontouchstart事件是否存在:

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!
}

这对我来说效果很好,但是包含触摸屏的笔记本电脑设备可能会有一个问题。

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


返回'ontouchstart'在window && window.screen. availwidth < 768

这个怎么样,它扩展了上面的答案,但也检查了屏幕大小


不要使用这种方法作为窗口。朝向现在已弃用!!

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

正如许多人所说,依赖于用户代理数据的移动目标是有问题的。这同样适用于屏幕大小的计数。

我的方法借鉴了CSS技术来确定界面是否是触摸的:

只使用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';
});

如果您正在寻找的是表示的使用matchMedia,它返回一个布尔值:

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
}

这取决于您的用例。如果你专注于屏幕使用屏幕。availWidth,或者你可以使用document.body. clientwidth如果你想基于document进行渲染。


使用Regex:

/* 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 */

这就是我用的。我知道userAgent嗅探是不受欢迎的,但我的需求恰好是排除的之一!

<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 phone
function isMobile() {

    // regex from http://detectmobilebrowsers.com/mobile
    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(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 ) );
}

触摸屏和方向解决方案在某些个人电脑上无法使用。

一些笔记本电脑有触摸屏,希望将来会有更多。 另外,虽然我无法亲自测试,但一些图形平板电脑可以作为屏幕使用,可以使用触摸屏。

探测方向也行不通。微软(Microsoft) Surface Books等一些个人电脑拥有可拆卸的屏幕,使其像平板电脑一样工作,包括定向支持。但它仍然是一台真正的个人电脑。

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


IE10+解决方案仅使用matchMedia:

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

isMobile()返回布尔值


我还没看到有人建议:

window.navigator.connection.type

这只存在于移动设备上,不存在于桌面浏览器上。检查该属性是否存在更简单,即if(window && window。Navigator && window.navigator.connection && window.navigator.connection.type) =>那么它是移动的

注意:这是实验性的

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


特征检测

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

截至2022-02-07,工作在CHROME + SAFARI::结合功能检测并尝试本线程和其他网站中的所有内容。localStorage。移动工作在Chrome移动;后者适用于Safari移动版。在打开或不打开dev-tools时和/或在移动模拟器上不会触发桌面浏览器。在撰写本文时,它会触发一个真正的移动浏览器,而不是桌面。

请考虑

我还在Win10上的联想X1 Yoga(键盘模式或平板模式)上进行了测试

localStorage。无论如何,移动是没有定义的 当笔记本电脑处于键盘模式时:window.navigator。maxTouchPoints is 1→isMobile为false 当键盘向后翻转,笔记本电脑处于平板电脑模式时:window.navigator。maxTouchPoints是10→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,像壁虎)Chrome/103.0.0.0 Safari/537.36: false Mozilla / 5.0 (Linux;Android 10;小米A2) AppleWebKit/537.36 (KHTML,像壁虎)Chrome/105.0.0.0移动Safari/537.36: true


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

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

这篇MDN文章可以支持这种说法:https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#avoiding_user_agent_detection。

上面的答案是对著名的MDN文章中建议的移动检测解决方案的重构。它首先依赖于特性检查,然后作为导航器的最后手段进行回退。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 found
            console.log('Is mobile device!'); 
        }
    }
}
window.onresize = () => {
    isMobileDeviceCheck();
}
isMobileDeviceCheck();

PS:作为浏览器扩展的Useragent切换器不能用这段代码欺骗你。


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

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


UserAgent不是100%可靠的。

window.navigator.maxTouchPoints > 1;

这就够了!它排除了浏览器开发控制台中的电话模拟器。这对我来说很重要。