Let's assume your card component is like this
function Card({ name }) {
return (
<div className="card">
<div className="card__pic"></div>
<h3 className="card__name" ref={nameRef}>
{name}
</h3>
</div>
);
}
All we need is the element containing the name i.e "card__name".
- Access the 'name' element.
To access this name element, we have to use useRef
hook. Here's how you would use it.
function Card({ name }) {
const nameRef = useRef(null);
useEffect(() => {
// nameRef.current is accessible here
}, []);
return (
<div className="card">
<div className="card__pic"></div>
<h3 className="card__name" ref={nameRef}>
{name}
</h3>
</div>
);
}
We have to pass ref={refVariable}
to the element we'd like to access.
The refVariable
will be initialized with the element node after mount i.e we can use it inside the useEffect
hook.
- Determine if the name is overflowing.
Now since we have the element, we can use it to check if the text inside is overflowing. I've created a function isTextOverflowingCard
to which we pass the reference to the element we get after mount. It will return true if it text is overflowing else false.
function isTextOverflowingCard(textElement) {
if (textElement.scrollWidth > textElement.clientWidth) {
return true;
}
return false;
}
Now inside Card we can use this function and based on its return value, add a class conditionally which will have the tight letter-spacing value.
function Card({ name }) {
const nameRef = useRef(null);
const [textOverflow, setTextOverflow] = useState(false);
useEffect(() => {
// nameRef.current is accessible here
setTextOverflow(isTextOverflowingCard(nameRef.current));
}, []);
return (
<div className="card">
<div className="card__pic"></div>
<h3 className={`card__name ${textOverflow ? 'card__name--tight-kerning' : ''}`} ref={nameRef}>
{name}
</h3>
</div>
);
}
In CSS,
.card__name--tight-kerning {
letter-spacing: -2px;
}
You can change useEffect to useLayoutEffect, which is better suited for such dom related calculations and applying to ui.
References:
- Detect if text has overflown
- useEffect vs useLayoutEffect
- https://reactjs.org/docs/hooks-reference.html#useref