¿Cómo detectar puntos de respuesta sensibles de Twitter Bootstrap 3 usando JavaScript?


139

Actualmente , Twitter Bootstrap 3 tiene los siguientes puntos de interrupción de respuesta: 768 px, 992 px y 1200 px, que representan dispositivos pequeños, medianos y grandes, respectivamente.

¿Cómo puedo detectar estos puntos de interrupción usando JavaScript?

Me gustaría escuchar con JavaScript todos los eventos relacionados que se activen cuando cambie la pantalla. Y para poder detectar si la pantalla es para dispositivos pequeños, medianos o grandes.

¿Hay algo ya hecho? Cuales son tus sugerencias?


Puede usar IntersectionObserver para detectar cuándo <div class="d-none d-?-block"></div>cambia la visibilidad (inserte el punto de interrupción deseado). Esas clases CSS son para Bootstrap 4 ... use lo que funcione en Bootstrap 3. Mucho más rendimiento que escuchar el evento de cambio de tamaño de ventana.
Matt Thomas

Respuestas:


241

Editar: esta biblioteca ahora está disponible a través de Bower y NPM. Vea el repositorio de github para más detalles.

RESPUESTA ACTUALIZADA:

Descargo de responsabilidad: soy el autor.

Aquí hay algunas cosas que puede hacer con la última versión (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);

A partir de la versión 2.3.0, no necesita los cuatro <div>elementos mencionados a continuación.


RESPUESTA ORIGINAL:

No creo que necesites ningún gran script o biblioteca para eso. Es una tarea bastante simple.

Inserte los siguientes elementos justo antes </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>

Estos 4 divs le permiten verificar el punto de interrupción actualmente activo. Para una fácil detección de JS, use la siguiente función:

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

Ahora, para realizar una determinada acción solo en el punto de interrupción más pequeño que pueda usar:

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

La detección de cambios después de DOM listo también es bastante simple. Todo lo que necesita es un oyente de tamaño de ventana ligero como este:

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

Una vez que esté equipado con él, puede comenzar a escuchar los cambios y ejecutar funciones específicas de punto de interrupción de esta manera:

$(window).resize(function () {
    waitForFinalEvent(function(){

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

    }, 300, fullDateString.getTime())
});

3
No funciona para mi viewport.current () siempre produce 'no reconocido'. ¿Estoy haciendo algo mal?
starbugs

¿Tienes un violín? Editar: ¿Podría ser que incluya sus scripts, incluido RBT en la sección principal, en lugar del cuerpo? Eso evitaría que se agreguen divisiones de visibilidad al cuerpo, rompiendo así la funcionalidad.
Maciej Gurban

@MaciejGurban No puedo hacer que funcione también. Estoy usando Rails 4.2. Incluyo bootstrap en mi cabeza pero tu script en el cuerpo pero sigue diciendo no reconocido. Ok, mi problema, he agregado todo en el cuerpo. ¿Pero es esto realmente necesario?
Dennis

Una vez más, es difícil distinguir el problema sin un violín o un código de muestra. Puede hacer una pregunta al respecto en SO y hacer referencia aquí, o abrir un problema en github. ¿Ha seguido el orden de incluir todas las partes como está en CodePen ? ¿Solo esa función no funciona? ¿Podría ser el problema como este ?
Maciej Gurban

1
¿Cómo podría usarse esto con Bootstrap 4?
Calonthar

64

Si no tiene necesidades específicas, simplemente puede hacer esto:

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
}

Editar: No veo por qué debería usar otra biblioteca js cuando puede hacer esto solo con jQuery ya incluido en su proyecto Bootstrap.


Gracias, ¿también puede proporcionar al oyente todos los eventos que desencadenan el cambio de dimensión en la pantalla?
Rubens Mariuzzo

No creo que haya eventos en el cambio de dimensión de la pantalla. Todo lo relacionado con la dimensión de la pantalla (consultas de medios) está en la hoja de estilo.
mtt

