CodePen

HTML

            
              <div class="wrapper">
  <div class="grid">
    
    <div class="grid-cell main">
      <h2>A Big Piece of Garbage</h2>
      <p>You mean while I'm sleeping in it? And remember, don't do anything that affects anything, unless it turns out you were supposed to, in which case, for the love of God, don't not do it! Bender, you risked your life to save me!</p>

      <img class="responsive-image" data-mobile="https://s3.amazonaws.com/lesjames-media/breakpoint/mobile.gif" data-tablet="https://s3.amazonaws.com/lesjames-media/breakpoint/tablet.gif" data-desktop="https://s3.amazonaws.com/lesjames-media/breakpoint/desktop.gif" />

      <h3>Leela's Homeworld</h3>
      <p>No! The cat shelter's on to me. Good news, everyone! I've taught the toaster to feel love! Would you censor the Venus de Venus just because you can see her spewers? Oh, I don't have time for this.  I have to go and buy a single piece of fruit with a coupon and then return it, making people wait behind me while I complain.</p>
    </div>
    
    <div class="grid-cell sidebar">
      <h2>Kif Gets Knocked Up A Notch</h2>
      <p>Our love isn't any different from yours, except it's hotter, because I'm involved. Hey! I'm a porno-dealing monster, what do I care what you think? Oh, I always feared he might run off like this. Why, why, why didn't I break his legs? I barely knew Philip, but as a clergyman I have no problem telling his most intimate friends all about him. Throw her in the brig.</p>
    </div>
  
  </div>
</div>
            
          
!

↑ Insert the most common viewport meta tag

CSS

            
              /* grid column size variables */
$grid-column: 60px;
$grid-gutter: 20px;

/* convert pixels to ems - defaults to 16px base */
@function em($px, $base: 16px) {
  @return ($px / $base) * 1em;
}

/* Grid based on https://github.com/necolas/griddle by Nicolas Gallagher (@necolas) */
.wrapper {
  margin-left: auto; margin-right: auto;
  padding-left: em($grid-gutter);
  padding-right: em($grid-gutter);
}

.grid {
  display: block;
  padding: 0;
  margin: 0 -0.5 * em($grid-gutter);
  text-align: left;
  //letter-spacing: -0.31em;
  //word-spacing: -0.43em;
  text-rendering: optimizespeed;
}

/* Note - this class uses Compass includes */
.grid-cell {
  width: 100%;
  float: left;
  //@include inline-block;
  @include box-sizing(border-box);
  margin: 0;
  padding: 0 0.5 * em($grid-gutter);
  vertical-align: top;
  text-align: left;
  letter-spacing: normal;
  word-spacing: normal;
  text-rendering: auto;
}

img { max-width: 100%; }

/* find width of columns */
@function fixed($col) {
  @return $col * em($grid-column + $grid-gutter)
}

/* create breakpoint label and default to mobile */
body::before { content: 'mobile'; display: none; }

/* create mq to fit columns */
@mixin breakpoint($min, $label: false) {
  @media (min-width: fixed($min) + em($grid-gutter)) {
    
    /* create a fixed width centered layout */
    .wrapper {
      width: fixed($min) - em($grid-gutter);
      margin-left: auto; margin-right: auto;
    }
    
    /* create breakpoint label if defined */
    @if ($label) { body::before { content: $label; } }
    
    /* css gradient overlay to help visualize columns */
    /* Note - this class uses Compass includes */
    body::after {
      content: ''; position: fixed; top: 0; bottom: 0; pointer-events: none; left: 50%;
      width: fixed($min) + em($grid-gutter); margin-left: fixed($min) / -2 - (em($grid-gutter)/2);
      @include background(linear-gradient(left, transparent $grid-gutter, transparentize(red, .8) $grid-gutter, transparentize(red, .8) $grid-gutter + $grid-column));
      @include background-size($grid-gutter + $grid-column);
    }   
    
    /* sass content block variable */
    @content
  
  }
}

/* create 5 column fixed layout */
@include breakpoint(5) {}

/* create 8 column layout with sidebar */
@include breakpoint(8, $label: 'tablet') {
  .main { width: fixed(5); }
  .sidebar { width: fixed(3); }
}

