Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

What's acceptable for the element query polyfill #32

Closed
adamdbradley opened this issue Apr 20, 2015 · 15 comments
Closed

What's acceptable for the element query polyfill #32

adamdbradley opened this issue Apr 20, 2015 · 15 comments

Comments

@adamdbradley
Copy link

I was hoping to layout the various hacks that can be used for the polyfill, and open up a discussion of what is and is not acceptable.

Matching:

  • Object Element: Using matchMedia on a nested object element within the container.
  • window.resize: On resize do a check on each container.

Configuration:

  • document.styleSheets: Loop through each rule and check if it has EQ information
  • Element attributes: Setting an element's EQ(s) via an attribute
  • Parsing Text: Manually parsing CSS text for the new syntax, which would be currently invalid css
  • CSS properties that accept text: Using the content property

What other methods could we add to this? And what methods can we absolutely say "no that's just too hacky".

@tysonmatanich
Copy link

document.styleSheets doesn't work for cross-domain requests, which is a common use case for sites using a CDN etc. I used JS to register the selectors but this is a total hack - https://github.com/tysonmatanich/elementQuery#selector-registration.

@wnr
Copy link
Contributor

wnr commented Apr 21, 2015

Have an EQ polyfill been discussed anywhere? I can't find anything in the mail archive or in the IRC logs.

@adamdbradley
Copy link
Author

@wnr I recall that creating a polyfill was discussed somewhere, but maybe I made that up or it was from other reference, idk. I guess a better question is if there's a goal that a polyfill could be created for element queries, or is it not realistic being that it'll probably involve CSS that would be invalid on today's browsers.

@wnr
Copy link
Contributor

wnr commented Apr 22, 2015

@adamdbradley Okay I understand, thought I missed something for a second.
I think creating a polyfill is a perfectly valid goal. My Master's Thesis actually aims to create a framework to realize element queries. There are many approaches, and my studies have shown that there is no silver bullet to element queries. In roughly two months my thesis will be done and you can then read my verdict and hopefully use my implementation :)

@serapath
Copy link

serapath commented Jul 9, 2015

@ausi
Copy link
Collaborator

ausi commented Oct 6, 2015

I created a prolyfill too: ausi/cq-prolyfill.

The idea about how they work can be found in WICG/container-queries#3.

@serapath
Copy link

serapath commented Oct 6, 2015

There are so many opinions on this.
What about making it controllable from a javascript API?

Think about something like react, where you assign a certain CLASS to an element in JSX and then you use the "container query API" to assign resiz behavior to it?

So it would be cool to split stuff into modules to have the best performing "resize sensor" in it's own module and then use it for different prolyfills or ponyfills :-)

Any thoughts on this?

@wnr
Copy link
Contributor

wnr commented Oct 7, 2015

Hi all,

I've finished my Master's Thesis now, and I think the result is close to what you describe @serapath.
I have created a library called ELQ, which aims to be a solid foundation for element queries.
The result is a JavaScript API that is very extensible, and a few plugins that implement different element queries API's.
As a side result, two supporting projects have been created: element-resize-detector and batch-processor.

Here are some positive properties of ELQ:

  • High extensibility through plugins
  • Super-fast element resize detection
  • Batch processed updates of elements breakpoint states (to avoid layout thrashing)
  • Compatibility with existing code (conforms to HTML, JS and CSS specs)
  • Compatibility with browsers (IE8+, Opera 12+, etc)
  • A runtime cycle detection system
  • Allowing style encapsulation of responsive elements (this allows nestable responsive modules)

I think that it is suitable to serve as a foundation for many element queries-based polyfills, prolyfills, API's, libraries, and what not. There are a few plugins that I'm thinking of (and have been told needed by colleagues) at the moment that could easily be created as plugins:

  • A plugin to parse CSS so that breakpoints can be defined in CSS only. (And possibly integration with PostCSS, similar to what you did @ausi).
  • A plugin to enable toggling of classes for elements, so that the classes present at an element may be conditional by breakpoints.
  • A plugin to enable a class-based high-level API similar to Bootstrap Grid and utils. This plugin is taking form at https://github.com/elqteam/elq-grid/, but is not yet ready to be used.

It was my intention to polish the code a bit more before releasing it to you guys, but I think it is wise to share it now as the question has arisen. So please keep in mind that it is an early beta version. With that said, my employer is currently integrating ELQ into enterprise web applications for banks so it will definitely be stabilized and well tested in the near future.

