为React添加Flexbox样式的前缀

时间:2015-04-03 20:02:24

标签: css reactjs

我真的很喜欢React如何为你净化事件所以我很惊讶地发现他们也没有为你的CSS样式添加前缀!

无论如何,我开始实现我自己的基本前缀:

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;
};

但是我realized a big problem,React使用一个对象作为样式并适当地为flexbox添加前缀,你需要为值前缀,而不是属性。因此,我不能同时包含以下所有样式:

.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+ */
 }

任何想法如何解决这个问题?

3 个答案:

答案 0 :(得分:3)

嗯,实际上,通过非常小的XSS技巧,您可以轻松实现您想要的效果。不要害怕,我们不会去“黑暗面”;)

只需添加小功能,您就可以像这样编写React CSS

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' ]
  }
});

所有属性的应用顺序与数组中表示的顺序相同。酷不是吗? :)

它自己的功能非常简单

// 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;
}

工作演示

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

PS:我们使用XSS技术 - 我们不会引入任何新的安全问题。标准的XSS保护也适用于此。

答案 1 :(得分:0)

我更喜欢将我的样式放在单独的文件中并使用Autoprefixer

使用grunt和其他任务运行器进行设置非常简单,并且可以定位您想要支持的特定浏览器。它会检查caniuse数据库以保持最新状态,甚至可以从您的CSS中删除任何不必要的前缀。

它也可以作为后编译器使用less和sass。

希望有所帮助!

答案 2 :(得分:0)

自动供应商前缀已被声明为React团队不想维护的内容。这真的很有意义,每个应用程序都有不同的要求,支持哪些浏览器。根据支持的距离,问题呈指数级增长。

认为React开箱即用应该支持供应商前缀,因为仅使用内联样式就不能使用flexbox(Hello现代网络!?)。

认为对象文字语法几乎没有其他地方没有的价值,并且大多增加了样式的摩擦力。猜测它与向后兼容性支持有关,并且能够将CSS对象作为道具传递,并且不想强迫人们使用ES5 / ES6,其中可以使用模板字符串(``)语法。如果我们将+运算符与字符串一起添加到我们的变量中,那将会非常难看......但是模板文字不再需要了! (见mdn

对所有其他攻击此问题的软件包感到不满意,因此最简单的方法就是将它们全部排除在外。名为Style It的包只是让你编写CSS。同样也是自动子树范围,因此您不能使用CSS在全局名称空间中(类似于内联但不具有高特异性)。与内联样式类似,默认情况下它也是XSS安全的(使用相同的lib React使用它来逃避你的CSS),是同构的,并且在1.8kb gzip压缩时很小。哦,没有建立步骤。

npm install style-it --save

功能语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .flex-container {
        padding: 0;
        margin: 0;
        list-style: none;

        display: -webkit-box;
        display: -moz-box;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;

        -webkit-flex-flow: row wrap;
        justify-content: space-around;
      }

      .flex-item {             
        background: tomato;
        padding: 5px;
        width: 200px;
        height: 150px;
        margin-top: 10px;

        line-height: 150px;
        color: white;
        font-weight: bold;
        font-size: 3em;
        text-align: center;
      }
    `,
      <ul class="flex-container">
        <li class="flex-item">1</li>
        <li class="flex-item">2</li>
        <li class="flex-item">3</li>
        <li class="flex-item">4</li>
        <li class="flex-item">5</li>
        <li class="flex-item">6</li>
      </ul>
    );
  }
}

export default Intro;

JSX语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .flex-container {
          padding: 0;
          margin: 0;
          list-style: none;

          display: -webkit-box;
          display: -moz-box;
          display: -ms-flexbox;
          display: -webkit-flex;
          display: flex;

          -webkit-flex-flow: row wrap;
          justify-content: space-around;
       }

       .flex-item {
          background: tomato;
          padding: 5px;
          width: 200px;
          height: 150px;
          margin-top: 10px;

          line-height: 150px;
          color: white;
          font-weight: bold;
          font-size: 3em;
          text-align: center;
        }
      `}

      <ul class="flex-container">
        <li class="flex-item">1</li>
        <li class="flex-item">2</li>
        <li class="flex-item">3</li>
        <li class="flex-item">4</li>
        <li class="flex-item">5</li>
        <li class="flex-item">6</li>
      </ul>
    </Style>
  }
}

export default Intro;

HTML / CSS取自Chris Coyier的A Complete Guide to Flexbox帖子。