diff --git a/docs/tips/02-inline-styles.md b/docs/tips/02-inline-styles.md index 1f61596a54..01d80285fe 100644 --- a/docs/tips/02-inline-styles.md +++ b/docs/tips/02-inline-styles.md @@ -15,10 +15,11 @@ In React, inline styles are not specified as a string. Instead they are specifie var divStyle = { color: 'white', backgroundImage: 'url(' + imgUrl + ')', - WebkitTransition: 'all' // note the capital 'W' here + WebkitTransition: 'all', // note the capital 'W' here + msTransition: 'all' // 'ms' is the only lowercase vendor prefix }; React.renderComponent(
Hello World!
, mountNode); ``` -Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes from JS (e.g. `node.style.backgroundImage`). Vendor prefixes should begin with a capital letter. This is why `WebkitTransition` has an uppercase "W". +Style keys are camelCased in order to be consistent with accessing the properties on DOM nodes from JS (e.g. `node.style.backgroundImage`). Vendor prefixes [other than `ms`](http://www.andismith.com/blog/2012/02/modernizr-prefixed/) should begin with a capital letter. This is why `WebkitTransition` has an uppercase "W". diff --git a/src/browser/ui/dom/CSSPropertyOperations.js b/src/browser/ui/dom/CSSPropertyOperations.js index 8bb292ee7e..27db51bc0d 100644 --- a/src/browser/ui/dom/CSSPropertyOperations.js +++ b/src/browser/ui/dom/CSSPropertyOperations.js @@ -21,14 +21,33 @@ var CSSProperty = require('CSSProperty'); +var camelizeStyleName = require('camelizeStyleName'); var dangerousStyleValue = require('dangerousStyleValue'); var hyphenateStyleName = require('hyphenateStyleName'); var memoizeStringOnly = require('memoizeStringOnly'); +var warning = require('warning'); var processStyleName = memoizeStringOnly(function(styleName) { return hyphenateStyleName(styleName); }); +if (__DEV__) { + var warnedStyleNames = {}; + + var warnHyphenatedStyleName = function(name) { + if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) { + return; + } + + warnedStyleNames[name] = true; + warning( + false, + 'Unsupported style property ' + name + '. Did you mean ' + + camelizeStyleName(name) + '?' + ); + }; +} + /** * Operations for dealing with CSS properties. */ @@ -52,6 +71,11 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + if (__DEV__) { + if (styleName.indexOf('-') > -1) { + warnHyphenatedStyleName(styleName); + } + } var styleValue = styles[styleName]; if (styleValue != null) { serialized += processStyleName(styleName) + ':'; @@ -74,6 +98,11 @@ var CSSPropertyOperations = { if (!styles.hasOwnProperty(styleName)) { continue; } + if (__DEV__) { + if (styleName.indexOf('-') > -1) { + warnHyphenatedStyleName(styleName); + } + } var styleValue = dangerousStyleValue(styleName, styles[styleName]); if (styleValue) { style[styleName] = styleValue; diff --git a/src/browser/ui/dom/__tests__/CSSPropertyOperations-test.js b/src/browser/ui/dom/__tests__/CSSPropertyOperations-test.js index b40617f743..29bc77a9c2 100644 --- a/src/browser/ui/dom/__tests__/CSSPropertyOperations-test.js +++ b/src/browser/ui/dom/__tests__/CSSPropertyOperations-test.js @@ -108,4 +108,32 @@ describe('CSSPropertyOperations', function() { expect(/style=".*"/.test(root.innerHTML)).toBe(false); }); + it('should warn when using hyphenated style names', function() { + spyOn(console, 'warn'); + + expect(CSSPropertyOperations.createMarkupForStyles({ + 'background-color': 'crimson' + })).toBe('background-color:crimson;'); + + expect(console.warn.argsForCall.length).toBe(1); + expect(console.warn.argsForCall[0][0]).toContain('backgroundColor'); + }); + + it('should warn when updating hyphenated style names', function() { + spyOn(console, 'warn'); + + var root = document.createElement('div'); + var styles = { + '-ms-transform': 'translate3d(0, 0, 0)', + '-webkit-transform': 'translate3d(0, 0, 0)' + }; + + React.renderComponent(
, root); + React.renderComponent(
, root); + + expect(console.warn.argsForCall.length).toBe(2); + expect(console.warn.argsForCall[0][0]).toContain('msTransform'); + expect(console.warn.argsForCall[1][0]).toContain('WebkitTransform'); + }); + }); diff --git a/src/vendor/core/camelizeStyleName.js b/src/vendor/core/camelizeStyleName.js new file mode 100644 index 0000000000..ea4ff460c2 --- /dev/null +++ b/src/vendor/core/camelizeStyleName.js @@ -0,0 +1,47 @@ +/** + * Copyright 2014 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule camelizeStyleName + * @typechecks + */ + +"use strict"; + +var camelize = require('camelize'); + +var msPattern = /^-ms-/; + +/** + * Camelcases a hyphenated CSS property name, for example: + * + * > camelizeStyleName('background-color') + * < "backgroundColor" + * > camelizeStyleName('-moz-transition') + * < "MozTransition" + * > camelizeStyleName('-ms-transition') + * < "msTransition" + * + * As Andi Smith suggests + * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix + * is converted to lowercase `ms`. + * + * @param {string} string + * @return {string} + */ +function camelizeStyleName(string) { + return camelize(string.replace(msPattern, 'ms-')); +} + +module.exports = camelizeStyleName; diff --git a/src/vendor/core/hyphenateStyleName.js b/src/vendor/core/hyphenateStyleName.js index 6586378a2b..26cd3c678e 100644 --- a/src/vendor/core/hyphenateStyleName.js +++ b/src/vendor/core/hyphenateStyleName.js @@ -26,11 +26,11 @@ var msPattern = /^ms-/; /** * Hyphenates a camelcased CSS property name, for example: * - * > hyphenate('backgroundColor') + * > hyphenateStyleName('backgroundColor') * < "background-color" - * > hyphenate('MozTransition') + * > hyphenateStyleName('MozTransition') * < "-moz-transition" - * > hyphenate('msTransition') + * > hyphenateStyleName('msTransition') * < "-ms-transition" * * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix