如何使用JavaScript检测Twitter Bootstrap 3的响应断点?

目前 ,Twitter Bootstrap 3具有以下响应断点:768px,992px和1200px,分别代表小型,中型和大型设备。

如何使用JavaScript检测这些断点?

我想用JavaScript来监听屏幕更改时触发的所有相关事件。 并能够检测到屏幕是否适用于小型,中型或大型设备。

有没有事情已经完成? 你有什么build议?

编辑:这个库现在可以通过鲍尔和NPM。 有关详细信息,请参阅github回购。

更新的答案:

  • 现场示例: CodePen
  • 最新版本: Github存储库
  • 不喜欢Bootstrap? 检查: 基础演示和自定义框架演示
  • 有一个问题? 打开一个问题

免责声明:我是作者。

以下是使用最新版本(Responsive Bootstrap Toolkit 2.5.0)可以执行的一些操作:

// Wrap everything in an IIFE (function($, viewport){ // Executes only in XS breakpoint if( viewport.is('xs') ) { // ... } // Executes in SM, MD and LG breakpoints if( viewport.is('>=sm') ) { // ... } // Executes in XS and SM breakpoints if( viewport.is('<md') ) { // ... } // Execute only after document has fully loaded $(document).ready(function() { if( viewport.is('xs') ) { // ... } }); // Execute code each time window size changes $(window).resize( viewport.changed(function() { if( viewport.is('xs') ) { // ... } }) ); })(jQuery, ResponsiveBootstrapToolkit); 

从版本2.3.0开始,您不需要下面提到的四个<div>元素。


原文答案:

我不认为你需要任何巨大的脚本或图书馆。 这是一个相当简单的任务。

</body>之前插入以下元素:

 <div class="device-xs visible-xs"></div> <div class="device-sm visible-sm"></div> <div class="device-md visible-md"></div> <div class="device-lg visible-lg"></div> 

这4个div允许您检查当前活动的断点。 为了方便JS检测,请使用以下function:

 function isBreakpoint( alias ) { return $('.device-' + alias).is(':visible'); } 

现在只需要在最小的断点处执行某个操作就可以使用:

 if( isBreakpoint('xs') ) { $('.someClass').css('property', 'value'); } 

在DOM准备好之后检测更改也相当简单。 所有你需要的是一个像这样的轻量级窗口resize的监听器:

 var waitForFinalEvent = function () { var b = {}; return function (c, d, a) { a || (a = "I am a banana!"); b[a] && clearTimeout(b[a]); b[a] = setTimeout(c, d) } }(); var fullDateString = new Date(); 

一旦你有了它,你可以开始监听更改并执行断点特定的function,如下所示:

 $(window).resize(function () { waitForFinalEvent(function(){ if( isBreakpoint('xs') ) { $('.someClass').css('property', 'value'); } }, 300, fullDateString.getTime()) }); 