2
Lo sé, solo estoy buscando un comportamiento similar en JS. Realmente escuche el cambio de dimensión de la pantalla con: $(window).bind('resize')... pero hay otros eventos relacionados con la orientación de la pantalla móvil que impactan la dimensión de la pantalla.
Rubens Mariuzzo

La orientación del dispositivo sigue siendo una característica experimental: developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent le sugiero que use.on('resize')
mtt

1
He oído hablar de casos en los que esta forma de detectar el estado causa problemas. Es mejor ir con algo que busque elementos auxiliares visibles en mi humilde opinión, solo para estar a salvo de cualquier caso de esquina.
Manuel Arwed Schmidt

11

¿Has echado un vistazo a Response.js? Está diseñado para este tipo de cosas. Combine Response.band y 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
    }
});

Biblioteca interesante, aunque no fue diseñada teniendo en cuenta Twitter Bootstrap 3. De todos modos, parece que se puede adaptar fácilmente a TWBS3.
Rubens Mariuzzo

11

Puede usar el tamaño de la ventana y codificar los puntos de interrupción. Usando 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';
                }
            }
        };
    });

Me gusta esta respuesta No se requieren otras bibliotecas (ni siquiera jQuery).
dprothero

11

Detecta el punto de respuesta sensible de Twitter Bootstrap 4.1.x usando JavaScript

El v.4.0.0 Bootstrap (y la última versión de Bootstrap 4.1.x ) introdujeron los actualizados opciones de cuadrícula , por lo que el viejo concepto de detección no puede directamente aplicarse (ver las instrucciones de migración ):

  • Se agregó un nuevo smnivel de cuadrícula a continuación 768pxpara un control más granular. Ahora tenemos xs, sm, md, lg, y xl;
  • xs Las clases de cuadrícula se han modificado para no requerir el infijo.

Escribí la pequeña función de utilidad que respeta los nombres de clase de cuadrícula actualizados y un nuevo nivel de cuadrícula:

/**
 * Detect the current active responsive breakpoint in Bootstrap
 * @returns {string}
 * @author farside {@link https://stackoverflow.com/users/4354249/farside}
 */
function getResponsiveBreakpoint() {
    var envs = {xs:"d-none", sm:"d-sm-none", md:"d-md-none", lg:"d-lg-none", xl:"d-xl-none"};
    var env = "";

    var $el = $("<div>");
    $el.appendTo($("body"));

    for (var i = Object.keys(envs).length - 1; i >= 0; i--) {
        env = Object.keys(envs)[i];
        $el.addClass(envs[env]);
        if ($el.is(":hidden")) {
            break; // env detected
        }
    }
    $el.remove();
    return env;
};

Detecta el punto de respuesta sensible de Bootstrap v4-beta usando JavaScript

El Bootstrap v4-alfa y Bootstrap v4-beta tenían enfoque diferente en los puntos de interrupción de la red, así que aquí tiene la forma legado de la consecución de la misma:

/**
 * Detect and return the current active responsive breakpoint in Bootstrap
 * @returns {string}
 * @author farside {@link https://stackoverflow.com/users/4354249/farside}
 */
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("d-" + env + "-none");;
        if ($el.is(":hidden")) {
            break; // env detected
        }
    }
    $el.remove();
    return env;
}

Creo que sería útil, ya que es fácil de integrar en cualquier proyecto. Utiliza clases de visualización receptivas nativas de Bootstrap.


7

Aquí mi propia solución simple:

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

5

Usar este enfoque con Response.js es mejor. Los disparadores Response.resize en cada ventana cambian el tamaño donde el crossover solo se activará si se cambia el punto de interrupción

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

4

No debería haber ningún problema con alguna implementación manual como la mencionada por @oozic.

Aquí hay un par de librerías a las que puedes echar un vistazo:

  • Response.js - plugin jQuery - utiliza atributos de datos html y también tiene una api js.
  • enquire.js - enquire.js es una biblioteca de JavaScript ligera y pura para responder a consultas de medios CSS
  • SimpleStateManager - es un administrador de estado de javascript para sitios web receptivos. Está construido para ser ligero, no tiene dependencias.

