CSS React 中的伪元素

CSS pseudo elements in React

我正在 React components. I have added CSS inline in the components as suggested in this brilliant presentation 由 React 背后的一位开发人员构建。我整晚都在尝试寻找一种内联添加 CSS 伪 类 的方法,就像演示文稿中标题为“::after”的幻灯片一样。不幸的是,我不仅需要添加 content:""; 属性,还需要添加 position:absolute; -webkit-filter: blur(10px) saturate(2);。幻灯片显示了如何通过 {/* … */} 添加内容,但是您将如何添加其他属性?

内联样式不能用于定位伪类 或伪元素。您需要使用样式表。

如果要动态生成CSS,那么最简单的方法就是创建一个DOM元素<style>.

<style dangerouslySetInnerHTML={{
  __html: [
     '.my-special-div:after {',
     '  content: "Hello";',
     '  position: absolute',
     '}'
    ].join('\n')
  }}>
</style>
<div className='my-special-div'></div>

React 团队@Vjeux 的回复:

正常HTML/CSS:

<div class="something"><span>Something</span></div>
<style>
    .something::after {
    content: '';
    position: absolute;
    -webkit-filter: blur(10px) saturate(2);
}
</style>

使用内联样式作出反应:

render: function() {
    return (
        <div>
          <span>Something</span>
          <div style={{position: 'absolute', WebkitFilter: 'blur(10px) saturate(2)'}} />
        </div>
    );
},

诀窍在于,与其在 CSS 中使用 ::after 来创建新元素,不如通过 React 创建新元素。如果你不想在任何地方都添加这个元素,那么制作一个组件来为你做这件事。

对于像 -webkit-filter 这样的特殊属性,对其进行编码的方法是删除破折号 - 并将下一个字母大写。于是就变成了WebkitFilter。请注意,{'-webkit-filter': ...} 也应该有效。

内联样式不支持伪造或 at 规则(例如,@media)。建议范围从通过 onMouseEnteronMouseLeave 为 CSS 状态(如 :hover)重新实现 JavaScript 中的 CSS 功能,到使用更多元素来重现伪元素像 :after:before 一样只使用外部样式表。

个人不喜欢所有这些解决方案。通过 JavaScript 重新实现 CSS 功能并不能很好地扩展——添加多余的标记也不行。

想象一个大型团队,其中每个开发人员都在重新创建 CSS 个功能,例如 :hover。每个开发人员 以不同的方式来做,随着团队规模的扩大,如果可以做到,就会做到。事实是 JavaScript 有大约 n 种方法可以重新实现 CSS 功能,随着时间的推移,您可以打赌这些方法中的每一种都会得到最终结果是意大利面条代码。

那怎么办?使用 CSS。当然,如果您询问内联样式,假设您可能属于 CSS-in-JS 阵营(我也是!)。发现 HTML 和 CSS 与 JS 和 HTML 并置一样有价值,很多人还没有意识到这一点(JS-HTML 并置有很多一开始也很抗拒)。

在这个 space 中提出了一个名为 Style It 的解决方案,它只允许您在 React 组件中写入明文 CSS。无需浪费周期在 JS 中重新发明 CSS。正确的工具适合正确的工作,这里是一个使用 :after:

的例子

npm install style-it --save

函数语法 (JSFIDDLE)

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