如果你没有特定的需求,你可以这样做:

 if ($(window).width() < 768) { // do something for small screens } else if ($(window).width() >= 768 && $(window).width() <= 992) { // do something for medium screens } else if ($(window).width() > 992 && $(window).width() <= 1200) { // do something for big screens } else { // do something for huge screens } 

编辑:我不明白为什么你应该使用另一个js库,当你可以做到这一点,只是已经包含在您的Bootstrap项目中的jQuery。

你有没有看过Response.js? 它是为这种事情devise的。 结合Response.band和Response.resize。

http://responsejs.com/

 Response.resize(function() { if ( Response.band(1200) ) { // 1200+ } else if ( Response.band(992) ) { // 992+ } else if ( Response.band(768) ) { // 768+ } else { // 0->768 } }); 

您可以使用窗口大小和硬编码的断点。 使用Angular:

 angular .module('components.responsiveDetection', []) .factory('ResponsiveDetection', function ($window) { return { getBreakpoint: function () { var w = $window.innerWidth; if (w < 768) { return 'xs'; } else if (w < 992) { return 'sm'; } else if (w < 1200) { return 'md'; } else { return 'lg'; } } }; }); 

与Response.js一起使用这种方法更好。 每个窗口的Response.resize触发器resize,只有在断点发生变化时才会触发交叉

 Response.create({ prop : "width", breakpoints : [1200, 992, 768, 480, 320, 0] }); Response.crossover('width', function() { if (Response.band(1200)) { // 1200+ } else if (Response.band(992)) { // 992+ } else if (Response.band(768)) { // 768+ } else if (Response.band(480)) { //480+ } else { // 0->320 } }); Response.ready(function() { $(window).trigger('resize'); }); 

这里我自己的简单解决scheme

jQuery的:

 function getBootstrapBreakpoint(){ var w = $(document).innerWidth(); return (w < 768) ? 'xs' : ((w < 992) ? 'sm' : ((w < 1200) ? 'md' : 'lg')); } 

VanillaJS:

 function getBootstrapBreakpoint(){ var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; return (w < 768) ? 'xs' : ((w < 992) ? 'sm' : ((w < 1200) ? 'md' : 'lg')); } 

像@oozic提到的手动实现应该没有问题。

这里有几个库,你可以看看:

  • Response.js – jQuery插件 – 利用html数据属性,也有js api。
  • enquire.js – enquire.js是一个用于响应CSS媒体查询的轻量级纯JavaScript库
  • SimpleStateManager – 为响应式网站的JavaScript状态pipe理器。 它被build造成重量轻,没有依赖性。

请注意,这些库被devise为独立于bootstrap,foundation等工作。您可以configuration自己的断点并获得乐趣。

build立在Maciej Gurban的答案(这是太棒了…如果你喜欢这个,请直接投票他的答案)。 如果您正在构build查询服务,则可以使用下面的设置返回当前正在运行的服务。 这可以完全替代其他断点检测库(如果你把某些事件放在enquire.js中)。 请注意,我已经添加了一个带有ID的容器到DOM元素来加速DOM遍历。

HTML

 <div id="detect-breakpoints"> <div class="breakpoint device-xs visible-xs"></div> <div class="breakpoint device-sm visible-sm"></div> <div class="breakpoint device-md visible-md"></div> <div class="breakpoint device-lg visible-lg"></div> </div> 

COFFEESCRIPT(AngularJS,但这很容易兑换)

 # this simple service allows us to query for the currently active breakpoint of our responsive app myModule = angular.module('module').factory 'BreakpointService', ($log) -> # alias could be: xs, sm, md, lg or any over breakpoint grid prefix from Bootstrap 3 isBreakpoint: (alias) -> return $('#detect-breakpoints .device-' + alias).is(':visible') # returns xs, sm, md, or lg getBreakpoint: -> currentBreakpoint = undefined $visibleElement = $('#detect-breakpoints .breakpoint:visible') breakpointStringsArray = [['device-xs', 'xs'], ['device-sm', 'sm'], ['device-md', 'md'], ['device-lg', 'lg']] # note: _. is the lodash library _.each breakpointStringsArray, (breakpoint) -> if $visibleElement.hasClass(breakpoint[0]) currentBreakpoint = breakpoint[1] return currentBreakpoint 

JAVASCRIPT(AngularJS)

 var myModule; myModule = angular.module('modules').factory('BreakpointService', function($log) { return { isBreakpoint: function(alias) { return $('#detect-breakpoints .device-' + alias).is(':visible'); }, getBreakpoint: function() { var $visibleElement, breakpointStringsArray, currentBreakpoint; currentBreakpoint = void 0; $visibleElement = $('#detect-breakpoints .breakpoint:visible'); breakpointStringsArray = [['device-xs', 'xs'], ['device-sm', 'sm'], ['device-md', 'md'], ['device-lg', 'lg']]; _.each(breakpointStringsArray, function(breakpoint) { if ($visibleElement.hasClass(breakpoint[0])) { currentBreakpoint = breakpoint[1]; } }); return currentBreakpoint; } }; }); 

而不是使用$(document).width(),你应该设置一个CSS规则,给你这个信息。

我只是写了一篇文章,以准确地得到它。 在此处查看: http : //www.xurei-design.be/2013/10/how-to-accurately-detect-responsive-breakpoints/

您可能希望将其添加到引导程序项目中,以便可视化地检查活动断点

  <script type='text/javascript'> $(document).ready(function () { var mode; $('<div class="mode-informer label-info" style="z-index:1000;position: fixed;bottom:10px;left:10px">%mode%</div>').appendTo('body'); var checkMode = function () { if ($(window).width() < 768) { return 'xs'; } else if ($(window).width() >= 768 && $(window).width() < 992) { return 'sm'; } else if ($(window).width() >= 992 && $(window).width() < 1200) { return 'md'; } else { return 'lg'; } }; var compareMode = function () { if (mode !== checkMode()) { mode = checkMode(); $('.mode-informer').text(mode).animate({ bottom: '100' }, 100, function () { $('.mode-informer').animate({bottom: 10}, 100) }); } }; $(window).on('resize', function () { compareMode() }); compareMode(); }); </script> 

这是BOOTPLY

为什么不使用jQuery来检测引导程序容器类的当前css宽度?

即..

 if( parseInt($('#container').css('width')) > 1200 ){ // do something for desktop screens } 

如果有人调整浏览器窗口的大小,也可以使用$(window).resize()来防止布局“弄脏床”。

而不是在每个页面插入以下许多次…

 <div class="device-xs visible-xs"></div> <div class="device-sm visible-sm"></div> <div class="device-md visible-md"></div> <div class="device-lg visible-lg"></div> 

只要使用JavaScriptdynamic插入到每个页面(请注意,我已经更新它与Bootstrap 3使用.visible-*-block

 // Make it easy to detect screen sizes var bootstrapSizes = ["xs", "sm", "md", "lg"]; for (var i = 0; i < bootstrapSizes.length; i++) { $("<div />", { class: 'device-' + bootstrapSizes[i] + ' visible-' + bootstrapSizes[i] + '-block' }).appendTo("body"); } 

我没有足够的声望点评论,但对于那些在尝试使用Maciej Gurban的ResponsiveToolKit时遇到“无法识别”的问题,我也得到了这个错误,直到我注意到Maciej实际上是从底层引用了工具包在他的CodePen页面

我试图做到这一点,突然它的工作! 所以,使用ResponsiveToolkit,但把你的链接放在页面的底部:

我不知道为什么它有所作为,但它确实如此。

这里是另一种检测当前视口的方法, 而不会将视口大小编号放入您的javascript中。

在这里看到CSS和JavaScript片段: https : //gist.github.com/steveh80/288a9a8bd4c3de16d799

在将这些代码片段添加到您的css和javascript文件后,您可以像这样检测当前的视口:

 viewport.is('xs') // returns boolean 

如果你想检测一个视口范围,就像这样使用它

 viewport.isEqualOrGreaterThan('sm') // returns true for sm, md and lg 

我为Twitter Bootstrap屏幕大小检测做了一个本机jQuery方法。 这是:

 // Screen size ID will be stored in this variable (global var for JS) var CurrentBootstrapScreenSize = 'unknown'; $(document).ready(function () { // <div> objects for all screen sizes required for screen size detection. // These <div> is hidden for users eyes. var currentScreenSizeDetectorObjects = $('<div>').css({ 'position':'absolute', 'top':'-200px' }).addClass('current-screen-size').append([ $('<div>').addClass('device-xs visible-xs').html('&nbsp;'), $('<div>').addClass('device-sm visible-sm').html('&nbsp;'), $('<div>').addClass('device-md visible-md').html('&nbsp;'), $('<div>').addClass('device-lg visible-lg').html('&nbsp;') ]); // Attach <div> objects to <body> $('body').prepend(currentScreenSizeDetectorObjects); // Core method for detector function currentScreenSizeDetectorMethod() { $(currentScreenSizeDetectorObjects).find('div').each(function() { var className = $(this).attr('class'); if($(this).is(':visible')) { if(String(className).match(/device-xs/)) CurrentBootstrapScreenSize = 'xs'; else if(String(className).match(/device-sm/)) CurrentBootstrapScreenSize = 'sm'; else if(String(className).match(/device-md/)) CurrentBootstrapScreenSize = 'md'; else if(String(className).match(/device-lg/)) CurrentBootstrapScreenSize = 'lg'; else CurrentBootstrapScreenSize = 'unknown'; }; }) console.log('Current Bootstrap screen size is: '+CurrentBootstrapScreenSize); $('.CurrentBootstrapScreenSize').first().html('Bootstrap current screen size: <b>' + CurrentBootstrapScreenSize + '</b>' ); } // Bind screen size and orientation change $(window).bind("resize orientationchange", function() { // Execute screen detection currentScreenSizeDetectorMethod(); }); // Execute screen detection on page initialize currentScreenSizeDetectorMethod(); }); 

JSFillde: https ://jsfiddle.net/pstepniewski/7dz6ubus/

作为全屏示例的JSFillde: https ://jsfiddle.net/pstepniewski/7dz6ubus/embedded/result/

Bootstrap的.container类的CSS如下所示:

 .container { padding-right: 15px; padding-left: 15px; margin-right: auto; margin-left: auto; } @media (min-width: 768px) { .container { width: 750px; } } @media (min-width: 992px) { .container { width: 970px; } } @media (min-width: 1200px) { .container { width: 1170px; } } 

所以这意味着我们可以安全地依靠jQuery('.container').css('width')来检测断点而不依赖于jQuery(window).width()的缺点。

我们可以写一个这样的函数:

 function detectBreakpoint() { // Let's ensure we have at least 1 container in our pages. if (jQuery('.container').length == 0) { jQuery('body').append('<div class="container"></div>'); } var cssWidth = jQuery('.container').css('width'); if (cssWidth === '1170px') return 'lg'; else if (cssWidth === '970px') return 'md'; else if (cssWidth === '750px') return 'sm'; return 'xs'; } 

然后testing它

 jQuery(document).ready(function() { jQuery(window).resize(function() { jQuery('p').html('current breakpoint is: ' + detectBreakpoint()); }); detectBreakpoint(); }); 

使用CSS :beforecontent属性在<span id="breakpoint-js">打印断点状态,所以JavaScript只需要读取这些数据就可以将其作为variables在函数中使用。

(运行该代码段来查看示例)

注: 我添加了几行CSS来使用<span>作为我的浏览器上angular的红色标志。 只要确保将其切换回display:none; 在推动你的东西公开之前。

 // initialize it with jquery when DOM is ready $(document).on('ready', function() { getBootstrapBreakpoint(); }); // get bootstrap grid breakpoints var theBreakpoint = 'xs'; // bootstrap336 default = mobile first function getBootstrapBreakpoint(){ theBreakpoint = window.getComputedStyle(document.querySelector('#breakpoint-js'),':before').getPropertyValue('content').replace(/['"]+/g, ''); console.log('bootstrap grid breakpoint = ' + theBreakpoint); } 
 #breakpoint-js { /* display: none; //comment this while developping. Switch back to display:NONE before commit */ /* optional red flag layout */ position: fixed; z-index: 999; top: 0; left: 0; color: white; padding: 5px 10px; background-color: red; opacity: .7; /* end of optional red flag layout */ } #breakpoint-js:before { content: 'xs'; /* default = mobile first */ } @media screen and (min-width: 768px) { #breakpoint-js:before { content: 'sm'; } } @media screen and (min-width: 992px) { #breakpoint-js:before { content: 'md'; } } @media screen and (min-width: 1200px) { #breakpoint-js:before { content: 'lg'; } } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> <div class="container"> <span id="breakpoint-js"></span> <div class="page-header"> <h1>Bootstrap grid examples</h1> <p class="lead">Basic grid layouts to get you familiar with building within the Bootstrap grid system.</p> </div> </div> 

对于任何人使用knockout.js ,我想要一些knockout.js可观察的属性 ,告诉我何时击中断点。 我select使用Modernizr对css风格媒体查询的支持,以便数字匹配引导程序定义,并获得modernizr的兼容性优势。 我的淘汰赛模型如下:

 var viewModel = function() { // depends on jquery, Modernizr var self = this; self.widthXsOrLess = ko.observable(); self.widthSmOrLess = ko.observable(); self.widthMdOrLess = ko.observable(); var setWindowSizeVars = function() { self.widthXsOrLess(!Modernizr.mq('(min-width: 768px)')); self.widthSmOrLess(!Modernizr.mq('(min-width: 992px)')); self.widthMdOrLess(!Modernizr.mq('(min-width: 1200px)')); }; $(window).resize(setWindowSizeVars); setWindowSizeVars(); }; 

使用JavaScript检测Twitter Bootstrap 4的响应断点

我已经迁移到最新版本的Bootstrap v4.0.0-alpha.2 (现在的状态),所以创build了一个小的实用程序函数来检测使用JS的响应断点:

 /** * Detect and return the current active responsive breakpoint in Bootstrap * @returns {string} */ function getResponsiveBreakpoint() { var envs = ["xs", "sm", "md", "lg"]; var env = ""; var $el = $("<div>"); $el.appendTo($("body")); for (var i = envs.length - 1; i >= 0; i--) { env = envs[i]; $el.addClass("hidden-" + env + "-up"); if ($el.is(":hidden")) { break; // env detected } } $el.remove(); return env; } 

我认为这将是有用的,因为它很容易整合到任何项目。

这是检测它的好方法(也许有趣,但工作),你可以使用必要的元素,所以代码是明确的:

例如: css:

 @media (max-width: 768px) { #someElement { background: pink } } 

并在jQuery文档中:

 if($('#someElement').css('background') == 'pink') { doWhatYouNeed(); } 

当然CSS属性是任何。

由于引导4将很快出来,我想我会分享一个支持它(xl现在的事情)的function,并执行最小的jQuery完成工作。

 /** * Get the Bootstrap device size * @returns {string|boolean} xs|sm|md|lg|xl on success, otherwise false if Bootstrap is not working or installed */ function findBootstrapEnvironment() { var environments = ['xs', 'sm', 'md', 'lg', 'xl']; var $el = $('<span />'); $el.appendTo($('body')); for (var i = environments.length - 1; i >= 0; i--) { var env = environments[i]; $el.addClass('hidden-'+env); if ($el.is(':hidden')) { $el.remove(); return env; } } $el.remove(); return false; } 

Bootstrap 4

 setResponsiveDivs(); function setResponsiveDivs() { var data = [ {id: 'visible-xs', class: 'd-block d-sm-none'}, {id: 'visible-sm', class: 'd-none d-sm-block d-md-none'}, {id: 'visible-md', class: 'd-none d-md-block d-lg-none'}, {id: 'visible-lg', class: 'd-none d-lg-block d-xl-none'}, {id: 'visible-xl', class: 'd-none d-xl-block'} ]; for (var i = 0; i < data.length; i++) { var el = document.createElement("div"); el.setAttribute('id', data[i].id); el.setAttribute('class', data[i].class); document.getElementsByTagName('body')[0].appendChild(el); } } function isVisible(type) { return window.getComputedStyle(document.getElementById('visible-' + type), null).getPropertyValue('display') === 'block'; } // then, at some point window.onresize = function() { console.log(isVisible('xs') === true ? 'xs' : ''); console.log(isVisible('sm') === true ? 'sm' : ''); console.log(isVisible('md') === true ? 'md' : ''); console.log(isVisible('lg') === true ? 'lg' : ''); console.log(isVisible('xl') === true ? 'xl' : ''); }; 

如果您使用Knockout ,则可以使用以下自定义绑定将当前视口断点(xs,sm,md或lg)绑定到模型中的observable。 绑定…

  • visible-??包装4个divs visible-?? 在一个与ID detect-viewport的div类,如果它不存在已经添加到身体(所以你可以重复使用这个绑定,而不复制这些div)
  • 通过查询哪些div可见,将当前的视口断点设置为绑定的observable
  • 窗口resize时更新当前视口断点
 ko.bindingHandlers['viewport'] = { init: function(element, valueAccessor) { if (!document.getElementById('detect-viewport')) { let detectViewportWrapper = document.createElement('div'); detectViewportWrapper.id = 'detect-viewport'; ["xs", "sm", "md", "lg"].forEach(function(breakpoint) { let breakpointDiv = document.createElement('div'); breakpointDiv.className = 'visible-' + breakpoint; detectViewportWrapper.appendChild(breakpointDiv); }); document.body.appendChild(detectViewportWrapper); } let setCurrentBreakpoint = function() { valueAccessor()($('#detect-viewport div:visible')[0].className.substring('visible-'.length)); } $(window).resize(setCurrentBreakpoint); setCurrentBreakpoint(); } }; ko.applyBindings({ currentViewPort: ko.observable() }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <script src="bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <div data-bind="viewport: currentViewPort"></div> <div> Current viewport breakpoint: <strong data-bind="text: currentViewPort"></strong> </div> <div> (Click the <em>full page</em> link of this snippet to test the binding with different window sizes) </div>