Comment détecter les points d'arrêt réactifs de Twitter Bootstrap 3 à l'aide de JavaScript?


139

Actuellement , Twitter Bootstrap 3 a les points d'arrêt réactifs suivants: 768px, 992px et 1200px, représentant respectivement des appareils petits, moyens et grands.

Comment puis-je détecter ces points d'arrêt à l'aide de JavaScript?

Je souhaite écouter avec JavaScript tous les événements liés déclenchés lorsque l'écran change. Et pour pouvoir détecter si l'écran est destiné aux appareils petits, moyens ou grands.

Y a-t-il quelque chose déjà fait? Quelles sont vos suggestions?


Vous pouvez utiliser IntersectionObserver pour détecter quand une <div class="d-none d-?-block"></div>visibilité change (insérez votre point d'arrêt souhaité). Ces classes CSS sont pour Bootstrap 4 ... utilisent tout ce qui fonctionne dans Bootstrap 3. Beaucoup plus performant que d'écouter l'événement de redimensionnement de la fenêtre.
Matt Thomas

Réponses:


241

Edit: Cette bibliothèque est maintenant disponible via Bower et NPM. Voir le dépôt github pour plus de détails.

RÉPONSE MIS À JOUR:

Avertissement: je suis l'auteur.

Voici quelques choses que vous pouvez faire en utilisant la dernière version (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);

Depuis la version 2.3.0, vous n'avez pas besoin des quatre <div>éléments mentionnés ci-dessous.


RÉPONSE ORIGINALE:

Je ne pense pas que vous ayez besoin d'un énorme script ou d'une bibliothèque pour cela. C'est une tâche assez simple.

Insérez les éléments suivants juste avant </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>

Ces 4 divs vous permettent de vérifier le point d'arrêt actuellement actif. Pour une détection JS facile, utilisez la fonction suivante:

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

Maintenant, pour effectuer une certaine action uniquement sur le plus petit point d'arrêt que vous pourriez utiliser:

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

Détecter les changements une fois que le DOM est prêt est également assez simple. Tout ce dont vous avez besoin est un écouteur de redimensionnement de fenêtre léger comme celui-ci:

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

Une fois que vous en êtes équipé, vous pouvez commencer à écouter les changements et exécuter des fonctions spécifiques aux points d'arrêt comme ceci:

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

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

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

3
Ça ne marche pas pour moi. viewport.current () renvoie toujours «non reconnu». Est-ce que je fais quelque chose de mal?
starbugs

Avez-vous un violon? Edit: Serait-il possible que vous incluiez vos scripts, y compris RBT dans la section head, au lieu du body? Cela empêcherait l'ajout de div de visibilité au corps, cassant ainsi la fonctionnalité.
Maciej Gurban

@MaciejGurban Je ne peux pas le faire fonctionner aussi. J'utilise Rails 4.2. J'inclus bootstrap dans ma tête mais votre script dans le corps, mais il continue de dire non reconnu. Ok mon problème j'ai tout ajouté dans le corps. Mais est-ce vraiment nécessaire?
Dennis

Encore une fois, il est difficile de dire le problème sans un violon ou un exemple de code. Vous pouvez poser une question à ce sujet sur SO et la référencer ici, ou ouvrir un problème sur github. Avez-vous suivi l'ordre d'inclusion de toutes les pièces tel qu'il est sur CodePen ? Seule cette fonction ne fonctionne pas? Le problème pourrait-il être comme celui-ci ?
Maciej Gurban

1
Comment cela pourrait-il être utilisé avec bootstrap 4?
Calonthar

64

Si vous n'avez pas de besoins spécifiques, vous pouvez simplement le faire:

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
}

Edit: Je ne vois pas pourquoi vous devriez utiliser une autre bibliothèque js alors que vous pouvez le faire uniquement avec jQuery déjà inclus dans votre projet Bootstrap.


Merci, pouvez-vous également fournir l'auditeur pour tous les événements qui déclenchent un changement de dimension à l'écran?
Rubens Mariuzzo

Je ne pense pas qu'il y ait des événements sur le changement de dimension de l'écran. Tout ce qui concerne la dimension de l'écran (requêtes multimédias) se trouve dans la feuille de style.
mtt le

2
Je le sais, je cherche juste un comportement similaire dans JS. En fait, écoutez le changement de dimension de l'écran avec: $(window).bind('resize')... mais il y a d'autres événements liés à l'orientation de l'écran mobile qui ont un impact sur la dimension de l'écran.
Rubens Mariuzzo le

L'orientation de l'appareil est toujours une fonctionnalité expérimentale: developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent Je vous suggère d'utiliser.on('resize')
mtt

1
J'ai entendu parler de cas où cette façon de détecter l'état pose des problèmes. Il est préférable d'aller avec quelque chose qui vérifie les éléments d'aide visibles à mon humble avis - juste pour être à l'abri de tous les cas d'angle.
Manuel Arwed Schmidt

11

