Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prefixing flexbox styles for React

Tags:

css

reactjs

I really like how React purifies events for you so I was surprised to find that they dont prefix your CSS styles for your as well!

Anyways, I started implementing my own basic prefixer like this:

var prefixes = ["ms", "Moz", "Webkit", "O"];
var properties = [
  'userSelect',
  'transform',
  'transition',
  'transformOrigin',
  'transformStyle',
  'transitionProperty',
  'transitionDuration',
  'transitionTimingFunction',
  'transitionDelay',
  'borderImage',
  'borderImageSlice',
  'boxShadow',
  'backgroundClip',
  'backfaceVisibility',
  'perspective',
  'perspectiveOrigin',
  'animation',
  'animationDuration',
  'animationName',
  'animationDelay',
  'animationDirection',
  'animationIterationCount',
  'animationTimingFunction',
  'animationPlayState',
  'animationFillMode',
  'appearance',
  'flexGrow',
];


function vendorPrefix(property, value) {
  var result = {}
  result[property] = value

  if( properties.indexOf(property) == -1 ){
    return result;
  }

  property = property[0].toUpperCase() + property.slice(1);

  for (var i = 0; i < prefixes.length; i++) {
    result[prefixes[i] + property] = value;
  };

  return result;
}

React.prefix = function(obj) {
  var result = {};

  for(var key in obj){
    var prefixed = vendorPrefix(key, obj[key])
    for(var pre in prefixed){
      result[pre] = prefixed[pre]
    } 
  }
  return result;
};

But then I realized a big problem, React uses an object for styles and to appropriately prefix the flexbox, you need to prefix the values, not the properties. Thus, I cannot include all of the following styles at the same time:

.page-wrap {
  display: -webkit-box;      /* OLD - iOS 6-, Safari 3.1-6 */
  display: -moz-box;         /* OLD - Firefox 19- (buggy but mostly works) */
  display: -ms-flexbox;      /* TWEENER - IE 10 */
  display: -webkit-flex;     /* NEW - Chrome */
  display: flex;             /* NEW, Spec - Opera 12.1, Firefox 20+ */
 }

Any ideas how to get around this?

like image 714
Chet Avatar asked Apr 03 '15 20:04

Chet


People also ask

Can you use Flexbox With React?

Flexbox works the same way in React Native as it does in CSS on the web, with a few exceptions.

Can you add style to React component?

Sharing styles across many React components The style objects and the components do not have to be in the same file. We can create a separate . js file for our styles, export these styles, and then import them into the component where we want to use them.

What is inline style React?

Inline Styles In cases where you need to use other units, such as 'em' or 'rem', specify the unit with the value explicitly as a string. Applying that to the padding property should result in padding: '1.5em' . In addition, these styles are not vendor-prefixed automatically, so you have to add vendor prefixes manually.

What is Flex component in React?

Introduction. The Flex component can be used to layout its children in one dimension with flexbox. Any React Spectrum component can be used as a child, and Flex components can be nested to create more complex layouts.


1 Answers

Well, actually with really small XSS trick you can easily achive what you want. Don't be scared, we won't go to the "dark side" ;)

Just by adding small function you can write your React CSS like this

var divStyle = multipleValues({
  color: 'white',
  padding: '10px 20px',
  // if you want property to have multiple values
  // just write them all in the array
  display: [
    '-webkit-box',
    '-webkit-flex',
    '-ms-flexbox',
    'flex'
  ],
  background: ['red', 'blue'],

  extraStyles: {
    background: [ 'yellow', 'pink' ]
  }
});

All properties will apply in the same order as they represented in array. Cool isn't it? :)

The function it self is quite simple

// function that will do a "magic" XSS-ish trick
function multipleValues(style) {
  var result = {};
  // feel free to replace for..in+hasOwnProperty with for..of
  for (var key in style) { 
    if (style.hasOwnProperty(key)) {
      var value = style[key];
      if (Array.isArray(value)) {
        // by adding semicolon at the begging we applying
        // a trick that ofthen used in XSS attacks
        result[key] = ';' + key + ':' + value.join(';' + key + ':');
      } else if (typeof value === "object" && value !== null) {
        // here we doing recursion
        result[key] = multipleValues(value);
      } else {
        // and here we simply copying everything else
        result[key] = value;
      }
    }
  }
  return result;
}

Working Demo:

https://jsfiddle.net/z5r53tdh/1/

PS: event thou we using XSS technics - we don't introduce any new security issue. Standard XSS protection will also work here.

like image 128
obenjiro Avatar answered Sep 23 '22 08:09

obenjiro