Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

Vendor prefixes #11

Closed
alexlande opened this issue Jan 10, 2015 · 33 comments
Closed

Vendor prefixes #11

alexlande opened this issue Jan 10, 2015 · 33 comments

Comments

@alexlande
Copy link
Contributor

No description provided.

@mattborn
Copy link

I am so ready to start using this, but vendor prefixes were my third major concern after pseudo states and media queries. Not sure what the thinking is on this so far, but perhaps radium could work with Autoprefixer somehow so it’s not a concern at all?

@pstoica
Copy link

pstoica commented Feb 27, 2015

Maybe you could reuse JSS's css-vendor module? It checks on the client and caches the proper prefixes. Less bloat to download, and it's not expensive for browsers to do. https://github.com/jsstyles/css-vendor

@ianobermiller
Copy link
Contributor

Something like prefixfree might work as well: https://github.com/LeaVerou/prefixfree

@alexlande
Copy link
Contributor Author

Definitely agree that this should work transparently, ideally with Can I Use... support like Autoprefixer. Also ideally we wouldn't write this ourselves. Probably need to start by doing a survey of the solutions listed here (and any others we can think of) to see what might work best.

@gpbl
Copy link

gpbl commented Feb 27, 2015

material-ui is also porting its CSS to JS. For what I see, they are using a mixin which adopted a custom version of modernizr. It could be a source of inspiration. Maybe @hai-cea could drop some tip :-)

@mattborn
Copy link

@pstoica @ianobermiller My gut tells me it’s worth it to avoid a client-side solution even if it’s not expensive in the browser. I don’t have a scientific reason, but some of the team members I work with prefer to declare exactly which browsers we support and have the vendor prefixes explicitly rolled up in the build.

Even though Autoprefixer is a CSS parser, I was hoping it would be easy to implement since it’s already 98.2% Javascript. That said, I am a product designer + don’t know that I’d be much help with the level of neck-bearded thinking that will be required to figure this out.

@hai-cea
Copy link

hai-cea commented Feb 28, 2015

Modernizr comes with a handy function that will prefix js styles only if the browser needs it:
http://modernizr.com/docs/#prefixed

We generated a custom Modernizer build by only selecting the tests we needed:
http://modernizr.com/download/

We also created some simple helper functions to prefix our style objects:
https://github.com/callemall/material-ui/blob/css-in-js/src/js/styles/auto-prefix.js

We still need to figure out how to allow for server side rendering. Since we can't use Modernizr on the server, we need to come up with an alternative.

Hope all of that helps. :)

@jasonkuhrt
Copy link

@ai thoughts?

@ai
Copy link

ai commented Feb 28, 2015

@jasonkuhrt Autoprefixer is too big to take it to client side.

@swennemans
Copy link

What about a combination of webpack, css-to-radium and autoprefixer? So a very simplified (naive) workflow.

Require('styles.css') --> autoprefix with webpack --> css-to-radium and now the Require('styles.css') would be Require('styles.js');

An added benefit is that you still would be able to develop in a separate style file. Hopefully it won't throw any weird errors when adding value/functions in your styles.css before conversion.

@wmertens
Copy link

wmertens commented Mar 6, 2015

https://github.com/cgarvis/react-vendor-prefix is very small (https://github.com/cgarvis/react-vendor-prefix/blob/master/src/index.js) and does the job nicely.
It would be great if radium used this automatically.

@colinmegill
Copy link
Contributor

+1 great find, thanks for this

On Fri, Mar 6, 2015 at 1:51 AM, Wout Mertens [email protected]
wrote:

https://github.com/cgarvis/react-vendor-prefix is very small (
https://github.com/cgarvis/react-vendor-prefix/blob/master/src/index.js)
and does the job nicely.
It would be great if radium used this automatically.


Reply to this email directly or view it on GitHub
#11 (comment)
.

@colinmegill
Copy link
Contributor

Also vote it is not included by default, ie same syntax:

var { StyleResolverMixin, BrowserStateMixin, VendorPrefixMixin } = require('radium');

@alexlande
Copy link
Contributor Author

Agree that we don't want to run it by default. Iterating over every rule by default sounds like a performance headache in the making.

I'll try out react-vendor-prefix, but it looks like a great solution. Thanks for the suggestion!

