Method to provide hyphenated versions of prefixed CSS properties #848

Merged
merged 1 commit into from Mar 2, 2014

Projects

None yet

4 participants

@robcolburn

This issue was originally called “Vendor prefix constant”, but conversation has diverged. #1223 will result in a Modernizr._prefix property being added, fulfilling the OP’s original request, so we’ll track that request over there. – Stu Cox


Sometimes, to just get the vendor prefix for unsupported cases…

$('head').append([
'<style>',
'.carousel {',
prefix('transition') + ': all ' + duration + 's ease-in-out;',
prefix('transform') + ': translate3d(0, 0, 0);',
prefix('backface-visibility') + ':hidden;',  // Exception
'}',
'</style>'
].join("\n"));

function prefix (n) {
    return Modernizr.prefixed(n).replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
}
@patrickkettner
Member

Hey @robcolburn - what is it you are suggesting here?
Are you looking to add a new function to Modernizr that generates css values, or just leaving it here as a suggestion to others?

@stucox
Member
stucox commented Jul 14, 2013

A couple of things:

  • Your function assumes that Modernizr.prefixed() will always return a string, but it will return a Boolean false if the property isn't found – hence the error
  • Modernizr.prefixed() takes camelCase variants… calling your function as prefix('backfaceVisibility') correctly returns -webkit-backface-visibility in Chrome

This would be a more robust version of your prefix() function:

function prefix (n) {
    var propName = Modernizr.prefixed(n);
    // If the property is found, return the hyphenated version of its name,
    // otherwise `false` to indicate that it wasn't found
    if (propName) {
        return propName.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
    }
    else {
        return false;
    }
}

Which you could then use something like this:

var prefixedProp;
...
// Only add property if supported
(prefixedProp = prefix('backfaceVisibility')) ? prefixedProp + ':hidden;' : '',
...
@robcolburn

My implementation is the quickest and dirtiest route I could make work for a feature I was building, so I didn't take the time to understand the details of the prefixed function. The full usage is to: first feature detect the features I want, detect viewport constraints I'm under, then build the appropriate script block. In this way, I could move logic away from inline script tags, and into something more declarative.

The merits of the approach are debatable, but that's part of the reason I went with that route - to discover how effective the technique could be. It's a shift from the simplicity of inline, without going full included (much more pain).

I've started this thread, because I believe it would be a handy feature for Modernizer core to support. I know my implantation is weak, so I'm hoping to encourage the community to implement it better. Nicely, the Modernizer lib is completely customizable in terms of weight, so we can stand for sugar features.

@stucox
Member
stucox commented Jul 16, 2013

You're not the first to request a function to provide hyphenated versions of prefixed CSS properties.

I actually have a branch with a Modernizr.prefixedHyphenated() function which does exactly that:

Modernizr.prefixedHyphenated('backfaceVisibility')  // '-webkit-backface-visibility'

I might open a PR to get it included? Alternative names welcome.

/cc @WillsB3

@patrickkettner
Member

Is there ever a time where hyphenation is other than css? I can't think of any...

prefixedCSS might be a more self documenting name

+1, otherwise

@WillsB3
WillsB3 commented Jul 16, 2013

+1 for prefixedHyphenated or prefixedCSS (I'm indifferent about both of these names, but can't think of anything more suitable)

@patrickkettner
Member

@stucox did you ever have a chance to get that goin?

@stucox
Member
stucox commented Dec 1, 2013

Commits ^^ @patrickkettner

Not 100% sure about the API… currently matches Modernizr.prefixed(), so it’s camelCase in and hyphenated out:

Modernizr.prefixedCSS('fontFeatureSettings')
> -webkit-font-feature-settings

Maybe it should be hyphenated in and out?

Modernizr.prefixedCSS('font-feature-settings')
> -webkit-font-feature-settings
@patrickkettner
Member

What would you think about supporting both styles of syntax? Postels law and all that

@stucox
Member
stucox commented Dec 1, 2013

I guess the obvious way to do that would be to convert hyphens-to-camelCase if the prop name contains a hyphen, before pushing it through prefixed()… which would obviously slow it down slightly. Small price to pay?

Although then should we allow Modernizr.prefixed() to accept hyphenated properties too? Or is that too confusing?

Is it already going to be too confusing having Modernizr.prefixedCSS() as well as Modernizr.prefixed() (which can also be used for style properties)? @paulirish was saying he thinks we already expose too much API surface area anyway.

@patrickkettner
Member

hmm.

perhaps your original Modernizr.prefixedHyphenated would be a bit better, than. prefixed would be camelCase, and prefixedHyphenated would be the hyphenated version.

@patrickkettner
Member

worth mentioning when you do submit a PR that this will fix #688

@stucox
Member
stucox commented Dec 2, 2013

This is a PR now, I converted it using the magic of hub :-)

Use cases

  1. Setting style properties in JS via elem.style makes sense as camelCase in & out for a lot of use cases – which .prefixed() does nicely:

    elem.style[Modernizr.prefixed('animationPlayState')] = 'running';
  2. Setting style properties in JS which use other CSS property names probably makes sense as hyph in & out, although transform is probably by far the most used like this and looks the same in camelCase and hyph:

    elem.style[Modernizr.prefixed('transition')] = Modernizr.prefixedCSS('transform') + ' 1s 0.5s';
  3. Dynamically generating style tags, as per the original post, probably makes sense as hyph in & out