What do you think of it?

@ausi, perhaps we can collaborate to port your code to an ELQ plugin?

Here's ELQ: https://github.com/elqteam/elq

@ausi
Copy link
Collaborator

ausi commented Oct 7, 2015

@ausi, perhaps we can collaborate to port your code to an ELQ plugin?

I’m not sure if this is possible, as my prolyfill works a bit different than most others:

  • The “container” is selected by the script which needs to know the computed style and the cascaded style of all elements (e.g. the difference between width: auto and width: 100%). The selected container is not fixed and may change.
  • The breakpoints are dynamic and may depend on the font-size of the container.
  • It is not limited to dimension queries and supports other properties too, e.g. :container(text-align = right).

@serapath
Copy link

serapath commented Oct 8, 2015

Interesting :-)

What is: https://github.com/wnr/elq-dummy ? elq-grid depends on it.

And https://github.com/wnr/element-resize-detector depends on https://github.com/wnr/batch-processor which does not depend on elq-grid ...

From what you describe above, i feel a plugin architecture in general is not nice.
Bad examples: grunt, gulp :-)

Why wouldn't you instead make your library a useful "service library" that others can just require(..) and build whatever they need on top.

batch-processor doesn't use requestAnimationFrame yet but maybe should.
There is a library called raf (npm install raf) which should be cross browser

Otherwise - the resize sensor is 1000 lines big, that's a little heavy weight - is that really necessary?

@wnr
Copy link
Contributor

wnr commented Oct 8, 2015

@ausi

I’m not sure if this is possible, as my prolyfill works a bit different than most others:

It is my goal that ELQ should be a suitable foundation for most prolyfills, so if it is not compatible at the moment, I gladly redesign some bits to make it even more general.

The “container” is selected by the script which needs to know the computed style and the cascaded style of all elements (e.g. the difference between width: auto and width: 100%). The selected container is not fixed and may change.

My solution does not assumed fixed elements.

The breakpoints are dynamic and may depend on the font-size of the container.

This is also supported, if by dynamic you mean that breakpoints are able to change. ELQ also currently supports breakpoints with unit "px", "em", or "rem".

It is not limited to dimension queries and supports other properties too, e.g. :container(text-align = right).

This is on my todo-list, to support arbitrary element properties. Since I have been unable to find a proper use case for this, it does not have very high prio at the moment. But it should not be too hard to support.

@serapath

What is: https://github.com/wnr/elq-dummy ? elq-grid depends on it.

elq-dummy is a repo that hogs the npm/elq name. As soon as npm/elq actually points to elqteam/elq, it will be deleted. The elq-grid plugin is not finished, and therefore strange stuff such as that still floats around. I just uploaded it so that you could glance at the code :)

And https://github.com/wnr/element-resize-detector depends on https://github.com/wnr/batch-processor which does not depend on elq-grid ...

What do you mean? element-resize-detector depends on batch-processor, correctly. Neither of them should depend on elq-grid.

From what you describe above, i feel a plugin architecture in general is not nice.
Bad examples: grunt, gulp :-)

Please elaborate :)

Why wouldn't you instead make your library a useful "service library" that others can just require(..) and build whatever they need on top.

It is fully possible to require ELQ in any way, and build stuff on top. Or what am I missing? Plugins creates an unified method of handling and installing these additions and extensions.

batch-processor doesn't use requestAnimationFrame yet but maybe should.
There is a library called raf (npm install raf) which should be cross browser

Waiting for next layout frame before processing a batch could be useful, but for the element resize detection I think it makes more sense to process it as quickly as possible. Imagine a user resizing an element. The width is now narrower than a breakpoint that is supposed to style the element red. Since element queries will always be one layout behind, the browser will perform a layout so that the element has the new width but still is not colored red. Now, we want to minimize the time that the user sees the invalid design, so it is important to process the batch as quickly as possible.

Otherwise - the resize sensor is 1000 lines big, that's a little heavy weight - is that really necessary?

Basically, yes. However, the resize sensor currently ships with two strategies. In the future this may be reduced to one. I have focused on nice, commented, readable and maintainable code. I'm all ears how to reduce the code size, if needed. It's 3.7 KB minified and gzipped :)

@serapath
Copy link

serapath commented Oct 8, 2015

