Css Pseudo Elements in React

CSS pseudo elements in React

Got a reply from @Vjeux over at the React team:

Normal HTML/CSS:

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

React with inline style:

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

The trick is that instead of using ::after in CSS in order to create a new element, you should instead create a new element via React. If you don't want to have to add this element everywhere, then make a component that does it for you.

For special attributes like -webkit-filter, the way to encode them is by removing dashes - and capitalizing the next letter. So it turns into WebkitFilter. Note that doing {'-webkit-filter': ...} should also work.

React JS and css pseudo element ::after ::before

className JSX attribute is a string variable, which will be set as the class attribute value on the HTML element when it will be rendered by React. CSS pseudo elements can appear in CSS code, not as a class name for a HTML element.

So you need to give a class name to your button using className JSX attribute, then define CSS rules for this class. To do so you need to choose a strategy to setup CSS in your React app. There is multiple solutions :

  • use a plain old CSS file imported in your index.js or index.html
  • use a plain old style element in your index.html (these 2 options are global, like in plain old 90's web development)
  • use JSX "style" attribute : <Component style={{here put CSS object}} /> : https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
  • use CSS modules (if you are using create-react-app) : https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
  • use styled-components or any other CSS-in-JS option, there is a lot of solutions, I mention styled-components since it is one of the most popular

With all of these options you will be able to use CSS pseudo-element. For SASS you may have to setup a CSS preprocessor. If you are using create-react-app (https://create-react-app.dev/docs/adding-a-sass-stylesheet/) or styled-components (https://styled-components.com/docs/faqs#can-i-nest-rules) you're good to go, it's build in. Well for styled-components I'm not sure if it is a true full SASS support though.

Good luck with that !

How to put React.Component to CSS content property (in :before/:after pseudo-elements)?

If you need to use styled-components (or any other CSS-in-JS library) with an icon from react-icons (or any other library that exports a React.Component which renders an <svg> element), I see the only one way: to transform a component to an url() with a markup string because only this way you can pass an image to content property in your case. For that transformation, you need: React.createElement(), ReactDOMServer.renderToStaticMarkup() and encodeURIComponent(). Also, you can use Base64 instead.

This one works (CodeSandbox):

import { createElement } from "react";
import { render } from "react-dom";
import { renderToStaticMarkup } from "react-dom/server";
import styled from "styled-components";
import { Link } from "gatsby";
import { FaArrowRight } from "react-icons/fa";

window.___loader = { enqueue: () => {}, hovering: () => {} };

const reactSvgComponentToMarkupString = (Component, props) =>
`data:image/svg+xml,${encodeURIComponent(
renderToStaticMarkup(createElement(Component, props))
)}`;

const FooLink = styled(Link)`
${({ color }) => color && `color: ${color};`}
&:after {
content: ${({ color }) =>
`url(${reactSvgComponentToMarkupString(FaArrowRight, {
color
})})`};
position: absolute;
opacity: 0;
}

&:hover:after {
opacity: 1;
}
`;

render(
<>
<div>
<FooLink to="/test1" color="red">
Link with arrow (red)
</FooLink>
</div>
<div>
<FooLink to="/test2">Link with arrow (default)</FooLink>
</div>
</>,
document.getElementById("root")
);

Thanks to this Github Gist.

Can Reactjs programmatically handle :before?

Pseudo elements cannot be styled with inline styles as explained in https://stackoverflow.com/a/14141821/368697. You will have to style the something class name in a stylesheet with the .something:before selector. This is not a limitation of React but rather a design choice for HTML + CSS.

If you need to programmatically change the width of the pseudo :before element, it is probably more appropriate as a regular DOM element rendered by React.



Related Topics



Leave a reply



Submit