So this function accepting a hyphenated input definitely makes sense. I can’t imagine a time when it would make sense to mix hyph/camel input/output in a function call.

I’d love to just extend .prefixed() so if you provide a camelCase input you get a camelCase output, provide a hyphenated input you get a hyphenated output… but single-word properties (e.g. transition) are ambiguous. Unless we use special syntax in the case of ambiguity, e.g. Modernizr.prefixed('-transition') returns the hyphenated form?

@patrickkettner
Member

care to squish it down for a formal review?

@WillsB3
WillsB3 commented Dec 2, 2013

@stucox I think avoiding making .prefixed() look like it's doing different magic depending on whether or not you use that special '-transition' syntax should be avoided. Keep the API simple and obvious.

Just my 2c

@patrickkettner
Member

+1 to @WillsB3

@WillsB3
WillsB3 commented Feb 20, 2014

I've just seen that Google Closure library has the function "goog.string.toSelectorCase". I quite like the "toSelectorCase" terminology. Maybe that's useful here instead of prefixedHyphenated or prefixedCSS.

@patrickkettner
Member

@stucox - were you still messign with this? toSelectorCase sounds good to me, for lack of a better option.

@stucox stucox self-assigned this Feb 22, 2014
@stucox stucox added this to the Modernizr v3 milestone Feb 22, 2014
@stucox
Member
stucox commented Feb 22, 2014

Just realised the topic title totally doesn’t match the code we’re discussing anymore, so I’ve renamed it and added a note to the first post.


Sorry @WillsB3, on reflection I’m not convinced by toSelectorCase – property names never appear in CSS selectors, do they? So I don’t see why ‘hyphenated’ is “selector case”. I can’t find any other reference to “selector case” being used to mean that.

My search did however throw up the terms “spinal-case”, “caterpillar-case” and, my favourite, “kebab-case”… although I don’t think any are common enough for us to use, as much as I’d love Modernizr to have a prefixedKebab() method.

Best ideas for easter eggs to hide in that API on the back of a postcard please.

So my vote is still with prefixedCSS(). What do you all think?

I’ll update my PR:

  • Both prefixed() and prefixedCSS() will accept camelCase or kebab-case
  • prefixed() will of course still output camelCase
  • prefixedCSS() will output kebab-case (getting quite fond of this term now)
  • I’ll squash it

Have assigned this to myself and put it in the v3 milestone.

@patrickkettner
Member

hahah - the most beautiful case I have ever seen with a kebab

thanks stu

@stucox stucox Adding `Modernizr.prefixedCSS()` API
Squashed commit of the following:

commit 508b8934dc86d9fa22f563081f6dae2b9b0dcca0
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Mar 2 01:09:31 2014 +0000

    Updated comments in `prefixedCSS` to explain that it accepts either camelCase or kebab-case

commit 9ba6dfa96be800b1e668eac3978fb0c2494976d0
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Mar 2 01:01:56 2014 +0000

    Removing duplicated/unused code and re-adding `cssToDOM()` (got lost in the rebase somewhere)

commit 0062bd8ade4f4ef08359040f0e4e01424c004f5b
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Mar 2 00:39:29 2014 +0000

    Added tests for both camelCase and kebab-case inputs to Modernizr.prefixed and Modernizr.prefixedCSS

commit 87e7271a954095c17c10c9029832f443b1f60285
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sat Mar 1 22:10:55 2014 +0000

    `Moderizr.prefixed()` and `Modernizr.prefixedCSS()` now accept properties in camelCase OR kebab-case

commit c1ccbc91c0e7837166d1677ab49c2ab2bffbef62
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sat Mar 1 21:40:35 2014 +0000

    Changed `domToHyphenated` to `domToCSS` throughout the repo

commit 560a929ce9efc954fafd20eebbf46412c62221ed
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Dec 1 21:26:36 2013 +0000

    Added tests for prefixedCSS()

commit dc0d27170afef838218562286c3b350ae39469b1
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Dec 1 20:44:22 2013 +0000

    Added comment to prefixed() re. prefixedCSS()

commit 6e34fc143fea73200167c71588f89316b66475b4
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Sun Dec 1 20:42:37 2013 +0000

    Changed name of prefixedHyphenated to prefixedCSS

commit fb9f494f51e769bccf5455956c4239a7774e60be
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Tue Jul 16 18:28:59 2013 +0100

    Handled case of `prefixed()` returning false and added to `config-all.json`

commit 7748702dfe4a5158ab970a84cbc6ae4a9e7459fd
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Tue Jul 16 18:11:49 2013 +0100

    Added domToHyphenated dependency

commit 74b5b9a5e476c41ddd1dc9fbb1363c3b3783b6a7
Author: Stu Cox <stuart.cox@gmail.com>
Date:   Tue Jul 16 17:57:35 2013 +0100

    Added prefixedHyphenated function
c4c60c1
@stucox
Member
stucox commented Mar 2, 2014

Updated 👍

@stucox stucox referenced this pull request Mar 2, 2014
Closed

v3.0 release notes #805

@patrickkettner
Member

bravo, sir.

lgtm

@stucox stucox merged commit 22a9cac into Modernizr:master Mar 2, 2014

1 check passed

default The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment