1. 특정 라인 수 이상일 경우 ellipsis 처리하기
일반적으로 아래의 CSS 속성들을 이용해 다중 줄수 ...(ellipsis) 처리를 한다.
overflow: hidden;
word-break: normal;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
overflow: hidden;
요소의 내용이 자신의 상자를 벗어날 경우, 초과된 부분을 숨김으로 처리
word-break: normal;
단어의 줄 바꿈을 일반적인 방식으로 처리.
긴 단어가 요소의 너비를 벗어날 경우, 단어의 일부를 다음 줄로 옮기지 않고, 단어 전체를 다음 줄로 이동
text-overflow: ellipsis;
요소의 텍스트가 요소의 너비를 초과하는 경우, 초과된 텍스트를 생략 부호(…)로 표시
display: -webkit-box;
요소를 블록 레벨 상자로 표시하며, 내부의 자식 요소들을 유연하게 배치하기 위해 사용
-webkit- 접두어
과거 웹킷(WebKit) 기반 브라우저에서의 사용을 위한 것
-webkit-line-clamp: 5;
브라우저의 웹킷 엔진에서 사용되며, 표시하고자 하는 텍스트의 줄 수를 지정
이 예시에서는 최대 5줄까지 표시하고 그 이상의 내용은 생략 부호로 표시
-webkit-box-orient: vertical;
브라우저의 웹킷 엔진에서 사용되며, 요소 내의 블록 레벨 상자들의 배치 방향을 수직(세로)으로 설정
Ellipsis 처리하려는 태그의 CSS 속성값은 위와같이 지정한다.
import styled from 'styled-components'
...
return (
<Box>
...
<EllipsisText>
텍스트를 매우 많이 넣어주세요.
</EllipsisText>
...
</Box>
)
...
const EllipsisText = styled.div`
overflow: hidden;
word-break: normal;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
`;
2. ellipsis 처리된 text 더보기/접기 버튼을 이용해보기
1) ellipsis를 제어할 상태를 만든다. 총 3가지의 상태를 만들어 구현했다. (방법은 다양함)
1. textRef: 텍스트의 길이변화에 따라 높이를 감지하는 역활
2. hasEllipsis: Eliipisis의 유무 상태 핸들링
3. isExpanded: "더보기" / "접기" 상태 핸들링
- hasEllipsis는 텍스트가 ellipsis되는 경우 나타나는 "더 보기" or "접기" 버튼이 활성화되어지는 상태이다.
2) text-overflow가 ellipsis가 되었을 경우를 탐지하는 방법
scrollHeight: 텍스트영역(안보이는 부분을 포함) 이 차지하고 있는 높이
offsetHeight: 현재 보이는 텍스트영역이 차지하고 있는 높이
scrollHeight(전체 텍스트 영역높이) > offsetHeight(보이는 텍스트영역높이) = 텍스트오버플로우 발생
결과
전체코드
import React, { useState, useEffect, useRef } from 'react';
import styled from 'styled-components';
const TEXT = `텍스트를 매우 많이 넣어주세요.텍스트를 매우 많이 넣어주세요.텍스트를
매우 많이 넣어주세요.텍스트를 매우 많이 넣어주세요.텍스트를 매우 많이
넣어주세요.텍스트를 매우 많이 넣어주세요.텍스트를 매우 많이
넣어주세요.텍스트를 매우 많이 넣어주세요.텍스트를 매우 많이
넣어주세요.`
export function App(props) {
const textRef = useRef(null);
const [isExpanded, setIsExpanded] = useState(false);
const [hasEllipsis, setHasEllipsis] = useState(false);
const checkEllipsis = () => {
if (textRef.current) {
const { scrollHeight, offsetHeight } = textRef.current || {};
// scrollHeight: 실제 컨텐츠 영역의 높이
// offsetHeight: 엘리먼트의 전체크기(패딩, 보더 스크롤바 사이즈포함)
const _hasEllipsis = scrollHeight > offsetHeight;
if (_hasEllipsis) { // ellipsis 일경우
setHasEllipsis(true);
}
else { // ellipsis 아닐경우
setIsExpanded(false); // "더보기" 버튼상태 초기화
setHasEllipsis(false); // ellipsis 상태 초기화
}
}
};
const onClickReadMore = () => {
setIsExpanded(prev => !prev);
};
useEffect(() => {
checkEllipsis();
window.addEventListener('resize', checkEllipsis);
return () => {
window.removeEventListener('resize', checkEllipsis);
};
}, [textRef]);
return (
<>
{isExpanded ? ( // "더보기 클릭 했을 경우"
<p ref={textRef}>
{TEXT}
</p>
) : ( // "기본 텍스트"
<EllipsisText ref={textRef}>
{TEXT}
</EllipsisText>
)}
{hasEllipsis && (
<button type='button' onClick={onClickReadMore}>
{isExpanded ? '접기' : '더 보기'}
</button>
)}
</>
);
}
const EllipsisText = styled.p`
overflow: hidden;
word-break: normal;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
`;
'JavaScript > React' 카테고리의 다른 글
| ContextAPI 사용자 정의 훅이 있는 팩토리패턴 (0) | 2024.04.10 |
|---|---|
| window.scroll smooth 크로스브라우징 이슈 (0) | 2023.03.30 |
| [React] 리액트 성능 최적화 TODO (0) | 2023.01.14 |
| [React] 리액트 Checkbox 상태관리 (0) | 2023.01.03 |