Detect dynamic media queries with JavaScript?

前端 未结 4 780
误落风尘
误落风尘 2021-01-13 06:16

I\'ve been searching for a lightweight, flexible, cross-browser solution for accessing CSS Media Queries in JavaScript, without the CSS breakpoints being repeated in the Jav

相关标签:
4条回答
  • 2021-01-13 06:54

    try this

    const mq = window.matchMedia( "(min-width: 500px)" );
    

    The matches property returns true or false depending on the query result, e.g.

    if (mq.matches) {
    
      // window width is at least 500px
    } else {
      // window width is less than 500px
    }
    

    You can also add an event listener which fires when a change is detected:

    // media query event handler
    if (matchMedia) {
      const mq = window.matchMedia("(min-width: 500px)");
      mq.addListener(WidthChange);
      WidthChange(mq);
    }
    
    // media query change
    function WidthChange(mq) {
      if (mq.matches) {
        // window width is at least 500px
      } else {
        // window width is less than 500px
      }
    
    }
    
    0 讨论(0)
  • 2021-01-13 07:10

    I found an hackish but easy solution :

    @media (min-width: 800px) {
    .myClass{
        transition-property: customNS-myProp;
    }
    

    this css property is just a markup to be able to know in JS if the breaking point was reached. According to the specs, transition-property can contain anything and is supported by IE (see https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property and https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident).

    Then just check in js if transition-property has the value. For instance with JQuery in TS :

    const elements: JQuery= $( ".myClass" );
            $.each( elements, function (index, element) {
                const $element = $( element );
                const transition = $element.css( "transition-property" );
                if (transition == "custNS-myProp") {
                    // handling                     ...
                }
            });
    

    Of course there is a word of warning in the wiki that the domain of css property identifiers is evolving but I guess if you prefix the value (for instance here with customNS), you can avoid clashes for good.

    In the future, when IE supports them, use custom properties instead of transition-property https://developer.mozilla.org/en-US/docs/Web/CSS/--*.

    0 讨论(0)
  • 2021-01-13 07:12

    I managed to get the breakpoint values by creating width rules for invisible elements.

    HTML:

    <div class="secret-media-breakpoints">
        <span class="xs"></span>
        <span class="tiny"></span>
        <span class="sm"></span>
        <span class="md"></span>
        <span class="lg"></span>
        <span class="xl"></span>
    </div>
    

    CSS:

    $grid-breakpoints: (
        xs:   0,
        tiny: 366px,
        sm:   576px,
        md:   768px,
        lg:   992px,
        xl:   1200px
    );
    
    .secret-media-breakpoints {
        display: none;
    
        @each $break, $value in $grid-breakpoints {
            .#{$break} {
                width: $value;
            }
        }
    }
    

    JavaScript:

    app.breakpoints = {};
    $('.secret-media-breakpoints').children().each((index, item) => {
        app.breakpoints[item.className] = $(item).css('width');
    });
    
    0 讨论(0)
  • 2021-01-13 07:13

    See this post from expert David Walsh Device State Detection with CSS Media Queries and JavaScript:

    CSS

    .state-indicator {
        position: absolute;
        top: -999em;
        left: -999em;
    }
    .state-indicator:before { content: 'desktop'; }
    
    /* small desktop */
    @media all and (max-width: 1200px) {
        .state-indicator:before { content: 'small-desktop'; }
    }
    
    /* tablet */
    @media all and (max-width: 1024px) {
        .state-indicator:before { content: 'tablet'; }
    }
    
    /* mobile phone */
    @media all and (max-width: 768px) {
        .state-indicator:before { content: 'mobile'; }
    }
    

    JS

    var state = window.getComputedStyle(
        document.querySelector('.state-indicator'), ':before'
    ).getPropertyValue('content')
    

    Also, this is a clever solution from the javascript guru Nicholas C. Zakas:

      // Test a media query.
      // Example: if (isMedia("screen and (max-width:800px)"){}
      // Copyright 2011 Nicholas C. Zakas. All rights reserved.
      // Licensed under BSD License.
      var isMedia = (function () {
    
        var div;
    
        return function (query) {
    
          //if the <div> doesn't exist, create it and make sure it's hidden
          if (!div) {
            div = document.createElement("div");
            div.id = "ncz1";
            div.style.cssText = "position:absolute;top:-1000px";
            document.body.insertBefore(div, document.body.firstChild);
          }
    
          div.innerHTML = "_<style media=\"" + query + "\"> #ncz1 { width: 1px; }</style>";
          div.removeChild(div.firstChild);
          return div.offsetWidth == 1;
        };
      })();
    
    0 讨论(0)
提交回复
热议问题