web-dev-qa-db-fra.com

Pseudo-éléments CSS dans React

Je construis React composants. J'ai ajouté CSS en ligne dans les composants comme suggéré dans cette brillante présentation par l'un des types derrière React. Toute la nuit, j'ai essayé de trouver un moyen d'ajouter des pseudo-classes CSS en ligne, comme sur la diapositive intitulée ":: after" dans la présentation. Malheureusement, je n'ai pas seulement besoin d'ajouter la propriété content:"";, Mais aussi position:absolute; -webkit-filter: blur(10px) saturate(2);. Les diapositives montrent comment ajouter du contenu via {/* … */}, Mais comment ajouteriez-vous d'autres propriétés?

53
Michael Johansen

Vous avez une réponse de @Vjeux à l'équipe React :

Normal HTML/CSS:

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

Réagissez avec le style en ligne:

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

Le truc, c'est qu'au lieu d'utiliser ::after en CSS pour créer un nouvel élément, vous devez plutôt créer un nouvel élément via React. Si vous ne souhaitez pas ajouter cet élément partout, créez un composant qui le fait pour vous.

Pour des attributs spéciaux comme -webkit-filter, le moyen de les encoder consiste à supprimer les tirets et à mettre la lettre suivante en majuscule. Donc ça devient WebkitFilter. Notez que faire {'-webkit-filter': ...} devrait également fonctionner.

59
Michael Johansen

Les styles en ligne ne peuvent pas être utilisés pour cibler des pseudo-classes ou des pseudo-éléments. Vous devez utiliser une feuille de style.

Si vous voulez générer du CSS de manière dynamique, le moyen le plus simple est de créer un élément DOM <style>.

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

Le style en ligne ne prend pas en charge les pseudos ou les règles (par exemple, @media). Les recommandations vont de la réimplémentation de fonctionnalités CSS en JavaScript pour des états CSS tels que :hover via onMouseEnter et onMouseLeave pour utiliser plusieurs éléments afin de reproduire des pseudo-éléments tels que :after et :before simplement utiliser une feuille de style externe.

Personnellement, n'aime pas toutes ces solutions. La réimplémentation des fonctionnalités CSS via JavaScript ne s'adapte pas correctement - l'ajout de balises superflues non plus.

Imaginez une grande équipe dans laquelle chaque développeur recrée des fonctionnalités CSS telles que :hover. Chaque développeur procédera différemment, à mesure que les équipes grossissent, si cela est possible, cela sera fait. En réalité, avec JavaScript, il existe environ n moyens de réimplémenter les fonctionnalités CSS, et avec le temps, vous pouvez parier sur chacun de ces moyens mis en œuvre avec le résultat final. être le code spaghetti.

Alors que faire? Utilisez CSS. Si vous avez posé des questions sur le style en ligne, vous supposerez probablement que vous êtes dans le camp CSS-in-JS (moi aussi!). La colocalisation de HTML et de CSS a été jugée aussi utile que la colocalisation de JS et de HTML, mais beaucoup de gens ne le réalisent pas encore (la colocation JS-HTML a eu beaucoup de résistance également au début).

Faites une solution dans cet espace appelée Style It qui permet simplement d’écrire du texte brut en CSS dans vos composants React. Il n’est pas nécessaire de perdre des cycles en réinventant le CSS dans JS. le bon travail, voici un exemple en utilisant :after:

npm install style-it --save

Syntaxe fonctionnelle ( 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;

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

Exemple de coeur tiré de CSS-Tricks

10
Joshua Robinson

Pas une réponse directe à la question, mais cela pourrait aider ceux qui ont du mal à créer des informations style à l'aide de TypeScript.

J'avais une erreur en me disant que ce qui suit était incorrect:

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

L'erreur m'a dit que "les types de biens 'position' sont incompatibles". Je ne sais pas pourquoi.

J'ai corrigé cela en ajoutant une déclaration TypeScript stricte, comme ceci:

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

Cela marche.

1
Stuart Aitken