How to define css variables in style attribute in React and typescript
ReactjsTypescriptJsxTsxReactjs Problem Overview
I want to define jsx like this:
<table style={{'--length': array.lenght}}>
<tbody>
<tr>{array}</tr>
</tbody>
</table>
and I use --length in CSS, I also have cells that have --count that shows count using CSS pseudo selector (using the counter hack).
but typescript throws error:
TS2326: Types of property 'style' are incompatible.
Type '{ '--length': number; }' is not assignable to type 'CSSProperties'.
Object literal may only specify known properties, and ''--length'' does not exist in type 'CSSProperties'.
is it possible to change type of style attribute to accept CSS variable (custom properties) or is there a way to force any on style object?
Reactjs Solutions
Solution 1 - Reactjs
Like this:
function Component() {
const style = { "--my-css-var": 10 } as React.CSSProperties;
return <div style={style}>...</div>
}
Or without the extra style
variable:
function Component() {
return <div style={{ "--my-css-var": 10 } as React.CSSProperties} />
}
Solution 2 - Reactjs
If you go to the definition of CSSProperties
, you'll see:
export interface CSSProperties extends CSS.Properties<string | number> {
/**
* The index signature was removed to enable closed typing for style
* using CSSType. You're able to use type assertion or module augmentation
* to add properties or an index signature of your own.
*
* For examples and more information, visit:
* https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors
*/
}
That link gives examples of how to solve the type error by augmenting the definition of Properties
in csstype
or casting the property name to any
.
Solution 3 - Reactjs
You could add a type assertion to the variable. i.e. {['--css-variable' as any]: value }
<table style={{['--length' as any]: array.lenght}}>
<tbody>
<tr>{array}</tr>
</tbody>
</table>
Solution 4 - Reactjs
Casting the style
to any
defeats the whole purpose of using TypeScript, so I recommend extending React.CSSProperties
with your custom set of properties:
import React, {CSSProperties} from 'react';
export interface MyCustomCSS extends CSSProperties {
'--length': number;
}
By extending React.CSSProperties
, you will keep TypeScript's property checking alive and you will be allowed to use your custom --length
property.
Using MyCustomCSS
would look like this:
const MyComponent: React.FC = (): JSX.Element => {
return (
<input
style={
{
'--length': 300,
} as MyCustomCSS
}
/>
);
};
Solution 5 - Reactjs
you can simply put this module declaration merge using string templates at the top of the file or in any .d.ts file, then you will be able to use any CSS variable as long it starts '--' and that is string or number
import 'react';
declare module 'react' {
interface CSSProperties {
[key: `--${string}`]: string | number
}
}
for example
<div style={{ "--value": percentage }} />
Solution 6 - Reactjs
import "react";
type CustomProp = { [key in `--${string}`]: string };
declare module "react" {
export interface CSSProperties extends CustomProp {}
}
put this in your global.d.ts file
Solution 7 - Reactjs
I would like to add a different approach by using document.body.style.setProperty
, and maybe if your css variable will be affected by certain props you can put it in a useEffect
like this:
useEffect(() => {
document.body.style.setProperty(
"--image-width-portrait",
`${windowSize.width - 20}px`
);
}, [windowSize])
Later inside your css file you can call it like this:
width: var(--image-width-portrait);