Tenga en cuenta que estas bibliotecas están diseñadas para funcionar independientemente de bootstrap, fundación, etc. Puede configurar sus propios puntos de interrupción y divertirse.


3
Enquire.js parece prometedor.
Rubens Mariuzzo

4

Es posible que desee agregar esto a su proyecto de arranque para verificar visualmente el punto de interrupción activo

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

Aquí está el botín


4

Sobre la base de la respuesta de Maciej Gurban (lo cual es fantástico ... si te gusta esto, solo vota su respuesta). Si está creando un servicio para consultar, puede devolver el servicio actualmente activo con la configuración a continuación. Esto podría reemplazar otras bibliotecas de detección de puntos de interrupción por completo (como enquire.js si incluye algunos eventos). Tenga en cuenta que he agregado un contenedor con una ID a los elementos DOM para acelerar el recorrido 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, pero esto es fácilmente convertible)

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


3

¿Por qué no simplemente usar jQuery para detectar el ancho actual de CSS de la clase de contenedor bootstrap?

es decir..

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

También puede usar $ (window) .resize () para evitar que su diseño "ensucie la cama" si alguien cambia el tamaño de la ventana del navegador.


3

En lugar de insertar el siguiente muchas veces en cada página ...

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

Simplemente use JavaScript para insertarlo dinámicamente en cada página (tenga en cuenta que lo he actualizado para que funcione con Bootstrap 3 con .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");
}

2

No tengo suficientes puntos de reputación para comentar, pero para aquellos que tienen problemas para ser "no reconocidos" cuando intentan usar ResponsiveToolKit de Maciej Gurban, también recibí ese error hasta que noté que Maciej realmente hace referencia al kit de herramientas desde la parte inferior del página en su CodePen

¡Intenté hacer eso y de repente funcionó! Entonces, use ResponsiveToolkit pero coloque sus enlaces en la parte inferior de la página:

No sé por qué hace la diferencia, pero lo hace.


2

Aquí hay otra forma de detectar la ventana gráfica actual sin poner los números de tamaño de ventana gráfica en su javascript.

Vea fragmentos de CSS y JavaScript aquí: https://gist.github.com/steveh80/288a9a8bd4c3de16d799

Después de agregar esos fragmentos a sus archivos CSS y JavaScript, puede detectar la ventana gráfica actual de esta manera:

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

Si desea detectar un rango de ventana gráfica, utilícelo así

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

2

El CSS de Bootstrap para la .containerclase se ve así:

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

Por lo tanto, esto significa que podemos confiar con seguridad jQuery('.container').css('width')para detectar puntos de interrupción sin los inconvenientes de confiar en ellos jQuery(window).width().

Podemos escribir una función como esta:

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

Y luego pruébalo como

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

    detectBreakpoint();
});

Esto solo funcionará en los anchos especificados; cualquier cosa en el medio fallará. Puede ser mejor: Primero, analizar en cssWidth var cssWidth = parseInt( jQuery('.container').css('width') ); Segundo, usar rangos if ( cssWidth < 768) { return 'xs'; } else if (cssWidth >= 768 && cssWidth <= 992) { return 'sm'; } else if (cssWidth > 992 && cssWidth <= 1200) { return 'md'; } else { return 'lg'; }
kakoma

2

Use CSS :beforey contentpropiedad para imprimir el estado del punto de interrupción en<span id="breakpoint-js"> modo que el JavaScript solo tiene que leer estos datos para convertirlo en una variable para usar dentro de su función.

(ejecuta el fragmento para ver el ejemplo)

NOTA: Agregué algunas líneas de CSS para usar <span>como una bandera roja en la esquina superior de mi navegador. Solo asegúrate de volver a cambiarlo display:none;antes de hacer públicas tus cosas.

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


1

