Reputation: 91
I have a container size of 400wx300h. Inside the container is a single paragraph tag bind to a Textarea field. The max character that can be entered is 255. The max font size of the paragraph tag is 96px and the minimum is 28px. Now, I want to calculate the in-between font size of the paragraph based on the height of the container such that it will always stay inside the container without overflowing.
Here a simple a implementation that I came up with:
import { useEffect, useRef, useState } from "react";
export default function App() {
const [text, setText] = useState("");
const [fontSize, setFontSize] = useState(96);
const paragraph = useRef();
useEffect(() => {
let ph = paragraph.current.offsetHeight;
let noOflines = ph / fontSize;
let minFontsize = 28;
let fs = 300 / noOflines;
if (ph > 225) {
console.log("fs and nolines and text length and ph", fs, noOflines, ph);
if (fs < minFontsize) {
setFontSize(minFontsize);
} else {
setFontSize(fs);
}
}
if (fs > 96 && ph < 225 && noOflines <= 3) {
console.log("fs and nolines and text length and ph", fs, noOflines, ph);
setFontSize(96);
}
}, [text]);
return (
<div className="App" style={{ textAlign: "center" }}>
<h1>Hello CodeSandbox</h1>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
background: "red",
width: "400px",
margin: "auto",
height: "300px"
}}
>
<p
id="par"
style={{
wordBreak: "break-word",
lineHeight: 1,
textAlign: "center",
fontSize: fontSize
}}
ref={paragraph}
>
{text}
</p>
</div>
<br />
<br />
<br />
<textarea
type="text"
value={text}
onChange={(e) => {
if (e.target.value.length > 255) {
return;
}
setText(e.target.value);
}}
/>
</div>
);
}
https://codesandbox.io/s/clever-meadow-zooyo?file=/src/App.js:0-1644
It works but there is logical issue somewhere which I am unable to figure out. At certain scenario the paragraph overflows.
Upvotes: 0
Views: 367
Reputation: 564
Try change your useEffect in this way:
useEffect(() => {
let ph = paragraph.current.offsetHeight;
if (ph > 300) {
let noOflines = ph / fontSize;
let minFontsize = 28;
let fs = 300 / noOflines;
setFontSize(fs < minFontsize ? minFontsize : fs);
} else if (300 - fontSize > ph) {
let noOflines = ph / fontSize;
let fs = fontSize + fontSize / noOflines;
setFontSize(fs > 96 ? 96 : fs);
}
}, [text, fontSize]);
Upvotes: 1