@swennemans: That could work, definitely! Radium is agnostic to build process (unfortunately for this case, because this is really a situation where preprocessors shine and doing it at run time isn't necessary), but if you have a setup like that you should be in good shape.

An idea that's an ugly API but might be a good middle ground between performance and convenience is to support a prefix property (similar to computed) on style objects that we could autoprefix any rules declared in.

{
  background: 'blue',
  color: 'red',

  prefix: {
    transition: '0.3s ease all'
  }
}

@wmertens
Copy link

wmertens commented Mar 6, 2015

👍 on the ugly prefix idea, that's nicer than having to include a mixin.

On Fri, Mar 6, 2015, 7:38 PM Alex Lande [email protected] wrote:

Agree that we don't want to run it by default. Iterating over every rule
by default sounds like a performance headache in the making.

I'll try out react-vendor-prefix, but it looks like a great solution.
Thanks for the suggestion!

@swennemans https://github.com/swennemans: That could work, definitely!
Radium is agnostic to build process (unfortunately for this case, because
this is really a situation where preprocessors shine and doing it at run
time isn't necessary), but if you have a setup like that you should be in
good shape.

An idea that's an ugly API but might be a good middle ground between
performance and convenience is to support a prefix property (similar to
computed) on style objects that we could autoprefix any rules declared in.

{
background: 'blue',
color: 'red',

prefix: {
transition: '0.3s ease all'
}
}


Reply to this email directly or view it on GitHub
#11 (comment)
.

@wmertens
Copy link

wmertens commented Mar 6, 2015

Actually on second thought, that is premature optimization. Looking at the code it is quite tiny and only in some cases does it need to intervene. Furthermore the current code misses some optimizations, like making the flexbox tests a null operation on non-safari or IE 10 browsers.
Radium needs to iterate over the CSS already, so why not add in a quick check to see if an attribute is part of a to-be-prefixed map?

@alexlande
Copy link
Contributor Author

We don't iterate over individual properties. I don't have data to back this up because I haven't tried it, but iterating over every CSS property that's going to be rendered + checking it against a dictionary of properties that need prefixes seems like it will definitely have an adverse impact on performance, given the number of properties rendered at any time in a good-sized app.

We could memoize the check, which would help some, but I'm not convinced.

I guess the right thing is to do some benchmarks before making that call either way.

@wmertens
Copy link

wmertens commented Mar 7, 2015

So according to this benchmark modern browsers can do 50-75 million checks
per second :)
http://jsperf.com/hasownproperty-vs-in-vs-undefined/12

Furthermore, there could be a vendorPrefixes boolean added to the style
object, that would make Radium perform the prefixing (as well as a Radium
static setting to enable it?). It will be ignored by the style setting so
that's nicer than a prefix sub-object.

As for keeping the prefixes up-to-date, because it's running in the browser
it can simply check at startup what needs prefixing by inspecting the style
object of head and checking what is available. E.g. check if
style.transition exists, otherwise try webkitTransition etc. Once you found
your first prefix you know what the browser prefix is.
Attribute value prefixing like flexbox support can be checked simply by
setting display to "flex", "-webkit-flex", "-ms-flexbox" and seeing if the
setting sticks.
You run this check once, the first time you encounter
style.vendorPrefixes===true, and create an array of attributes that need
translation as well as a function that does flexbox renaming if needed.
Then, for the array of attributes, check if the style object has the
attribute and translate.

All that needs to be maintained then is the list of to-prefix attributes.

In any case I think this should be enabled by default, because the overhead
is small and it Just Makes Things Work. If you're working on an app where
all performance matters, disable it and figure it out manually.

On Fri, Mar 6, 2015 at 11:06 PM Alex Lande [email protected] wrote:

We don't iterate over individual properties. I don't have data to back
this up because I haven't tried it, but iterating over every CSS property
that's going to be rendered + checking it against a dictionary of
properties that need prefixes seems like it will definitely have an adverse
impact on performance, given the number of properties rendered at any time
in a good-sized app.

We could memoize the check, which would help some, but I'm not convinced.

I guess the right thing is to do some benchmarks before making that call
either way.


Reply to this email directly or view it on GitHub
#11 (comment)
.

@wmertens
Copy link

wmertens commented Mar 8, 2015

@alexlande when you do _.merge, you're iterating over properties 😁.

Anyway, I wrote up a completely automatic prefixer, I have to turn it into a module though.
http://codepen.io/wmertens/pen/EaeXqY?editors=001
It works by checking if a css property exists and trying prefixes if not, so it doesn't need tables.

It's lazy and memoized, and some initial jsperfing shows that it's 5000x faster than creating an element with react.

@alexlande
Copy link
Contributor Author

@wmertens You're right, not sure what I was thinking 😄.

Your module looks awesome, nice work! I think we'll need something based on a dictionary to support server-side rendering though. react-vendor-prefix seems like the best option for that use case right now.

I'll try it out today 👍

@alexlande
Copy link
Contributor Author

Never mind, react-vendor-prefix has the same end result (only prefixes for the current browser).

Will work on putting something together.

@wmertens
Copy link

wmertens commented Mar 8, 2015

I've done more pondering in the mean time: It's probably faster to just add
the prefixed version into the style object instead of creating a new
object, since the browser will ignore unsupported properties. So in that
case the module should keep track of supported vs unsupported vs
yet-untested properties and then the prefixed versions for the needed
translations. Just testing membership without reading the value is fast so
there would be an object with only valid don't-change properties, and then
the current foundProps translation object.
Kind of depends on where in the Radium flow it would go.

For the server version, an option would be to parse the caniuse data to
find properties that sometimes need prefixing, and then just output all
versions of those. The browser will ignore what it can't use and it works
everywhere, at the cost of some bytes of course.

Then, a next stage would be supporting prefixed attributes in animation and
so on, but that seems a bit more complex and certainly something I'd expect
people to call separately.

On Sun, Mar 8, 2015 at 7:38 PM Alex Lande [email protected] wrote:

Never mind, react-vendor-prefix has the same end result (only prefixes for
the current browser).

Will work on putting something together.


Reply to this email directly or view it on GitHub
#11 (comment)
.

@wmertens
Copy link

For the server side, I think it's best to just post-process with autoprefixer: https://github.com/RebelMail/html-autoprefixer

BTW there's a bug in my codepen code: the 'ms' prefix should not be capitalized. Sigh.

@ghost
Copy link

ghost commented Mar 12, 2015

like @wmertens on server side its maybe better to 'over saturate' css with all know prefixes.

@benoneal
Copy link

Any progress on this? The html-autoprefixer + react-vendor-prefix solutions sound great.

@wmertens
Copy link

Here's my prefixer module, not npm-ed yet but working fine as far as I can
tell: https://gist.github.com/wmertens/78c840ce04b6e9a1193d

On Tue, Mar 31, 2015 at 8:21 AM benoneal [email protected] wrote:

Any progress on this? The html-autoprefixer + react-vendor-prefix
solutions sound great.


Reply to this email directly or view it on GitHub
#11 (comment)
.

@fabien-h
Copy link

fabien-h commented Apr 2, 2015

I don't get why the StyleResolverMixin could not implement a autoprefixing functionnality.

It's not that big.

@wmertens
Copy link

wmertens commented Apr 2, 2015

Yes, +1 for copying my prefixer module into Radium. I can make it into an
npm module instead if desired.
https://gist.github.com/wmertens/78c840ce04b6e9a1193d

On Thu, Apr 2, 2015 at 5:23 PM fabien huet [email protected] wrote:

I don't get why the StyleResolverMixin could not implement a
autoprefixing functionnality.

It's not that big.


Reply to this email directly or view it on GitHub
#11 (comment)
.

@pikeas
Copy link

pikeas commented Apr 8, 2015

+1, would love to start using Radium, but vendor prefixes are a must. Will check out your gist, @wmertens!

@chiefjester
Copy link

+1

@chiefjester
Copy link

I see a PR merged does this resolve this issue of radium lacking vendor prefixes?

@ianobermiller
Copy link
Contributor

Yes, for the majority of cases. I think we are still missing a server-side component and some of the advanced prefixing capabilities, like the old flexbox syntax. But besides those, the current implementation will prefix css properties and values.

@mattborn
Copy link

mattborn commented Nov 8, 2015

Official support in core autoprefixer: https://github.com/postcss/autoprefixer/releases/tag/6.1.0

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests