1
\$\begingroup\$

I'm using JavaScript to handle breakpoints in a single page, non-scrollable application. I want to do various things when changing viewports, such as fire off animations with a JavaScript animation library.

I've assigned the viewports like so:

CodePen

HTML:

<div class='box'></div>

CSS:

.box {
  width: 300px;
  height: 300px;
  background-color: red;
}

JS:

var winWidth = '';
var newWinWidth = '';
var winHeight = '';
var newWinHeight = '';

function setWidthBreakpoints(windowWidth) { //matches bootstrap's breakpoints
    if (windowWidth >= 1200) {
        newWinWidth = 'lg';
    } else if (windowWidth >= 992) {
        newWinWidth = 'md';
    } else if (windowWidth >= 768) {
        newWinWidth = 'sm';
    } else {
        newWinWidth = 'xs';
    }
}

function setHeightBreakpoints(windowHeight) {

  if (windowHeight >= 1024) { //more or less arbitrary, may add or remove
      newWinHeight = 'lg';
  } else if (windowHeight >= 480) {
      newWinHeight = 'md';
  } else {
      newWinHeight = 'sm';
  }

}

window.onresize = function () {
    'use strict';
    setWidthBreakpoints($(this).width());
    setHeightBreakpoints($(this).height());


    if (newWinWidth !== winWidth || newWinHeight !== winHeight) {
        onSizeChange();
        winWidth = newWinWidth;
        winHeight = newWinHeight;
    }
};

function onSizeChange() {
    switch(newWinWidth + '|' + newWinHeight) {
    case 'xs|sm':
        $('.box').css('background-color', 'yellow')
    case 'xs|md':
    case 'xs|lg':
        $('.box').css('background-color', 'purple')
    case 'sm|sm':
        $('.box').css('background-color', 'orange')
    case 'sm|md':
    case 'sm|lg':
        $('.box').css('background-color', 'purple')
    case 'md|sm':
        $('.box').css('background-color', 'green')
    case 'md|md':
    case 'md|lg':
        $('.box').css('background-color', 'purple')
    case 'lg|sm':
        $('.box').css('background-color', 'blue')
    case 'lg|md':
    case 'lg|lg':
        $('.box').css('background-color', 'purple')
    }
}

In the above code, we want anything above a small height to be purple. But we have to repeat ourselves to set it four different times.

I will be supporting IE9 with this application so I chose to use JS animation library GSAP for performance and fallback reasons. This is why I am handling my media query breakpoints in Javascript.

How can I build such a scheme to minimize code repetition? Is there a more elegant way to handle combined height and width breakpoints? Am I doing it wrong? I don't foresee many more height viewports being added to this application, and the width ones are tied to Bootstrap so they won't be changing at all.

\$\endgroup\$
  • \$\begingroup\$ What exactly do you mean with "breakpoints"? What code repition do you mean? There is hardly anything there. Also your code isn't runable like this, which is a requirment for codereview. Finally: This is something that may be more appropriate for CSS than JS. \$\endgroup\$ – RoToRa Mar 6 '15 at 11:20
  • \$\begingroup\$ @RoToRa I have added information in question that answers these questions. Hope this helps. \$\endgroup\$ – Conor Mar 8 '15 at 17:16
  • \$\begingroup\$ I've never heard of this referred to as "breakpoints," which usually refers to lines of code that you want to automatically pause (break) in a debugger. Perhaps a better term is in order? (I usually hear "snap point" or the like.) \$\endgroup\$ – fluffy Mar 8 '15 at 17:44
  • \$\begingroup\$ @fluffy it is a term used by Twitter's Bootstrap front end framework to refer to a set point at which viewport display changes (getbootstrap.com/css), see the section called "Media Queries" under the section called "Grid System" \$\endgroup\$ – Conor Mar 8 '15 at 17:54
  • \$\begingroup\$ @fluffy but fair point, there is some ambiguity in the question title. Unfortunately because of Bootstrap's widespread popularity the term "breakpoint" is probably now a bit too ubiquitous for us to change it to "snap point", but I've edited the title to make it a bit clearer what is meant when the term "breakpoint" is used. \$\endgroup\$ – Conor Mar 8 '15 at 18:05
1
\$\begingroup\$

Here is one way to get rid of if chaines (if that is the repition you mean):

var WIDTHS = [
    {name: 'xs', max: 768},
    {name: 'sm', max: 992},
    {name: 'md', max: 1200},
    {name: 'lg'}
];

function getRangeName(value, ranges) {
    for (var i = 0, len = ranges.length; i < len; i++) {
        var range = ranges[i];
        if (typeof range.max === "undefined" || value < range.max) {
            return range.name;
        }
    }
}

function setWidthBreakpoints(windowWidth) {
    return getRangeName(windowWidth, WIDTHS);
}
\$\endgroup\$
  • \$\begingroup\$ thank you for your answer. I will add code to make it runnable and refine the question based on your feedback \$\endgroup\$ – Conor Mar 6 '15 at 15:02
  • \$\begingroup\$ @Conor Keep in mind not to modify the code in the original question (although extending it to make it runnable should be ok). \$\endgroup\$ – RoToRa Mar 7 '15 at 7:51
  • \$\begingroup\$ I added the necessary fixes to make the code runnable and a CodePen. Will also add some more details to the question. Thanks again for your feedback. \$\endgroup\$ – Conor Mar 8 '15 at 17:10
  • \$\begingroup\$ @Conor A nice way to say thanks for feedback is to upvote \$\endgroup\$ – janos Jun 8 '15 at 18:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.