Avez-vous jeté un œil à Response.js? Il est conçu pour ce genre de chose. Combinez Response.band et 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
    }
});

Bibliothèque intéressante, même si elle n'a pas été conçue avec Twitter Bootstrap 3 à l'esprit. Quoi qu'il en soit, on dirait qu'il peut être facilement adapté dans TWBS3.
Rubens Mariuzzo

11

Vous pouvez utiliser la taille de la fenêtre et coder en dur les points d'arrêt. Utilisation angulaire:

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

J'aime cette réponse. Aucune autre bibliothèque (pas même jQuery) requise.
dprothero le

11

Détecter le point d'arrêt réactif de Twitter Bootstrap 4.1.x à l'aide de JavaScript

Le Bootstrap v.4.0.0 (et la dernière version Bootstrap 4.1.x ) a présenté les mises à jour les options de grille , de sorte que le vieux concept de la détection ne peut pas être appliqué directement (voir les instructions de migration ):

  • Ajout d'un nouveau smniveau de grille ci-dessous 768pxpour un contrôle plus granulaire. Nous avons maintenant xs, sm, md, lget xl;
  • xs les classes de grille ont été modifiées pour ne pas nécessiter l'infixe.

J'ai écrit la petite fonction utilitaire qui respecte un nom de classe de grille mis à jour et un nouveau niveau de grille:

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

Détecter le point d'arrêt réactif de Bootstrap v4-beta à l'aide de JavaScript

Le v4-alpha Bootstrap et Bootstrap v4 bêta ont une approche différente sur des points d' arrêt de la grille, voici donc le chemin de l' héritage d'atteindre le même:

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

Je pense que ce serait utile, car il est facile à intégrer à n'importe quel projet. Il utilise des classes d'affichage natives réactives du Bootstrap lui-même.


7

Voici ma propre solution 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

Il est préférable d' utiliser cette approche avec Response.js . Response.resize se déclenche à chaque redimensionnement de fenêtre où le croisement ne sera déclenché que si le point d'arrêt est modifié

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

Il ne devrait y avoir aucun problème avec une implémentation manuelle comme celle mentionnée par @oozic.

Voici quelques bibliothèques que vous pouvez consulter:

  • Response.js - plugin jQuery - utilise des attributs de données html et possède également une API js.
  • enquire.js - enquire.js est une bibliothèque JavaScript légère et pure pour répondre aux requêtes multimédias CSS
  • SimpleStateManager - un gestionnaire d'état javascript pour les sites Web réactifs . Il est construit pour être léger, n'a pas de dépendances.

Notez que ces bibliothèques sont conçues pour fonctionner indépendamment du bootstrap, de la fondation, etc. Vous pouvez configurer vos propres points d'arrêt et vous amuser.


3
Enquire.js semble prometteur.
Rubens Mariuzzo

4

Vous voudrez peut-être l'ajouter à votre projet d'amorçage pour vérifier visuellement le point d'arrêt actif

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

Voici le BOOTPLY


4

S'appuyant sur la réponse de Maciej Gurban (ce qui est fantastique ... si vous aimez ça, votez simplement sa réponse). Si vous créez un service à interroger, vous pouvez renvoyer le service actuellement actif avec la configuration ci-dessous. Cela pourrait remplacer entièrement d'autres bibliothèques de détection de points d'arrêt (comme enquire.js si vous insérez certains événements). Notez que j'ai ajouté un conteneur avec un ID aux éléments DOM pour accélérer la traversée du 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, mais c'est facilement 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

Pourquoi ne pas simplement utiliser jQuery pour détecter la largeur css actuelle de la classe de conteneur bootstrap?

c'est à dire..

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

Vous pouvez également utiliser $ (window) .resize () pour empêcher votre mise en page de «salir le lit» si quelqu'un redimensionne la fenêtre du navigateur.


3

Au lieu d'insérer ce qui suit plusieurs fois dans chaque page ...

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

Utilisez simplement JavaScript pour l'insérer dynamiquement dans chaque page (notez que je l'ai mis à jour pour fonctionner avec Bootstrap 3 avec .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

Je n'ai pas assez de points de réputation à commenter, mais pour ceux qui rencontrent des problèmes pour être «non reconnus» lorsqu'ils essaient d'utiliser le ResponsiveToolKit de Maciej Gurban, j'obtiens également cette erreur jusqu'à ce que je remarque que Maciej fait référence à la boîte à outils du bas de la page page dans son CodePen

J'ai essayé de faire ça et tout à coup ça a marché! Alors, utilisez le ResponsiveToolkit mais mettez vos liens en bas de page:

Je ne sais pas pourquoi cela fait une différence, mais c'est le cas.


2

Voici une autre façon de détecter la fenêtre courante sans mettre les numéros de taille de la fenêtre dans votre javascript.

Voir les extraits de code CSS et javascript ici: https://gist.github.com/steveh80/288a9a8bd4c3de16d799

