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