diff --git a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
index e695a845ff505..7d83b08424d7a 100644
--- a/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMComponent-test.js
@@ -2698,5 +2698,34 @@ describe('ReactDOMComponent', () => {
ReactDOM.render(, container);
expect(typeof container.onclick).not.toBe('function');
});
+
+ it('should warn about css shorthand properties collision', () => {
+ const container = document.createElement('div');
+ const oldStyle = {
+ background: 'url(http://example.org/image/a.jpg) no-repeat center',
+ backgroundSize: '150px',
+ backgroundColor: 'red',
+ };
+
+ ReactDOM.render(
, container);
+ const stubStyle = container.firstChild.style;
+
+ expect(stubStyle.background).toEqual(
+ 'url(http://example.org/image/a.jpg) no-repeat center',
+ );
+ expect(stubStyle.backgroundSize).toEqual('150px');
+ expect(stubStyle.backgroundColor).toEqual('red');
+
+ const newStyle = {
+ background: 'url(http://example.org/image/b.jpg) no-repeat center',
+ };
+
+ expect(() =>
+ ReactDOM.render(, container),
+ ).toWarnDev(
+ 'Warning: Css shorthand properties collision:' +
+ ' background properties are being overridden. (backgroundSize,backgroundColor)',
+ );
+ });
});
});
diff --git a/packages/react-dom/src/client/ReactDOMComponent.js b/packages/react-dom/src/client/ReactDOMComponent.js
index 4fded23f31a7d..7b61931c5d2b1 100644
--- a/packages/react-dom/src/client/ReactDOMComponent.js
+++ b/packages/react-dom/src/client/ReactDOMComponent.js
@@ -13,6 +13,7 @@ import {registrationNameModules} from 'events/EventPluginRegistry';
import warning from 'shared/warning';
import {canUseDOM} from 'shared/ExecutionEnvironment';
import warningWithoutStack from 'shared/warningWithoutStack';
+import {shorthandProperties} from '../shared/CSSProperty';
import * as DOMPropertyOperations from './DOMPropertyOperations';
import * as ReactDOMInput from './ReactDOMInput';
@@ -709,6 +710,26 @@ export function diffProperties(
if (!styleUpdates) {
styleUpdates = {};
}
+ // Check shorthand properties collision
+ if (__DEV__) {
+ if (shorthandProperties.hasOwnProperty(styleName)) {
+ const propertyGroup = shorthandProperties[styleName];
+ const overriddenProperties = [];
+ for (let lastStyleName in lastProp) {
+ if (propertyGroup.includes(lastStyleName)) {
+ overriddenProperties.push(lastStyleName);
+ }
+ }
+ if (overriddenProperties.length > 0) {
+ warning(
+ false,
+ 'Css shorthand properties collision: %s properties are being overridden. (%s)',
+ styleName,
+ overriddenProperties,
+ );
+ }
+ }
+ }
styleUpdates[styleName] = nextProp[styleName];
}
}
diff --git a/packages/react-dom/src/shared/CSSProperty.js b/packages/react-dom/src/shared/CSSProperty.js
index 7b1e4aba8b545..3590478443ef7 100644
--- a/packages/react-dom/src/shared/CSSProperty.js
+++ b/packages/react-dom/src/shared/CSSProperty.js
@@ -55,6 +55,18 @@ export const isUnitlessNumber = {
strokeWidth: true,
};
+export const shorthandProperties = {
+ background: [
+ 'backgroundAttachment',
+ 'backgroundClip',
+ 'backgroundColor',
+ 'backgroundImage',
+ 'backgroundOrigin',
+ 'backgroundPosition',
+ 'backgroundRepeat',
+ 'backgroundSize',
+ ],
+};
/**
* @param {string} prefix vendor-specific prefix, eg: Webkit
* @param {string} key style name, eg: transitionDuration