skip to Main Content

I am trying to add the Read more action on the same line as the cut off text after ‘x’ lines. Right now it is displaying below the cut off text.

<p style={{ overflow: 'hidden', display: '-webkit-box', 
-webkit-line-clamp: 4, line-clamp: 4, -webkit-box-orient: 'vertical' 
}}>
   Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
   do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
   Ut enim ad minim veniam, quis nostrud exercitation ullamco 
   laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
   dolor in reprehenderit in voluptate velit esse cillum dolore eu 
   fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 
   proident, sunt in culpa qui officia deserunt mollit anim id est 
   laborum.
</p>
<Button>Read more</Button>

I am able to handle to functionality where it toggles the text by changing the overflow prop to visible/hidden. I am just trying to style it in a way where the Read more is always on the last line in place of the ellipsis.

This currently cuts is off at 4 lines which is correct, but wanting to replace the ellipsis with the Read more button.

Any help is appreciated

enter image description here

2

Answers


  1. Place the button inside the paragraph tag so it is a part of the text flow. Then you’ll need to use some CSS to properly position the button during truncation.

    <div style={{ position: 'relative' }}>
        <p style={{ overflow: 'hidden', display: '-webkit-box', 
                    -webkit-line-clamp: 4, line-clamp: 4, 
                    -webkit-box-orient: 'vertical', marginBottom: '0' 
                  }}>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed 
            do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
            Ut enim ad minim veniam, quis nostrud exercitation ullamco 
            laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
            dolor in reprehenderit in voluptate velit esse cillum dolore eu 
            fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 
            proident, sunt in culpa qui officia deserunt mollit anim id est 
            laborum.
            <span style={{ position: 'absolute', right: 0, bottom: 0 }}>
                <Button>Read more</Button>
            </span>
        </p>
    </div>
    

    Creating a custom function:

    import React, { useState, useRef, useEffect } from 'react';
    const EllipsisText = ({ children, maxLine, lineHeight }) => {
      const textRef = useRef();
      const [readMore, setReadMore] = useState(false);
      const [text, setText] = useState(children);
      const maxTextHeight = maxLine * lineHeight;
      useEffect(() => {
        if (textRef.current) {
          if (textRef.current.scrollHeight > textRef.current.offsetHeight) {
            setReadMore(true);
            let trimLength = children.length * (maxTextHeight / textRef.current.scrollHeight);
            setText(children.substring(0, trimLength - 3) + '...'); 
          }
        }
      }, [children, maxTextHeight]);
    
      return (
        <div style={{ position: 'relative', lineHeight: `${lineHeight}px` }}>
          <p ref={textRef} style={{ maxHeight: maxTextHeight, overflow: 'hidden' }}>
            {text}
          </p>
          {readMore && (
            <button style={{ position: 'absolute', right: 0, bottom: 0 }} onClick={() => setReadMore(false)}>
              Read more
            </button>
          )}
        </div>
      );
    };
    
    const App = () => {
      const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
    
      return (
        <div>
          <EllipsisText maxLine={4} lineHeight={16}>
            {text}
          </EllipsisText>
        </div>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
  2. Here’s an example:

    import { useState, useRef, useEffect } from 'react';
    
    const ClampTextWithReadMore = ({ text, maxLines }) => {
      const [isClamped, setIsClamped] = useState(false);
      const textRef = useRef(null);
    
      useEffect(() => {
        if (textRef.current) {
          const computedStyle = window.getComputedStyle(textRef.current);
          const lineHeight = parseInt(computedStyle.lineHeight);
          const maxHeight = maxLines * lineHeight;
    
          if (textRef.current.scrollHeight > maxHeight) {
            setIsClamped(true);
          }
        }
      }, [text, maxLines]);
    
      const toggleClamp = () => {
        setIsClamped(!isClamped);
      };
    
      return (
        <div style={{ position: 'relative' }}>
          <p
            ref={textRef}
            style={{
              overflow: isClamped ? 'hidden' : 'visible',
              display: '-webkit-box',
              WebkitLineClamp: maxLines,
              WebkitBoxOrient: 'vertical',
              maxHeight: isClamped ? `${maxLines * 1.2}em` : 'none', // Adjust as needed
            }}
          >
            {text}
          </p>
          {isClamped && (
            <button style={{ position: 'absolute', bottom: 0, right: 0 }} onClick={toggleClamp}>
              Read more
            </button>
          )}
        </div>
      );
    };
    
    // Usage
    <ClampTextWithReadMore text={/* Your text here */} maxLines={4} />;
    

    This code snippet uses useRef to access the DOM element containing the text and calculates if the text is clamped based on the maximum height. If the text is clamped, it conditionally renders the "Read more" button positioned at the bottom right of the clamped area. Clicking the button toggles the clamped state.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search