class Intro extends React.Component {
  render() {
    return Style.it(`
      #heart {
        position: relative;
        width: 100px;
        height: 90px;
      }
      #heart:before,
      #heart:after {
        position: absolute;
        content: "";
        left: 50px;
        top: 0;
        width: 50px;
        height: 80px;
        background: red;
        -moz-border-radius: 50px 50px 0 0;
        border-radius: 50px 50px 0 0;
        -webkit-transform: rotate(-45deg);
        -moz-transform: rotate(-45deg);
        -ms-transform: rotate(-45deg);
        -o-transform: rotate(-45deg);
        transform: rotate(-45deg);
        -webkit-transform-origin: 0 100%;
        -moz-transform-origin: 0 100%;
        -ms-transform-origin: 0 100%;
        -o-transform-origin: 0 100%;
        transform-origin: 0 100%;
      }
      #heart:after {
        left: 0;
        -webkit-transform: rotate(45deg);
        -moz-transform: rotate(45deg);
        -ms-transform: rotate(45deg);
        -o-transform: rotate(45deg);
        transform: rotate(45deg);
        -webkit-transform-origin: 100% 100%;
        -moz-transform-origin: 100% 100%;
        -ms-transform-origin: 100% 100%;
        -o-transform-origin: 100% 100%;
        transform-origin :100% 100%;
      }
    `,
      <div id="heart" />
    );
  }
}

export default Intro;

JSX 语法 (JSFIDDLE)

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

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        #heart {
          position: relative;
          width: 100px;
          height: 90px;
        }
        #heart:before,
        #heart:after {
          position: absolute;
          content: "";
          left: 50px;
          top: 0;
          width: 50px;
          height: 80px;
          background: red;
          -moz-border-radius: 50px 50px 0 0;
          border-radius: 50px 50px 0 0;
          -webkit-transform: rotate(-45deg);
          -moz-transform: rotate(-45deg);
          -ms-transform: rotate(-45deg);
          -o-transform: rotate(-45deg);
          transform: rotate(-45deg);
          -webkit-transform-origin: 0 100%;
          -moz-transform-origin: 0 100%;
          -ms-transform-origin: 0 100%;
          -o-transform-origin: 0 100%;
          transform-origin: 0 100%;
        }
        #heart:after {
          left: 0;
          -webkit-transform: rotate(45deg);
          -moz-transform: rotate(45deg);
          -ms-transform: rotate(45deg);
          -o-transform: rotate(45deg);
          transform: rotate(45deg);
          -webkit-transform-origin: 100% 100%;
          -moz-transform-origin: 100% 100%;
          -ms-transform-origin: 100% 100%;
          -o-transform-origin: 100% 100%;
          transform-origin :100% 100%;
        }
     `}

      <div id="heart" />
    </Style>
  }
}

export default Intro;

心形示例取自CSS-Tricks

不是问题的直接答案,但这可能会帮助那些在使用 Typescript 创建 style 信息时遇到问题的人。

我收到一条错误消息,告诉我以下内容不正确:

let iconStyle = {
    position: 'relative',
    maxHeight: '90px',
    top: '25%',
}

错误告诉我"types of property 'position' are incompatible"。我不知道为什么。

我通过添加严格的 Typescript 声明来修复此问题,如下所示:

let iconStyle: CSSProperties = {
    position: 'relative',
    maxHeight: '90px',
    top: '25%',
}

这有效。

您可以使用带样式的组件。

使用 npm i styled-components

安装
import React from 'react';
import styled from 'styled-components';

const YourEffect = styled.div`
  height: 50px;
  position: relative;
  &:after {
    // whatever you want with normal CSS syntax. Here, a custom orange line as example
    content: '';
    width: 60px;
    height: 4px;
    background: orange
    position: absolute;
    bottom: 0;
    left: 0;
  },

const YourComponent = props => {
  return (
    <YourEffect>...</YourEffect>
  )
}

export default YourComponent

根据您是否只需要对几个属性进行内联样式设置,您可以执行类似此解决方案的操作(这样您就不必安装特殊包或创建额外元素):

<span class="something" datacustomattribute="">
  Hello
</span>
.something::before {
  content: attr(datascustomattribute);
  position: absolute;
}

请注意 datacustomattribute 必须以 data 开头且全部小写以满足 React。

我不知道这是否会被认为是 hacky,但它确实有效(使用 CSS 变量):

const passedInlineStyle = { '--color':'blue'}

然后在导入的 CSS 文件中:

background:var(--color);