Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trigger events when CSS breakpoints are reached

I have a set of breakpoints and I'd like to fire an event every time one is passed. Currently, I'm using $(document).resize(function(){}) but this doesn't match up with my CSS breakpoints whether I use window, document or any other selector.

Is there any way of just detecting when a media query is passed? Here's my current code:

$( window ).resize(
    function() {
        if( $(window).width() < 500 ) {
            $(window).trigger("breakpoint-sm");
        }
        if( $(window).width() < 900 ) {
            $(window).trigger("breakpoint-md");
        }
    }
);

$(window).on(
    "breakpoint-md", function() {
        if($(window).width() < 900) {
            // this happens when below medium screen size
            alert( "breakpoint reached" );
        }
    }
);
@media screen and (max-width: 500px) {
    /* do mobile things */
}
@media screen and (max-width: 900px) {
    /* do mobile things */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

If there's an easier way to know if the breakpoint has been passed upwards or downwards, I'd be willing to hear it.

Thankyou!

like image 987
Suspirium Avatar asked Sep 12 '18 08:09

Suspirium


1 Answers

I've got a solution to your exact problem which I use myself.

Basically, you can't directly detect breakpoints using JavaScript but you can detect changes to elements caused by breakpoints. The .css-js_ref-* divs will become visible when their respective breakpoint is reached.

<div class="css-js_ref">
    <div class="css-js_ref-sm" data-bp="sm"></div>
    <div class="css-js_ref-md" data-bp="md"></div>
</div>

And you can then use JS to detect what the last visible element is:

function currentBreakpoint() { return $('.css-js_ref > *:visible').first().attr('data-bp') };

This returns the breakpoint name you put into the .css-js_ref markup, i.e. sm.

Working Example:

function currentBreakpoint() { return $('.css-js_ref > *:visible').first().attr('data-bp') };
var breakpointLength = $('.css-js_ref > *:visible').length;

$(window).on('resize', function () {

    var newBreakpointLength = $('.css-js_ref > *:visible').length;

    if (newBreakpointLength < breakpointLength) {
        breakpointLength = newBreakpointLength;
        $(window).trigger('breakpoint:up', [currentBreakpoint()]);

    }
    if (newBreakpointLength > breakpointLength) {
        breakpointLength = newBreakpointLength;
        $(window).trigger('breakpoint:down', [currentBreakpoint()]);
    }

});


$(window).on('breakpoint:down', function(event, bp){
    console.log(bp);
});
.css-js_ref * {
    display: none;
}

@media screen and (max-width: 500px) {
    .css-js_ref-sm {
        display: block;
        max-width: 500px;
    }
}
@media screen and (max-width: 900px) {
    .css-js_ref-md {
        display: block;
        max-width: 900px;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="css-js_ref">
    <div class="css-js_ref-sm" data-bp="sm"></div>
    <div class="css-js_ref-md" data-bp="md"></div>
</div>

Usage:

// bp is the breakpoint that was reached
$(window).on('breakpoint:down', function(event, bp){
    if(bp === 'md') {
        // do stuff on below medium sized devices
    }
});

$(window).on('breakpoint:up', function(event, bp){
    if(bp === 'md') {
        // do stuff on above medium sized devices
    }
});

This solution is a bit of work but extremely versatile. It also means you only have to define your breakpoints in one place which is great for DRY compliance.

like image 199
Matt Avatar answered Oct 08 '22 02:10

Matt