I think it's in general nicer if you can just use modules, e.g. uglifyjs instead of the need to wrap it in order to use it as gulp-uglify or grunt-uglify ... so you create stuff that's only useful with those "ecosystems" and not without. That's kind of like a "vendor lock in" and people need to write code multiple times to adapt it to certain tools.

That's why I like npm scripts where i just use the core modules that solve a certain piece of functionality directly, rather than wrapping them into some opinionated structure plugin ecosystem.

ok, i understand the problem with raf vs custom :-)

cool - i'll follow the project

@ausi
Copy link
Collaborator

ausi commented Oct 8, 2015

I think too that using just modules would be nicer. Independent modules from which a creator of a prolyfill can select would probably be more useful.

I don’t really see the use case for a big element query system where I can plug in different prolyfills. Why would someone want to use multiple element query prolyfills on the same page?

@wnr
Copy link
Contributor

wnr commented Oct 9, 2015

I think it's in general nicer if you can just use modules, e.g. uglifyjs instead of the need to wrap it in order to use it as gulp-uglify or grunt-uglify ... so you create stuff that's only useful with those "ecosystems" and not without. That's kind of like a "vendor lock in" and people need to write code multiple times to adapt it to certain tools.

I think too that using just modules would be nicer. Independent modules from which a creator of a prolyfill can select would probably be more useful.

I understand, and agree that vendor-lock in is a drawback.
However, I think we are comparing different things, as uglifyjs is a general and useable component by itself where ELQ plugins are more of extensions of an existing code base.
Is jQuery bad because they also allow developers to extend it with plugins?
Is ESLint bad because one may write custom rules?
Is lodash bad because it is possible to extend it?

To be clear, there is a difference between extending the core of a library, and having an eco-system like grunt that requires wrapping of existing libraries :) Grunt basically says "if you want to use a standalone library X, you need to create grunt-X", where X might be something like jQuery, React, Backbone, etc. This is not the case with ELQ, as it plays perfectly fine with X and does not require anyone to write glue in order to use it with other libraries.

So the plugin-system is really a way to let external developers extend ELQ, and create their own element queries functionality, without having to bog down into details about the core or reinventing the wheel.

If I want to use element queries functionality X, Y and Z in my application I don't want to include three different libraries that implement their own base logic (such as resize detection, batch processing, cycle detection, error handling, etc.). Instead, a nicer approach is to have a foundation which I can extend with functionality X, Y and Z (and perhaps W in the future). This is not only a nicer API for the user, but also nicer for plugin developers as they can really focus on the behavior than the underlaying systems.

I don’t really see the use case for a big element query system where I can plug in different prolyfills. Why would someone want to use multiple element query prolyfills on the same page?

This perhaps gets more evident when developing large applications using responsive modules, as my employer does. We started off wanting element queries, for flexibility and power (base ELQ).
Then we realized that it would be nice to have a high-level API that allows us to use classes to define grids (similar to Bootstrap) that gets converted to element queries - no problem, there's a plugin for that! Then it would be beneficial to be able to toggle classes of some elements by breakpoints - no problem, there's a plugin for that! Then, in some cases we wanted to completely change a view to another view by breakpoints - no problem, there's a plugin for that! Later, we might decide that we want to define some breakpoints in CSS - no problem, there's a plugin for that!
And so on, I hope you see my point here.

The beauty of ELQ is that you are able to mix-n-match functionality for different use cases in a controlled way. This enables users to experiment and use different functionality through an unified API, without having to worry about each functionality bringing their own implementation of core element queries logic. Plugins may even collaborate in order to achieve some functionality. If ELQ wouldn't be plugin-based, then developers would need to hard-extend the code by modifications and additions. As soon as developers want to share their extensions with each other, their extensions will probably collide. Also, how would developers use two extensions at the same time, by using the extensions separate which means having two underlaying ELQ instances? A plugin-based design simply tries to ease the development and usage process.

tl;dr: You do want to use different plugins in different cases (and perhaps multiple plugins in the same application), and having an extensible foundation is a good way of enabling that :)

@eeeps
Copy link
Collaborator

eeeps commented Feb 8, 2018

Closing this, as polyfill techniques aren’t in-scope for work on the Use Cases / Requirements document.

@tomhodgins this issue reminds me strongly of what you were discussing yesterday, some kind of event or venue for plugin authors to talk/share experiences. IMO, you should set something up for that, as you're clearly not alone!

@eeeps eeeps closed this as completed Feb 8, 2018
@eeeps eeeps removed the issue-audit label Feb 8, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants