Skip to content

Instantly share code, notes, and snippets.

@jonathantneal
Last active January 30, 2020 10:42
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathantneal/d4e27ac9a65a426e6870 to your computer and use it in GitHub Desktop.
Save jonathantneal/d4e27ac9a65a426e6870 to your computer and use it in GitHub Desktop.
Simulating Element Queries

Simulating Element Queries

Until real element queries show up in a specification or a browser, these are the simulated techniques that I’m aware of. Am I missing others? Let me know.

Evaluating the pros and cons of each technique may help you decide which ones works best in your situation.

Technique #1: Window Resize Events

addEventListener('resize', function () {
	var
	elements = document.querySelector(element_selectors),
	width = window.innerWidth;

	// do stuff
});

Pros

  • Will fire on all window size changes.
  • May be used to select individual elements.
  • Will work in legacy browsers with nominal polyfilling.

Cons

  • Does not detect when elements change size without the window resizing.
  • May fire way too often, to the point of necessitating a throttle.
  • May require expensive element checks and/or element sizing checks.

Technique #2: Media Query Events

// fires when the query goes from true to false or vice versa
matchMedia('(max-width: 640px)').addListener(function (q) {
	var elements = document.querySelectorAll(element_selectors);

	// do stuff
});

Pros

  • May be used to modify individual elements.
  • Will only fire when specific breakpoints occur.
  • Will work in legacy browsers with some polyfilling.

Cons

  • Does not detect when element changes size without window resize.
  • Limited to specific breakpoints.

Technique #3: Polling

requestAnimationFrame(function () {
	var
	elements = document.querySelector(element_selectors),
	width = window.innerWidth;

	// do stuff
});

Pros

  • May be used to detect when individual elements change size.
  • Will work in legacy browsers with nominal polyfilling.

Cons

  • Will fire way too often, probably 60 times a second, no matter what.
  • May require expensive element checks and/or element sizing checks.

Technique #4: Iframe Media Query Events

NodeList.prototype.forEach = Array.prototype.forEach;

document.querySelectorAll(element_selectors).forEach(function (element) {
	// inject a hidden iframe for each element
	var iframe = element.appendChild(document.createElement('iframe'));

	iframe.style.cssText = 'border:0;height:100%;position:absolute;width:100%;z-index:-1';

	iframe.contentWindow.matchMedia(query).addListener(function (media) {
		// do stuff
	});
});

Pros

  • Fires on all element size changes.
  • Works in legacy browsers with some polyfilling.

Cons

  • Requires a position of relative, absolute, or sticky on the element.
  • May add <iframe> elements all over the page.
  • May upset :nth-child selectors.
  • May fire too often.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment