개발자

React 아코디언 효과 구현하기

2023년 11월 30일조회 355

다음과 같이 transition 속성을 적용하여 <Header> 컴포넌트를 클릭했을때, <ContentsWrapper> 컴포넌트가 아코디언 처럼 서서히 펼쳐지고, 접히는 효과를 구현하고 싶습니다. isOpen이 true가 되어 펼쳐지는 효과는 정상적으로 구현되는데, 접히는 효과가 안나타나고 한번에 사라집니다. transition 속성을 어떻게 적용하면 될까요?

1const Container = styled.div`
2  margin-left: 20px;
3`;
4
5const Header = styled.div`
6  width: 250px;
7  height: 30px;
8  margin-top : 20px;
9  margin-bottom: 20px;
10  border-radius: 4px;
11  cursor: pointer;
12`;
13
14const ContentsWrapper = styled.div<{ isOpen: boolean }>`
15  width: inherit;
16  padding: 0 15px 0 15px;
17  overflow: hidden;
18  height: ${({ isOpen }) => (isOpen ? "auto" : "0")};
19  margin-top: ${({ isOpen }) => (isOpen ? "20px" : "0")};
20  max-height: ${({ isOpen }) => (isOpen ? "1000px" : "0")};
21
22  transition: height 1s ease, max-height 1s ease, margin-top 1s ease; 
23`;
24
25const Contents = styled.div`
26  padding: 0 15px 0 15px;
27`;
28
29const TestReportOpinion = ({
30  reportAnswerList,
31  positionIndex,
32  question,
33  kind,
34}: {
35  reportAnswerList: reportAnswerList;
36  positionIndex: number;
37  question: string;
38  kind: number;
39}) => {
40
41  const [isOpen, setIsOpen] = useState(true);
42
43  const handleButtonClick = () => {
44    setIsOpen((prev) => !prev);
45  };
46
47return(
48<Container>
49      <Header onClick={handleButtonClick}>
50        <p style={{ width: "400px" }}>
51          {t(question)}
52          <Caretdown style={{ marginLeft: "6px" }} rotate={isOpen ? 0 : 180}/>
53        </p>
54      </Header>
55      <ContentsWrapper isOpen={isOpen}>
56			<Contents>
57          		<>
58            		<TableRow>
59              			<Th width={162} height={44}>
60                			{t("등급")}
61              			</Th>
62              			<Th width={570} height={44}>
63                			{t("의견")}
64              			</Th>
65              			<Th width={125} height={44}>
66                			{t("평가")}
67              			</Th>
68            		</TableRow>
69					...
70				</>
71      </ContentsWrapper>
72</Container>
73)
이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.

답변 1

문정동개발자님의 프로필 사진

css의 transition은 값이 고정적일때만 동작합니다. ( px,em,rem등) 하지만 부모 요소에 맞게 동적으로 설정해야하는 경우가 많은데 그런 경우는 max-height와 같은 속성을 이용해서 구현 가능합니다. 자세한 설명은 아래 링크를 참고하시면 좋을것같습니다. https://stackoverflow.com/questions/3508605/how-can-i-transition-height-0-to-height-auto-using-css

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

AI 답변
커리어리 AI 봇 프로필 이미지

커리어리 AI 봇

GPT가 달아주는 답변입니다.

2023년 11월 30일

React에서 트랜지션을 사용하여 아코디언이 접힐 때 서서히 사라지는 효과를 적용하려면, height의 변화와 함께 `opacity`를 사용해볼 수 있습니다. 이 경우 'ContentsWrapper'의 styled-components 정의에 다음과 같이 추가하면 됩니다: ```jsx const ContentsWrapper = styled.div<{ isOpen: boolean }>` ... opacity: ${({ isOpen }) => (isOpen ? "1" : "0")}; transition: height 1s ease, max-height 1s ease, margin-top 1s ease, opacity 1s ease; `; ``` 다만 위 방법은 내용이 많고 wrapper의 높이가 큰 경우, max-height가 즉시 변경되므로 전체 효과가 원하는대로 실행되지 않을 수 있습니다. 높이(height)를 `'auto'`와 `'0px'`로 변경하면서 애니메이션을 작동시키는 것은 어렵습니다(`'auto'`는 이전 특정 값으로부터 점진적으로 변경되는 것을 계산할 수 없기 때문입니다). 따라서 대신에 `maxHeight` 속성을 실제 필요한 최대 높이 값으로 설정하고(1000px 등), 그 값을 기반으로 열림/닫힘 상태를 전환합니다. 아래처럼 코드를 수정해보세요. ```jsx const ContentsWrapper = styled.div<{ isOpen: boolean }>` ... max-height: ${({ isOpen }) => (isOpen ? "1000px" : "0")}; transition: max-height 1s ease-in-out; `; ``` 이렇게 수정하면, 확장 및 축소가 좀 더 자연스럽게 보일 것입니다. 하지만 `max-height` 값은 컨텐츠의 실제 최대 높이보다 항상 크거나 같아야 합니다. 그렇지 않으면 컨텐츠 일부가 잘릴 수 있습니다.

목록으로

지금 가입하면 모든 질문의 답변을 볼 수 있어요!