I'm building React components. I have added CSS inline in the components as suggested in this brilliant presentation by one of the people behind React. I've been trying all night to find a way to add CSS pseudo classes inline, like on the slide titled "::after" in the presentation. Unfortunately, I do not just need to add the content:"";
property, but also position:absolute; -webkit-filter: blur(10px) saturate(2);
. The slides show how to add content through {/* … */}
, but how would you add other properties?
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.
::after
-element, to create a custom shadow, just for styling purposes I wouldn't be in the DOM when Google sees it, but with this approach, Google will see it... Meaning you will have two headlines. –
Fount -webkit-user-select: "text"
then I saw react is not accepting this as a style so I found that i should use webkitUserSelect
–
Roselba Inline styles cannot be used to target pseudo-classes or pseudo-elements. You need to use a stylesheet.
If you want to generate CSS dynamically, then the easiest way is to create a DOM element <style>
.
<style
dangerouslySetInnerHTML={{
__html: `
.my-special-div:after {
content: "Hello";
position: absolute
}
`
}}
></style>
<div className="my-special-div"></div>
Depending if you only need a couple attributes to be styled inline you can do something like this solution (and saves you from having to install a special package or create an extra element):
https://stackoverflow.com/a/42000085
<span class="something" datacustomattribute="👋">
Hello
</span>
.something::before {
content: attr(datascustomattribute);
position: absolute;
}
Note that the datacustomattribute
must start with data
and be all lowercase to satisfy React.
data-custom-attribute
works too –
Selfinterest Inline styling does not support pseudos or at-rules (e.g., @media). Recommendations range from reimplement CSS features in JavaScript for CSS states like :hover
via onMouseEnter
and onMouseLeave
to using more elements to reproduce pseudo-elements like :after
and :before
to just use an external stylesheet.
Personally dislike all of those solutions. Reimplementing CSS features via JavaScript does not scale well -- neither does adding superfluous markup.
Imagine a large team wherein each developer is recreating CSS features like :hover
. Each developer will do it differently, as teams grow in size, if it can be done, it will be done. Fact is with JavaScript there are about n ways to reimplement CSS features, and over time you can bet on every one of those ways being implemented with the end result being spaghetti code.
So what to do? Use CSS. Granted you asked about inline styling going to assume you're likely in the CSS-in-JS camp (me too!). Have found colocating HTML and CSS to be as valuable as colocating JS and HTML, lots of folks just don't realise it yet (JS-HTML colocation had lots of resistance too at first).
Made a solution in this space called Style It that simply lets your write plaintext CSS in your React components. No need to waste cycles reinventing CSS in JS. Right tool for the right job, here is an example using :after
:
npm install style-it --save
Functional Syntax (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 Syntax (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;
Heart example pulled from CSS-Tricks
You can use styled components.
Install it with npm i styled-components
import React from 'react';
import styled from 'styled-components';
const ComponentWithPseudoClass = 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 (
<ComponentWithPseudoClass>...</ComponentWithPseudoClass>
)
}
export default YourComponent
I don't know if this would be considered hacky but it certainly works (using CSS variable):
const passedInlineStyle = { '--color':'blue'}
Then in an imported CSS file:
background:var(--color);
The easiest trick is to add '""'
instead of ''
in the content
property for the pseudo-element.
const styles = {
container: {
// ... Container styling
'&::after': {
display: 'block',
content: '""'
}
}
};
Not a direct answer to the question, but this may help those who are having trouble creating style
information using Typescript.
I was getting an error telling me that the following was incorrect:
let iconStyle = {
position: 'relative',
maxHeight: '90px',
top: '25%',
}
The error told me that "types of property 'position' are incompatible". I have no idea why.
I fixed this by adding a strict Typescript declaration, like so:
let iconStyle: CSSProperties = {
position: 'relative',
maxHeight: '90px',
top: '25%',
}
This works.
© 2022 - 2024 — McMap. All rights reserved.