Last active
May 15, 2017 03:32
-
-
Save stewartknapman/52b174aa62a6fb46c70a to your computer and use it in GitHub Desktop.
Media queries but for elements rather than the window.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Pollyfill for window.getComputedStyle() | |
*/ | |
if (!window.getComputedStyle) { | |
window.getComputedStyle = function(el, pseudo) { | |
this.el = el; | |
this.getPropertyValue = function(prop) { | |
var re = /(\-([a-z]){1})/g; | |
if (prop == 'float') prop = 'styleFloat'; | |
if (re.test(prop)) { | |
prop = prop.replace(re, function () { | |
return arguments[2].toUpperCase(); | |
}); | |
} | |
return el.currentStyle[prop] ? el.currentStyle[prop] : null; | |
}; | |
return this; | |
}; | |
} | |
/* | |
Utilities | |
*/ | |
var u = { | |
ready: function (callback, ctx) { | |
if (typeof callback !== 'function') return; | |
if (document.readyState !== "loading") { | |
callback.apply(ctx); | |
} else { | |
document.addEventListener("DOMContentLoaded", function () { | |
callback.apply(ctx); | |
}); | |
} | |
}, | |
each: function (arr, callback, ctx) { | |
for (var i = 0; i < arr.length; i++) { | |
ctx = ctx || arr[i]; | |
callback.apply(ctx, [arr[i], i]); | |
} | |
}, | |
debounce: function (callback, wait) { | |
var timeout, timestamp, args; | |
wait = wait || 100; | |
var later = function() { | |
var last = new Date().getTime() - timestamp; | |
if (last < wait && last >= 0) { | |
timeout = setTimeout(later, wait - last); | |
} else { | |
timeout = null; | |
callback.apply(ctx, args); | |
} | |
}; | |
return function () { | |
ctx = this; | |
args = arguments; | |
timestamp = new Date().getTime(); | |
if (!timeout) timeout = setTimeout(later, wait); | |
}; | |
} | |
}; | |
/* | |
Element Queries Main | |
*/ | |
var eqElementSelector = '[data-element-query]'; | |
var ElementQuery = function (eqEle, html) { | |
this.eqEle = eqEle; | |
this.html = html; | |
this.queries = this.getQueries(eqEle.dataset.elementQuery); | |
this.addEventListeners(); | |
this.calcElementQueries(); | |
}; | |
ElementQuery.prototype.addEventListeners = function () { | |
var _this = this; | |
window.addEventListener('resize', u.debounce(function () { | |
_this.calcElementQueries(); | |
})); | |
}; | |
ElementQuery.prototype.calcElementQueries = function () { | |
this.emptyCurrentQueries(); | |
u.each(this.queries, function (query) { | |
this.calcElementQuery(query); | |
}, this); | |
this.applyQueries(); | |
}; | |
ElementQuery.prototype.calcElementQuery = function (query) { | |
var offsetValue = this.getOffsetValue(query.dimension); | |
var computedValue = this.getComputedValue(query.value, query.unit); | |
if (query.limit === 'min') { | |
if (offsetValue >= computedValue) { | |
this.currentQueries[query.dataKey].push(query); | |
} | |
} else if (query.limit === 'max') { | |
if (offsetValue <= computedValue) { | |
this.currentQueries[query.dataKey].push(query); | |
} | |
} | |
}; | |
ElementQuery.prototype.getOffsetValue = function (dimension) { | |
if (dimension === 'width') { | |
return this.eqEle.offsetWidth; | |
} else if (dimension === 'height') { | |
return this.eqEle.offsetHeight; | |
} | |
}; | |
ElementQuery.prototype.getComputedValue = function (value, unit) { | |
var computedValue, | |
baseFontSize; | |
switch (unit) { | |
case 'rem': | |
baseFontSize = this.getFontSize(this.html); | |
computedValue = baseFontSize * value; | |
break; | |
case 'em': | |
baseFontSize = this.getFontSize(this.eqEle); | |
computedValue = baseFontSize * value; | |
break; | |
default: | |
computedValue = value; | |
} | |
return computedValue; | |
}; | |
ElementQuery.prototype.applyQueries = function () { | |
for (var dataKey in this.currentQueries) { | |
if (this.currentQueries.hasOwnProperty(dataKey)) { | |
var data = []; | |
var dataSet = this.currentQueries[dataKey]; | |
u.each(dataSet, function (query) { | |
data.push(query.value + query.unit); | |
}); | |
this.eqEle.dataset[dataKey] = data.join(' '); | |
} | |
} | |
} | |
/* Initial Setup */ | |
ElementQuery.prototype.emptyCurrentQueries = function () { | |
this.currentQueries = { | |
minWidth: [], | |
maxWidth: [], | |
minHeight: [], | |
maxHeight: [] | |
}; | |
}; | |
ElementQuery.prototype.getQueries = function (queryStr) { | |
var queries = [], | |
queryStrs = queryStr.split(','); | |
u.each(queryStrs, function (query) { | |
var queryObj = this.getQueryObject(query); | |
if (queryObj) { | |
queries.push(queryObj); | |
} | |
}, this); | |
return queries; | |
}; | |
ElementQuery.prototype.getQueryObject = function (queryStr) { | |
var queryMatch = queryStr.match(/(min|max)-(width|height):\s?(\d*)(px|rem|em)/); | |
if (queryMatch) { | |
return { | |
limit: queryMatch[1], | |
dimension: queryMatch[2], | |
value: parseFloat(queryMatch[3]), | |
unit: queryMatch[4], | |
dataKey: this.getDataKey(queryMatch[1], queryMatch[2]) | |
} | |
} else { | |
return false; | |
} | |
}; | |
ElementQuery.prototype.getFontSize = function (ele) { | |
return parseFloat(window.getComputedStyle(ele, null).getPropertyValue('font-size')); | |
}; | |
ElementQuery.prototype.getDataKey = function (limit, dimension) { | |
return limit + dimension.charAt(0).toUpperCase() + dimension.slice(1); | |
}; | |
/* Wrapper for multiple objects */ | |
var ElementQueries = function () { | |
var html = document.querySelector('html'); | |
var eqElements = document.querySelectorAll(eqElementSelector); | |
u.each(eqElements, function (eqEle) { | |
new ElementQuery(eqEle, html); | |
}); | |
}; | |
/* | |
Run this sucker | |
*/ | |
u.ready(function () { | |
new ElementQueries(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- Break points work with min and max, width and height, and use either px, em or rem --> | |
<div class="my-ele" data-element-query="min-width: 10em, min-width: 30em"> | |
... | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.my-ele { | |
background-color: red; | |
&[data-min-width~="10em"] { | |
background-color: green; | |
} | |
&[data-min-width~="30em"] { | |
background-color: blue; | |
} | |
} |
Edit 2017/05/15: Made into a standalone file.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FYI https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Testing_media_queries