```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"));
```