WICG / cq-usecases

Use cases and requirements for standardizing element queries.
Other
184 stars 24 forks source link

What's acceptable for the element query polyfill #32

Closed adamdbradley closed 6 years ago

adamdbradley commented 9 years ago

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:

Configuration:

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

tysonmatanich commented 9 years ago

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 commented 9 years ago

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

adamdbradley commented 9 years ago

@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 commented 9 years ago

@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 commented 9 years ago

I found those:

ausi commented 8 years ago

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

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

serapath commented 8 years ago

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 commented 8 years ago

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:

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:

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 commented 8 years ago

@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:

serapath commented 8 years ago

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 commented 8 years ago

@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 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 commented 6 years ago

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!