Jak wykryć responsywne punkty przerwania Twitter Bootstrap 3 za pomocą JavaScript?

139

Obecnie Twitter Bootstrap 3 ma następujące responsywne punkty przerwania: 768px, 992px i 1200px, reprezentujące odpowiednio małe, średnie i duże urządzenia.

Jak mogę wykryć te punkty przerwania za pomocą JavaScript?

Chciałbym nasłuchiwać z JavaScriptem wszystkich powiązanych zdarzeń wywoływanych po zmianie ekranu. I móc wykryć, czy ekran jest przeznaczony dla małych, średnich czy dużych urządzeń.

Czy coś już zostało zrobione? Jakie masz sugestie?

Rubens Mariuzzo
źródło
Możesz użyć IntersectionObserver, aby wykryć <div class="d-none d-?-block"></div>zmianę widoczności (wstaw żądany punkt przerwania). Te klasy CSS są przeznaczone dla Bootstrap 4 ... używają wszystkiego, co działa w Bootstrap 3. O wiele bardziej wydajne niż nasłuchiwanie zdarzenia zmiany rozmiaru okna.
Matt Thomas

Odpowiedzi:

241

Edycja: ta biblioteka jest teraz dostępna za pośrednictwem Bower i NPM. Zobacz repozytorium github, aby uzyskać szczegółowe informacje.

ZAKTUALIZOWANA ODPOWIEDŹ:

Zastrzeżenie: jestem autorem.

Oto kilka rzeczy, które możesz zrobić, korzystając z najnowszej wersji (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);

Od wersji 2.3.0 nie potrzebujesz czterech <div>elementów wymienionych poniżej.


ORYGINALNA ODPOWIEDŹ:

Myślę, że nie potrzebujesz do tego żadnego dużego skryptu ani biblioteki. To dość proste zadanie.

Wstaw następujące elementy tuż przed </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>

Te 4 elementy div pozwalają sprawdzić aktualnie aktywny punkt przerwania. Aby łatwo wykryć JS, użyj następującej funkcji:

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

Teraz, aby wykonać określoną akcję tylko na najmniejszym punkcie przerwania, którego możesz użyć:

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

Wykrywanie zmian po zakończeniu DOM jest również dość proste. Wszystko, czego potrzebujesz, to lekki odbiornik zmiany rozmiaru okna, taki jak ten:

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

Po wyposażeniu możesz zacząć nasłuchiwać zmian i wykonywać funkcje specyficzne dla punktu przerwania, takie jak:

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

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

    }, 300, fullDateString.getTime())
});
Maciej Gurban
źródło
3
Nie działa na mnie. viewport.current () zawsze zwraca „nierozpoznany”. czy robię coś źle?
starbugs
Masz skrzypce? Edycja: Czy to możliwe, że umieszczasz swoje skrypty, w tym RBT w sekcji head, zamiast ciała? Zapobiegałoby to dodawaniu elementów div visibility do body, co z kolei łamałoby funkcjonalność.
Maciej Gurban
@MaciejGurban też nie mogę zmusić go do pracy. Używam Rails 4.2. Włączam bootstrap w mojej głowie, ale twój skrypt w treści, ale ciągle mówi nierozpoznany. Ok mój problem dodałem wszystko w ciele. Ale czy to naprawdę potrzebne?
Dennis
Po raz kolejny trudno jest określić problem bez użycia skrzypiec lub przykładowego kodu. Możesz zadać pytanie na ten temat na SO i odnieść się do niego tutaj lub otworzyć problem na githubie. Czy postępowałeś zgodnie z kolejnością dołączania wszystkich części tak, jak jest na CodePen ? Czy tylko ta funkcja nie działa? Czy problem mógł wyglądać tak ?
Maciej Gurban
1
Jak można tego użyć z bootstrapem 4?
Calonthar
64

Jeśli nie masz konkretnych potrzeb, możesz to zrobić:

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
}

Edycja: Nie rozumiem, dlaczego powinieneś używać innej biblioteki js, skoro możesz to zrobić tylko z jQuery już zawartym w twoim projekcie Bootstrap.

mtt
źródło
Dzięki, czy możesz również zapewnić odbiornik wszystkich zdarzeń, które powodują zmianę wymiarów ekranu?
Rubens Mariuzzo
Nie wydaje mi się, żeby na ekranie zmieniły się wymiary. Wszystko, co dotyczy wymiarów ekranu (zapytania o media), znajduje się w arkuszu stylów.
mtt
2
Wiem o tym, po prostu szukam podobnego zachowania w JS. Właściwie słuchaj zmiany rozmiaru ekranu za pomocą: $(window).bind('resize')... ale są też inne zdarzenia związane z orientacją ekranu mobilnego, które mają wpływ na rozmiar ekranu.
Rubens Mariuzzo
Orientacja urządzenia jest nadal funkcją eksperymentalną: developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent Proponuję użyć.on('resize')
mtt
1
Słyszałem o przypadkach, w których ten sposób wykrywania stanu powoduje problemy. Lepiej jest iść z czymś sprawdzającym, czy nie ma widocznych elementów pomocniczych imho - żeby być bezpiecznym przed przypadkami narożnymi.
Manuel Arwed Schmidt
11

Czy spojrzałeś na Response.js? Został zaprojektowany do tego rodzaju rzeczy. Połącz Response.band i 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
    }
});
Mousius
źródło
Ciekawa biblioteka, chociaż nie została zaprojektowana z myślą o Twitter Bootstrap 3. W każdym razie wygląda na to, że można go łatwo zaadaptować do TWBS3.
Rubens Mariuzzo
11

Możesz użyć rozmiaru okna i na stałe zakodować punkty przerwania. Korzystanie z 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';
                }
            }
        };
    });
srlm
źródło
Podoba mi się ta odpowiedź. Żadne inne biblioteki (nawet jQuery) nie są wymagane.
dprothero
11

Wykryj responsywny punkt przerwania Twitter Bootstrap 4.1.x przy użyciu JavaScript

Bootstrap v.4.0.0 (i najnowsza wersja Bootstrap 4.1.x ) wprowadziła aktualizowane opcji sieciowych , tak stary koncept na detekcji nie mogą być stosowane bezpośrednio (patrz instrukcje migracji ):

  • Dodano nowy smpoziom siatki poniżej, 768pxaby uzyskać bardziej szczegółową kontrolę. Mamy teraz xs, sm, md, lg, i xl;
  • xs klasy grid zostały zmodyfikowane, aby nie wymagały wrostka.

Napisałem małą funkcję użytkową, która szanuje zaktualizowane nazwy klas siatki i nową warstwę siatki:

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

Wykryj responsywny punkt przerwania Bootstrap v4-beta za pomocą JavaScript

Bootstrap v4-alfa i Bootstrap v4-beta miał inne podejście na pułapki siatki, więc oto sposób dziedzictwo osiągnięcia takie same:

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

Myślę, że byłoby to przydatne, ponieważ łatwo jest zintegrować go z dowolnym projektem. Wykorzystuje natywne, responsywne klasy wyświetlania samego Bootstrap.

Daleko z boku
źródło
7

Oto moje własne proste rozwiązanie:

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'));
}
hckr
źródło
5

Korzystanie z tego podejścia w przypadku Response.js jest lepsze. Response.resize wyzwala przy każdej zmianie rozmiaru okna, gdzie crossover będzie wyzwalany tylko w przypadku zmiany punktu przerwania

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');
});
berkayunal
źródło
4

Nie powinno być problemu z ręczną implementacją, taką jak ta wspomniana przez @oozic.

Oto kilka bibliotek, którym możesz się przyjrzeć:

  • Response.js - wtyczka jQuery - wykorzystuje atrybuty danych html, a także ma js api.
  • enquire.js - enquire.js to lekka, czysta biblioteka JavaScript do odpowiadania na zapytania o media CSS
  • SimpleStateManager - menedżer stanu javascript dla responsywnych stron internetowych. Jest zbudowany tak, aby był lekki, nie ma żadnych zależności.

Zauważ, że te biblioteki są zaprojektowane tak, aby działały niezależnie od bootstrap, Foundation, itp. Możesz skonfigurować własne punkty przerwania i dobrze się bawić.

Matias
źródło
3
Enquire.js wygląda obiecująco.
Rubens Mariuzzo
4

Możesz chcieć dodać to do swojego projektu bootstrap, aby wizualnie sprawdzić aktywny punkt przerwania

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

Oto BOOTPLY

effe
źródło
4

Opierając się na odpowiedzi Macieja Gurbana (co jest fantastyczne ... jeśli ci się to podoba, po prostu zagłosuj na jego odpowiedź). Jeśli tworzysz usługę do wysyłania zapytań, możesz zwrócić aktualnie aktywną usługę za pomocą poniższej konfiguracji. Może to całkowicie zastąpić inne biblioteki do wykrywania punktów przerwania (np. Enquire.js, jeśli umieścisz niektóre zdarzenia). Zauważ, że dodałem kontener z identyfikatorem do elementów DOM, aby przyspieszyć przechodzenie do 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, ale można to łatwo zamienić)

# 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;
    }
  };
});
Złóg
źródło
3

Dlaczego po prostu nie użyć jQuery do wykrycia bieżącej szerokości css klasy kontenera ładowania początkowego?

to znaczy..

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

Możesz także użyć $ (window) .resize (), aby zapobiec „zabrudzeniu łóżka” przez układ, jeśli ktoś zmieni rozmiar okna przeglądarki.

Mark Williams
źródło
3

Zamiast wielokrotnie wstawiać poniższy kod na każdej stronie ...

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

Po prostu użyj JavaScript, aby dynamicznie wstawić go do każdej strony (zauważ, że zaktualizowałem go do pracy z Bootstrap 3 z .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");
}
Phillip Quinlan
źródło
2

Nie mam wystarczającej liczby punktów reputacji do skomentowania, ale dla tych, którzy mają problemy z „nierozpoznaniem”, gdy próbują użyć ResponsiveToolKit Macieja Gurbana, również otrzymywałem ten błąd, dopóki nie zauważyłem, że Maciej faktycznie odwołuje się do zestawu narzędzi od dołu strony w swoim CodePen

Próbowałem to zrobić i nagle zadziałało! Więc użyj ResponsiveToolkit, ale umieść swoje linki u dołu strony:

Nie wiem, dlaczego to ma znaczenie, ale tak jest.

Michael Ackary
źródło
2

Oto inny sposób na wykrycie bieżącego obszaru roboczego bez umieszczania numerów rozmiaru widocznego obszaru w skrypcie javascript.

Zobacz fragmenty css i javascript tutaj: https://gist.github.com/steveh80/288a9a8bd4c3de16d799

Po dodaniu tych fragmentów do plików css i javascript możesz wykryć bieżący widok w następujący sposób:

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

Jeśli chcesz wykryć zakres rzutni, użyj go w ten sposób

viewport.isEqualOrGreaterThan('sm') // returns true for sm, md and lg
steveh80
źródło
2

CSS Bootstrapa dla .containerklasy wygląda następująco:

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

Oznacza to, że możemy bezpiecznie polegać na jQuery('.container').css('width')wykrywaniu punktów przerwania bez wad polegających na poleganiu na nich jQuery(window).width().

Możemy napisać taką funkcję:

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

A potem przetestuj to jak

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

    detectBreakpoint();
});
FlavioEscobar
źródło
Będzie to działać tylko przy określonych szerokościach; wszystko pomiędzy zawiedzie. Najlepiej byłoby: Po pierwsze, przeanalizować cssWidth var cssWidth = parseInt( jQuery('.container').css('width') ); Po drugie, użyć zakresów 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

Użyj CSS :beforei contentwłaściwości, aby wydrukować stan punktu przerwania w pliku<span id="breakpoint-js"> formacie, więc JavaScript musi po prostu odczytać te dane, aby zmienić je jako zmienną do użycia w funkcji.

(uruchom fragment, aby zobaczyć przykład)

UWAGA: dodałem kilka linii CSS, aby użyć <span>jako czerwonej flagi w górnym rogu mojej przeglądarki. Po prostu pamiętaj, aby przełączyć go z powrotem na, display:none;zanim udostępnisz swoje rzeczy publicznie.

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

MartinDubeNet
źródło
1

Stworzyłem natywną metodę jQuery do wykrywania rozmiaru ekranu Twitter Bootstrap. Tutaj jest:

// 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 jako przykład pełnoekranowy: https://jsfiddle.net/pstepniewski/7dz6ubus/embedded/result/

Piotr Stępniewski
źródło
1

Dla wszystkich zainteresowanych tym, napisałem wykrywanie punktów przerwania na podstawie punktów przerwania CSS przy użyciu TypeScript i Observables. nie jest trudno zrobić z tego ES6, jeśli usuniesz typy. W moim przykładzie używam Sass, ale łatwo to usunąć.

Oto mój 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';
  }
}

Maszynopis:

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

Mam nadzieję, że to komuś pomoże.

Stefan Jelner
źródło
1

Bootstrap4 z jQuery, uproszczone rozwiązanie

<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>
Alex R.
źródło
1

Nie byłem zadowolony z udzielonych odpowiedzi, które wydają mi się zbyt skomplikowane w użyciu, więc napisałem własne rozwiązanie. Jednak na razie polega to na podkreśleniu / lodash do pracy.

https://github.com/LeShrimp/GridSizeEvents

Możesz go używać w ten sposób:

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

Działa to po wyjęciu z pudełka dla Bootstrap 3, ponieważ punkty przerwania są na stałe zakodowane na 768px, 992px i 1200px. W przypadku innych wersji można łatwo dostosować kod.

Wewnętrznie to używa matchMedia () i dlatego powinno zagwarantować, że wyniki będą zsynchronizowane z Bootstrap.

MaximeW
źródło
1

Może niektórym z was to pomoże, ale jest wtyczka, która pomoże wam wykryć, na którym aktualnym punkcie przerwania Bootstrap v4 się znajdujecie: https://www.npmjs.com/package/bs-breakpoints

Prosty w użyciu (może być używany z jQuery lub bez):

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

  $(window).on('new.bs.breakpoint', function (event) {
    console.warn(event.breakpoint)
  })
})
Johann-S
źródło
1

Oto moje rozwiązanie (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>
Antonio Petricca
źródło
0

Dla każdego, kto używa knockout.js , chciałem mieć kilka obserwowalnych właściwości knockout.js , które powie mi, kiedy zostaną osiągnięte punkty przerwania. Zdecydowałem się skorzystać z obsługi Modernizr dla zapytań o media w stylu css, aby liczby pasowały do ​​definicji bootstrap i aby uzyskać korzyści ze zgodności modernizr. Mój model widoku knockout jest następujący:

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();
};
rogersillito
źródło
0

Oto dobry sposób na wykrycie tego (może zabawny, ale działa) i możesz użyć niezbędnego elementu, aby kod był przejrzysty:

Przykład: css:

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

oraz w dokumencie jQuery:

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

oczywiście właściwość css jest dowolna.

Świeżu
źródło
0

Ponieważ bootstrap 4 wkrótce wyjdzie, pomyślałem, że udostępnię funkcję, która go obsługuje (xl jest teraz rzeczą) i wykonuje minimalne jQuery, aby wykonać zadanie.

/**
 * 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;
}
carcus88
źródło
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' : '');
};

lub zminimalizowane

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

Patrioticcow
źródło
0

Jeśli używasz Knockout , możesz użyć następującego niestandardowego powiązania, aby powiązać bieżący punkt przerwania rzutni (xs, sm, md lub lg) z obserwowalnym w modelu. Wiązanie...

  • owija 4 divsz visible-??klasy w div o identyfikatorzedetect-viewport i dodaje go do treści, jeśli jeszcze nie istnieje (więc możesz ponownie użyć tego powiązania bez duplikowania tych elementów div)
  • ustawia bieżący punkt przerwania rzutni na powiązany obserwowalny, pytając, który z elementów div jest widoczny
  • aktualizuje bieżący punkt przerwania rzutni po zmianie rozmiaru okna

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>

Philip Bijker
źródło
0

Minęło trochę czasu od OP, ale oto moje rozwiązanie tego problemu za pomocą Bootstrap 3. W moim przypadku celowałem tylko w wiersze, ale to samo można zastosować do kontenera itp.

Po prostu zmień. Rzuć na cokolwiek chcesz.

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();
});
Jason
źródło