```css .long-text { margin-bottom: 10px; }
.clamp { -webkit-line-clamp: 5; -webkit-box-orient: vertical; display: -webkit-box; overflow: hidden; text-overflow: ellipsis; overflow-wrap: break-word; } ```
```js import { LoremIpsum } from "https://cdn.skypack.dev/lorem-ipsum@2.0.3"; import classnames from "https://cdn.skypack.dev/classnames@2.3.1"; import * as lodash from "https://cdn.skypack.dev/lodash@4.17.21";
const getText = (paragraphs) => { const lorem = new LoremIpsum(); return lorem.generateParagraphs(paragraphs); };
const ReadMoreText = ({ text }) => { const [clamped, setClamped] = React.useState(true); const [showButton, setShowButton] = React.useState(true); const containerRef = React.useRef(null); const handleClick = () => setClamped(!clamped);
React.useEffect(() => { const hasClamping = (el) => { const { clientHeight, scrollHeight } = el; return clientHeight !== scrollHeight; };
const checkButtonAvailability = () => {
if (containerRef.current) {
// Save current state to reapply later if necessary.
const hadClampClass = containerRef.current.classList.contains("clamp");
// Make sure that CSS clamping is applied if aplicable.
if (!hadClampClass) containerRef.current.classList.add("clamp");
// Check for clamping and show or hide button accordingly.
setShowButton(hasClamping(containerRef.current));
// Sync clamping with local state.
if (!hadClampClass) containerRef.current.classList.remove("clamp");
}
};
const debouncedCheck = lodash.debounce(checkButtonAvailability, 50);
checkButtonAvailability();
window.addEventListener("resize", debouncedCheck);
return () => {
window.removeEventListener("resize", debouncedCheck);
};
}, [containerRef]);
return ( <> <div ref={containerRef} className={classnames("long-text", clamped && "clamp")} > {text} </div> {showButton && ( <button onClick={handleClick}>Read {clamped ? "more" : "less"}</button> )} <br /> ); };
const App = () => { const text = getText(2); return <ReadMoreText text={text} />; };
ReactDOM.render(<App />, document.getElementById("App")); ```