Hice un método jQuery nativo para la detección del tamaño de pantalla de Twitter Bootstrap. Aquí está:

// 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 como ejemplo de pantalla completa: https://jsfiddle.net/pstepniewski/7dz6ubus/embedded/result/


1

Para cualquier persona interesada en esto, escribí una detección de punto de interrupción basada en puntos de interrupción CSS utilizando TypeScript y Observables. No es muy difícil hacer ES6 con él, si elimina los tipos. En mi ejemplo, uso Sass, pero también es fácil de eliminar.

Aquí está mi JSFiddle: https://jsfiddle.net/StefanJelner/dorj184g/

HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.7/Rx.min.js"></script>
<div id="result"></div>

SCSS:

body::before {
  content: 'xs';
  display: none;

  @media screen and (min-width: 480px) {
    content: 's';
  }

  @media screen and (min-width: 768px) {
    content: 'm';
  }

  @media screen and (min-width: 1024px) {
    content: 'l';
  }

  @media screen and (min-width: 1280px) {
    content: 'xl';
  }
}

Mecanografiado:

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';

class BreakpointChangeService {
    private breakpointChange$: BehaviorSubject<string>;

    constructor(): BehaviorSubject<string> {
        // initialize BehaviorSubject with the current content of the ::before pseudo element
        this.breakpointChange$ = new Rx.BehaviorSubject(this.getBreakpoint());

        // observe the window resize event, throttle it and combine it with the BehaviorSubject
        Rx.Observable
            .fromEvent(window, 'resize')
            .throttleTime(0, Rx.Scheduler.animationFrame)
            .withLatestFrom(this.breakpointChange$)
            .subscribe(this.update.bind(this))
        ;

        return this.breakpointChange$;
    }