/* create 12 column layout with sidebar */
@include breakpoint(12, $label: 'desktop') {
  .main { width: fixed(8); }
  .sidebar { width: fixed(4); }
}
            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              (function($, window, document){

    var
        // regex to strip quotes around the breakpoint label
        rxQuotes = /('|"|\s+)/g,

        // defer setting any images until the breakpoint label
        // has been calculated the first time
        breakpointReady = $.Deferred(),
        ready = breakpointReady.promise(),

        // the current serial number
        serial = 0,

        // the current breakpoint label
        breakpoint = null,

        // get breakpoint label list
        labels = (function () {
            var labels = window.getComputedStyle && window.getComputedStyle(document.body, '::after');
            if (labels) {
                labels = labels.content || null;
                if (typeof labels === 'string' || labels instanceof String) {
                    labels = labels.replace(rxQuotes, '');
                    // convert label list into an array
                    labels = labels.split(',');
                }
            }
            return labels;
        }()),

        // searches label array for current breakpoint and returns position
        searchLabels = function (stringArray, breakpoint) {
            for (var j=0; j<stringArray.length; j++) {
                if (stringArray[j].match(breakpoint)) { return j; }
            }
            return -1;
        },

        // a utility for converting arguments to an Array
        rest = function(args, nth) {
            var values = [],
                length = args.length,
                i = nth || 0;
            for ( ; i < length; i++) {
                values.push(args[i]);
            }
            return values;
        },

        // a utility for currying function arguments
        partial = function(fn) {
            return (function(fn, args) {
                return function() {
                    return fn.apply(null, args.concat(rest(arguments)));
                };
            })(fn, rest(arguments, 1));
        },

        // generate the next serial number
        nextSerial = function() {
            serial += 1;
            return serial;
        },

        // update the current breakpoint label and dispatch
        // the breakpoint event if it has changed
        updateBreakpoint = function() {

            var currentBreakpoint = breakpoint,
                style = window.getComputedStyle && window.getComputedStyle(document.body, '::before');

            if (style) {
                breakpoint = style.content || null;
                if (typeof breakpoint === 'string' || breakpoint instanceof String) {
                    breakpoint = breakpoint.replace(rxQuotes, '');
                }
            }

            // fulfill the promise or dispatch an event?
            if (breakpointReady !== null) {

                breakpointReady.resolve();
                breakpointReady = null;

            } else if (breakpoint !== currentBreakpoint) {

                $('body').trigger($.Event('breakpoint', { breakpoint: breakpoint }));

            }
        };

    // update the breakpoint on load
    $(document).ready(updateBreakpoint);

    // update the breakpoint on window resize
    $(window).bind('resize.breakpoint', updateBreakpoint);

    // define the plugin
    $.fn.breakpoint = function(options) {

        this.each(function() {

            var image = $(this),
                serial = image.data('breakpoint-serial');

            // has this not yet been registered?
            if (!serial) {
                serial = nextSerial();
                image.data('breakpoint-serial', serial);

                // be a good memory citizen
                $(document).bind('unload.breakpoint.serial' + serial, partial(function(image, serial) {

                    // unbind our closures so garbage collection can happen
                    image.unbind('breakpoint.serial' + serial);
                    $(this).unbind('unload.breakpoint.serial' + serial);
                    image = null;

                }, image, serial));
            }

            // configure the options
            options = $.extend({
                delay : 200,
                callback: null,
                prefix: '',
                fallback: null
            }, options || { });

            // remove any previous handler
            $('body').unbind('breakpoint.serial' + serial);

            // create the new handler
            $('body').bind('breakpoint.serial' + serial, (function(image, options) {

                var
                    // have we set the src at least once?
                    once = false,

                    // track our delay timeout
                    timeout = null,

                    // track our current breakpoint setting
                    currentBreakpoint = null,

                    // set the image's src
                    set = function(breakpoint) {

                        var src, position;

                        // now we've processed this image at least once
                        once = true;

                        // logically, any timeout must be finished
                        timeout = null;

                        // resolve the breakpoint
                        breakpoint = breakpoint || options.fallback;

                        // update?
                        if (breakpoint !== currentBreakpoint) {

                            // breakpoint position in the array of known breakpoints
                            position = (labels) ? searchLabels(labels, breakpoint) : null;

                            src = (function () {

                                // find source by first trying the current breakpoint
                                var src = image.attr('data-' + options.prefix + breakpoint),
                                    i = position - 1;

                                // if no match is found walk backwards through the
                                // labels array until a matching data attr is found
                                if (src === undefined) {
                                    for (i; i >= 0; i = i - 1) {
                                        src = image.attr('data-' + options.prefix + labels[i]);
                                        if (src !== undefined) {
                                            break;
                                        }
                                    }
                                }

                                return src;
                            }());

                            if (src) {
                                image.attr('src', src);
                            } else {
                                console.warn('Breakpoint could not find a source for: ' + image[0].outerHTML);
                            }

                            if (typeof options.callback === 'function') {
                                options.callback.call(image, breakpoint, src);
                            }
                            currentBreakpoint = breakpoint;
                        }
                    };

                // set the image once with the current breakpoint
                ready.done(function() {
                    set(breakpoint);
                });

                // return the event handler
                return function(evt) {

                    // cancel any existing timeout
                    if (timeout !== null) {
                        clearTimeout(timeout);
                        timeout = null;
                    }

                    // run immediately or time out?
                    if (!once || options.delay <= 0) {
                        set(evt.breakpoint);
                    } else {
                        timeout = setTimeout(partial(set, evt.breakpoint), options.delay);
                    }
                };

            })(image, options));
        });

        // now that we have some images, update the breakpoint
        // to give them a chance to set their images
        updateBreakpoint();

        return this;
    };

})(jQuery, window, document);
$('.responsive-image').breakpoint();
            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................