Load AddThis (or similar) when a media-query breakpoint is met
Often times in Responsive Design, one wants to load functionality for certain viewport widths. It could be that you want to assume that desktop users have more bandwidth and keep the load lighter for smaller viewports. It could be that you have some buttons and functionality that are hidden in the layout until a media query makes them visible. Whatever the reason, I have found that this is a great way to load content and functionality when certain conditions are met.
In CSS, we apply a "label" to the body inside of a media query.
The CSS
@media (min-width: 36em ) {
body:after {
content: 'load-addthis';
display: none;
}
}
I like to name the label after the function that I want to perform. In this way, it is very transparent what the CSS is controlling.
Now, with JS we "listen" to this label. When that label is present, we use it to fire an event. Keep in mind that these events will be evaluated every time the window is resized, so, to prevent these events from firing more than once per page refresh, we first set variable to check against.
The JS
/* onresize handler that waits until a window resize event has stopped before firing – doesn't fire extraneously */
function on_resize(c,t){ onresize=function(){ clearTimeout(t);t = setTimeout(c,100)}; return c };
/* Check these so we dont load the same things twice */
addthis_loaded = false;
/* Load content progressively. Must remember to also load them for IE 7 and 8, since they do not support media queries or the getComputedStyle function */
on_resize(function() {
/* "Watch" the content of the body:after element. Will change as media queries fire. */
mq_tag = window.getComputedStyle(document.body,':after').getPropertyValue('content');
//console.log( "media query tag=" + mq_tag );
/* Load AddThis features for larger screens */
if ( mq_tag.indexOf("load-addthis") !=-1 && addthis_loaded == false ) {
/* We could also check to see if the target div was empty: !$.trim( $('#addthis').html() ).length */
var add_this_html =
'<div class="addthis_toolbox addthis_default_style addthis_32x32_style"><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_compact"></a></div>';
$("#addthis").html(add_this_html);
$.getScript('http://s7.addthis.com/js/250/addthis_widget.js#pubid=XXX',
function(){
addthis.init(); //callback function for script loading
});
addthis_loaded = true;
//console.log( "! load-addthis has fired" );
}
})(); // the magic extra () makes this function fire on page load
The cool part is that this code – mq_tag.indexOf("load-addthis") !=-1
– basically says "if this string of text appears anywhere in the current media query label". This means that the contents of that "label" can trigger more than one event.
For example, at the first breakpoint, we do two events. At the second, we do one new event and repeat a previous one. Same with the third:
@media (max-width: 48em) {
body:after {
content: 'action1 action2';
display: none;
}
}
@media (min-width: 48em) and (max-width: 60em) {
body:after {
content: 'action2 action3';
display: none;
}
}
@media (min-width: 60em) {
body:after {
content: 'action3 action4';
display: none;
}
}
In this way, our CSS can control JS events with media queries. The viewport dimensions stay in the CSS and the events stay in the JS. Responsive designs can get a lot more responsible and lighter for varying viewports with this method.
Written by J. Hogue
Related protips
4 Responses
This is a nice practical application of Jeremy Keith's Conditional CSS - http://adactio.com/journal/5429/ it's a great technique that I use for conditionally loading images - http://www.jordanm.co.uk/post/22964442013/source-shuffling-responsive-images-based-on-media
I like your labelling spin on it for attaching the MQs to specific functionality. Nice and specific.
Yes, I should have mentioned all of the different places that I got inspiration from. Jeremy's breakthrough idea of labeling the body with a pseudo element was one of them.
Interesting that you mention images. Most, not all, browsers will not download images contained in media queries until the media query conditions are met. For background images, this is nice to know. But you are correct, for other images in markup, the browser will still download them even though their display may be set to none in the CSS.
Setting the display of the pseudo element to none prevents access of the generated content in Chrome. See Hal D's comment here: http://davidwalsh.name/pseudo-element. You can work around this by setting display to block, and then line height, font size, and height all to 0.
dlow, thanks for that tip! You answered a question I had before I asked it. I recently noticed that in Chrome these actions were not being triggered, but didn't look into it yet. Now I know why... Thanks!