    // method to get the content of the ::before pseudo element
    private getBreakpoint(): string {
        // see https://www.lullabot.com/articles/importing-css-breakpoints-into-javascript
        return window.getComputedStyle(document.body, ':before').getPropertyValue('content').replace(/[\"\']/g, '');
    }

    private update(_, recent): void {
        var current = this.getBreakpoint();
        if(recent !== current) { this.breakpointChange$.next(current); }
    }
}

// if the breakpoint changes, react on it
var $result = document.getElementById('result');
new BreakpointChangeService().subscribe(breakpoint => {
    $result.innerHTML = Date.now()+': '+breakpoint;
});

Espero que esto ayude a alguien.


1

Bootstrap4 con jQuery, solución simplificada

<div class="device-sm d-sm-none"></div>
<div class="device-md d-md-none"></div>
<div class="device-lg d-lg-none"></div>
<div class="device-xl d-xl-none"></div>
<script>
var size = $('.device-xl').is(':hidden') ? 'xl' : ($('.device-lg').is(':hidden') ? 'lg'
    : ($('.device-md').is(':hidden') ? 'md': ($('.device-sm').is(':hidden') ? 'sm' : 'xs')));
alert(size);
</script>

1

No estaba realmente satisfecho con las respuestas dadas, que me parecen demasiado complicadas de usar, así que escribí mi propia solución. Sin embargo, por el momento esto depende del subrayado / lodash para funcionar.

https://github.com/LeShrimp/GridSizeEvents

Puedes usarlo así:

GridSizeEvents.addListener(function (newSize, oldSize) {
    // Will output eg. "xs -> sm"
    console.log(oldSize + ' -> ' + newSize);
});

Esto funciona de forma predeterminada para Bootstrap 3, ya que los puntos de interrupción están codificados en 768px, 992px y 1200px. Para otras versiones, puede adaptar fácilmente el código.

Internamente, utiliza matchMedia () y, por lo tanto, debe garantizar la producción de resultados que estén sincronizados con Bootstrap.


1

Tal vez ayude a algunos de ustedes, pero hay un complemento que lo ayuda a detectar en qué punto de interrupción actual de Bootstrap v4 se encuentra: https://www.npmjs.com/package/bs-breakpoints

Fácil de usar (se puede usar con o sin jQuery):

$(document).ready(function() {
  bsBreakpoints.init()
  console.warn(bsBreakpoint.getCurrentBreakpoint())

  $(window).on('new.bs.breakpoint', function (event) {
    console.warn(event.breakpoint)
  })
})

1

Aquí está mi solución (Bootstrap 4):

<div class="alert alert-warning row">
    <div class="col">
        Bootstrap breakpoint is
    </div>
    <div class="col">
        <div class="d-block d-sm-none">
            XS
        </div>
        <div class="d-none d-sm-block d-md-none">
            SM
        </div>
        <div class="d-none d-md-block d-lg-none">
            MD
        </div>
        <div class="d-none d-lg-block d-xl-none">
            MD
        </div>
        <div class="d-none d-xl-block">
            MD
        </div>
    </div>
</div>

0

Para cualquiera que use knockout.js , quería algunas propiedades observables de knockout.js que me indicaran cuándo se alcanzan los puntos de interrupción. Opté por utilizar el soporte de Modernizr para consultas de medios de estilo CSS para que los números coincidieran con las definiciones de arranque y para obtener los beneficios de compatibilidad de modernizr. Mi modelo de vista eliminatoria es el siguiente:

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

0

Aquí hay una buena forma de detectarlo (quizás divertido, pero funciona) y puede usar el elemento necesario para que el código sea claro:

Ejemplo: css:

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

y en el documento de jQuery:

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

por supuesto, la propiedad css es cualquiera.


0

Dado que Bootstrap 4 saldrá pronto, pensé que compartiría una función que lo soporte (xl ahora es una cosa) y realiza jQuery mínimo para hacer el trabajo.

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

0

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

o minificado

function setResponsiveDivs(){for(var e=[{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"}],s=0;s<e.length;s++){var l=document.createElement("div");l.setAttribute("id",e[s].id),l.setAttribute("class",e[s]["class"]),document.getElementsByTagName("body")[0].appendChild(l)}}function isVisible(e){return"block"===window.getComputedStyle(document.getElementById("visible-"+e),null).getPropertyValue("display")}setResponsiveDivs();


0

Si usa Knockout , podría usar el siguiente enlace personalizado para vincular el punto de interrupción de la ventana gráfica actual (xs, sm, md o lg) a un observable en su modelo. La Unión...

  • envuelve el 4 divscon visible-??clase en un div con id detect-viewporty lo agrega al cuerpo si aún no existe (para que pueda reutilizar este enlace sin duplicar estos divs)
  • establece el punto de interrupción de la vista actual en el límite observable al consultar cuál de los divs es visible
  • actualiza el punto de interrupción de la ventana gráfica actual cuando se cambia el tamaño de la ventana

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="https://maxcdn.bootstrapcdn.com/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>


0

Ha pasado un tiempo desde el OP, pero aquí está mi solución para esto usando Bootstrap 3. En mi caso de uso, solo apuntaba a filas, pero lo mismo podría aplicarse al contenedor, etc.

Solo cambia .row a lo que quieras.

jQuery(document).ready(function ($) {

    var alterClass = function () {

        var ww = document.body.clientWidth;

        if (ww < 768) {

            $('.row').addClass('is-xs').removeClass('is-sm').removeClass('is-lg').removeClass('is-md');

        } else if (ww >= 768 && ww < 992) {

            $('.row').addClass('is-sm').removeClass('is-xs').removeClass('is-lg').removeClass('is-md');

        } else if (ww >= 992 && ww < 1200) {

            $('.row').addClass('is-md').removeClass('is-xs').removeClass('is-lg').removeClass('is-sm');

        } else if (ww >= 1200) {

            $('.row').addClass('is-lg').removeClass('is-md').removeClass('is-sm').removeClass('is-xs');

        };
    };

    // Make Changes when the window is resized
    $(window).resize(function () {
        alterClass();
    });

    // Fire when the page first loads
    alterClass();
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.