Responsive Breakpoint Detection in JavaScript

By Eric Lathrop on

CSS makes up the majority of code responsible for implementing a responsive web site. Every once in a while I come across certain aspects of a responsive site that can only be implemented with JavaScript. In order to avoid repeating the screen widths (once in CSS, once in JavaScript), my coworker Martin Hofmann and I came up with a way of detecting the current CSS breakpoint from JavaScript.

First, there's a set of empty "beacon" tags somewhere on the page. I make one for each breakpoint in the CSS. The beacons are invisible because they're empty, but there's also CSS that sets them to display: none; for all of the breakpoints but one.

<div class="visible--only-sm" id="js-sm-beacon"></div>
<div class="visible--only-md" id="js-md-beacon"></div>
<div class="visible--only-lg" id="js-lg-beacon"></div>

Here's some example SCSS that only shows the beacons for the appropriate breakpoint:

.visible--only-sm {
  @media screen and (min-width: $screen-md-min) {
    display: none !important;
  }
}

.visible--only-md {
  @media screen and (max-width: $screen-sm-max) {
    display: none !important;
  }
  @media screen and (min-width: $screen-lg-min) {
    display: none !important;
  }
}

.visible--only-lg {
  @media screen and (max-width: $screen-md-max) {
    display: none !important;
  }
}

Now that we have beacons, we can detect if they're visible on the screen with JavaScript using the offsetWidth property:

const breakpoints = ["sm", "md", "lg"];

export function getBreakpoint() {
  for (var i = 0; i < breakpoints.length; i++) {
    if (isBreakpoint(breakpoints[i])) {
      return breakpoints[i];
    }
  }
  return "base";
}

function isBreakpoint(breakpoint) {
  var beacon = document.getElementById("js-" + breakpoint + "-beacon");
  if (beacon) {
    return beacon.offsetWidth > 0;
  }
  return false;
}