use Css Var (React)
Set, get and remove a
CSS custom property
from the comfort of a React component. This could result in slightly more
performant code when you're setting the style
property directly since React
will re-run your component fewer times.
import { useMemo, useEffect } from 'react'
type UseCssVarProps = {
name: `--${string}`
root?: HTMLElement
}
type CssVarControls = {
set: (value: string) => void
get: () => string
remove: () => void
}
const defaultRoot = typeof document !== 'undefined' ? document.body : undefined
export const useCssVar = ({
name,
root = defaultRoot!,
}: UseCssVarProps): CssVarControls => {
const controls: CssVarControls = useMemo(
() => ({
set: value => root.style.setProperty(name, value),
get: () => root.style.getPropertyValue(name),
remove: () => root.style.removeProperty(name),
}),
[name, root]
)
useEffect(() => {
return () => controls.remove()
}, [controls])
return controls
}
import { useMemo, useEffect } from 'react'
const defaultRoot = typeof document !== 'undefined' ? document.body : undefined
export const useCssVar = ({ name, root = defaultRoot }) => {
const controls = useMemo(
() => ({
set: value => root.style.setProperty(name, value),
get: () => root.style.getPropertyValue(name),
remove: () => root.style.removeProperty(name),
}),
[name, root]
)
useEffect(() => {
return () => controls.remove()
}, [controls])
return controls
}
Info
-
We use
useMemo
, so that if you follow hook rules and use the helpers in a function inside auseEffect
,useCallback
, etc, you won't have code (re-)running unnecessarily. -
If you don't want the variable to be removed when the hook is no longer used, you can either remove the
useEffect
, or add an extra prop and conditionally return a cleanup function in theuseEffect
. -
This hook doesn't use
useState
since it would nullify the performance aspect, and I didn't feel the need to be notified when the variable changed on the root. You could useMutationObserver
if you wanted to know if the variable was updated on theroot
.
Demo
If you open up your browser's devtools, find the <main>
element and look at
its style
attribute, you'll see the --example-css-var
CSS
variable change as you change the input's value or press the button.
The image's rotation is handled by styling it with transform:
rotate(calc(var(--example-css-var, 45) * 1deg))
.