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
Want to Add "Addeventlistener" on Multiple Elements With Same Class
Changing Nav-Bar Color After Scrolling
How to Prevent JavaScript Injection Attacks Within User-Generated Html
Bootstrap Close Responsive Menu "On Click"
JavaScript Get Element by Name
How to Get the Onclick Calling Object
Convert HTML to Data:Text/Html Link Using JavaScript
How to Make a Jquery "$.Post" Request Synchronous
Conditionally Load JavaScript File
Any Way to Clone Html5 Canvas Element With Its Content
Adding an Onclick Event to a Table Row
Typeerror: P.Easing[This.Easing] Is Not a Function
What Is JavaScript'S Highest Integer Value That a Number Can Go to Without Losing Precision