Après avoir ajouté ces extraits à vos fichiers css et javascript, vous pouvez détecter la fenêtre d'affichage actuelle comme suit:

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

Si vous souhaitez détecter une plage de fenêtres, utilisez-la comme ceci

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

2

Le CSS de Bootstrap pour la .containerclasse ressemble à ça:

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

Cela signifie donc que nous pouvons compter en toute sécurité jQuery('.container').css('width')pour détecter les points d'arrêt sans les inconvénients de se fier jQuery(window).width().

Nous pouvons écrire une fonction comme celle-ci:

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

Et puis testez-le comme

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

    detectBreakpoint();
});

Cela ne fonctionnera qu'aux largeurs spécifiées; tout ce qui se trouve entre les deux échouera. Il serait peut-être préférable de: Premièrement, parseInt sur cssWidth var cssWidth = parseInt( jQuery('.container').css('width') ); Deuxièmement, utilisez des plages 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

Utilisez CSS :beforeet contentpropriété pour imprimer l'état du point d'arrêt dans le<span id="breakpoint-js"> afin que le JavaScript n'ait qu'à lire ces données pour les transformer en variable à utiliser dans votre fonction.

(exécutez l'extrait pour voir l'exemple)

REMARQUE: j'ai ajouté quelques lignes de CSS pour utiliser le <span>comme indicateur rouge dans le coin supérieur de mon navigateur. Assurez-vous simplement de le réactiver display:none;avant de publier vos contenus.

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

J'ai créé une méthode native jQuery pour la détection de la taille de l'écran Twitter Bootstrap. Voici:

// 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 comme exemple plein écran: https://jsfiddle.net/pstepniewski/7dz6ubus/embedded/result/


1

Pour toute personne intéressée par cela, j'ai écrit une détection de point d'arrêt basée sur des points d'arrêt CSS en utilisant TypeScript et Observables. il n'est pas très difficile d'en faire ES6, si vous supprimez les types. Dans mon exemple, j'utilise Sass, mais il est également facile de le supprimer.

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

Manuscrit:

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

J'espère que cela aide quelqu'un.


1

Bootstrap4 avec jQuery, solution simplifiée

<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

Je n'étais pas vraiment satisfait des réponses données, qui me paraissent trop compliquées à utiliser, j'ai donc rédigé ma propre solution. Cependant, pour le moment, cela repose sur le trait de soulignement / lodash pour fonctionner.

https://github.com/LeShrimp/GridSizeEvents

Vous pouvez l'utiliser comme ceci:

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

Cela fonctionne immédiatement pour Bootstrap 3, car les points d'arrêt sont codés en dur à 768px, 992px et 1200px. Pour les autres versions, vous pouvez facilement adapter le code.

En interne, cela utilise matchMedia () et devrait donc garantir de produire des résultats synchronisés avec Bootstrap.


1

Peut-être que cela aidera certains d'entre vous, mais il existe un plugin qui vous aide à détecter sur quel point d'arrêt Bootstrap v4 actuel vous voyez: https://www.npmjs.com/package/bs-breakpoints

Simple à utiliser (peut être utilisé avec ou sans jQuery):

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

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

1

Voici ma solution (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

Pour tous ceux qui utilisent knockout.js , je voulais des propriétés observables knockout.js qui me diraient quand les points d'arrêt sont atteints. J'ai choisi d'utiliser le support de Modernizr pour les requêtes multimédias de style css afin que les nombres correspondent aux définitions de bootstrap, et pour bénéficier des avantages de compatibilité de modernizr. Mon modèle de vue knockout est le suivant:

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

Voici un bon moyen de le détecter (peut-être drôle, mais fonctionne) et vous pouvez utiliser l'élément nécessaire pour que le code soit clair:

Exemple: css:

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

et dans le document par jQuery:

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

bien sûr, la propriété css est any.


0

Puisque bootstrap 4 sera bientôt disponible, j'ai pensé partager une fonction qui le prend en charge (xl est maintenant une chose) et effectue un jQuery minimal pour faire le travail.

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

ou minifié

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 vous utilisez Knockout , vous pouvez utiliser la liaison personnalisée suivante pour lier le point d'arrêt de la fenêtre actuelle (xs, sm, md ou lg) à une observable dans votre modèle. La reliure ...

  • enveloppe le 4 divsavec visible-??classe dans un div avec iddetect-viewport et l'ajoute au corps s'il n'existe pas déjà (vous pouvez donc réutiliser cette liaison sans dupliquer ces divs)
  • définit le point d'arrêt de la fenêtre courante sur l'observable lié en demandant laquelle des divs est visible
  • met à jour le point d'arrêt de la fenêtre actuelle lorsque la fenêtre est redimensionnée

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

Cela fait un moment depuis l'OP, mais voici ma solution pour cela en utilisant Bootstrap 3. Dans mon cas d'utilisation, je ne ciblais que les lignes, mais la même chose pourrait être appliquée au conteneur, etc.

Changez simplement .row à ce que vous voulez.

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();
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.