청년을 구해줘!에서 메인 페이지 카드 슬라이더를 만들고 있다. 눌렀을 때 어떻게 이동시킬지 굉장히 고민이 많았다🤔 카드를 어떻게 옮기지? 싶었다.
하나의 카드 안에는 이미지, 텍스트, 하트 수가 들어간다.
카드의 왼쪽과 오른쪽에 검은색 선이 나타난다. div를 겹쳤을 때 나타나는 현상이다.
이를 해결할 수 있는 방법은 3가지이다.
::after
를 쓴다.const Card = ({ backgroundImg = tmpImg, title, likeNum }: CardProps) => {
let navigate = useNavigate();
return (
<StyledCard onClick={() => navigate('/detail')} backgroundImg={backgroundImg}>
<StyledTitleContainer>
<StyledTitle>{title}</StyledTitle>
<StyledLikeNumContainer>
<BlueHeart />
<StyledLikeNum>{likeNum}</StyledLikeNum>
</StyledLikeNumContainer>
</StyledTitleContainer>
</StyledCard>
);
};
(styled-components를 쓰면 이름이 길어지고 태그 색이 다 똑같아서 분간하기 어렵다.)
Card
를 갖고 있는 CardSlider
를 만든다.
StyledCardConatiner
보다 길다. return (
<section>
<StyledCardConatiner>
<StyledCardSlider
slideIndex={slideIndex}
todaySubscriptionsLength={todaySubscriptions.length}
>
{todaySubscriptions.map((todaySubscription) => (
<Card
key={todaySubscription.id}
title={todaySubscription.houseName}
likeNum={todaySubscription.likeNum}
/>
))}
</StyledCardSlider>
</StyledCardConatiner>
점의 개수는 가져온 데이터의 개수와 같게 만들었다.
<StyledDotsContainer>
{Array.from({ length: todaySubscriptions.length }).map((item, index) => (
<StyledDot
key={`${index}-${item}`}
active={slideIndex === index}
onClick={() => onDotClick(index)}
/>
))}
</StyledDotsContainer>
점 하나를 누를 때마다 slideIndex
state를 변경해서, 이 state에 비례하게 움직이게 한다. Card
자체가 움직이는 것이 아니라 StyledCardSlider
가 움직인다.
const StyledCardSlider = styled.div<{ slideIndex: number; todaySubscriptionsLength: number }>`
height: 100%;
display: flex;
transition: all 1s ease;
transform: translateX(
${(props) =>
props.slideIndex * -CARD_WIDTH + (CARD_WIDTH * (props.todaySubscriptionsLength - 1)) / 2}vw
);
`;
${(props) => props.slideIndex * -CARD_WIDTH
이렇게 하면 슬라이더가 화면 중앙에서 시작한다. 반면 지금 나와있는 코드처럼 작성하면 슬라이더의 시작 위치가 맨 앞으로 바뀐다.
이것보다는 Image와 Dot을 분리하여 같은 선에 두고 absoulte, relative의 관계로 위치를 잡은 다음에 transform
을 지정하는 것이 좋다. 다 만들어뒀는데 브랜치를 지워버렸다... 😇
참고로 calc *
을 계산할 때는 px이 여러 번 들어가면 계산이 되지 않는다.
예) calc(24px * 3)
🙆♀️ // calc(24px * 3px)
🙅♀️
카드 위에 움직였을 때 스크롤하면 transformX가 바뀐다.
StyledCardSlider
를 포함하고 있는 StyledCardConatiner
컴포넌트에 overflow-x: scroll
을 추가하여 스크롤 기능을 만든다. -webkit-overflow-scrolling
는 모바일 화면에서 스크롤이 잘 동작하지 않아서 추가하였다. none;
3가지는 스크롤을 숨기는 것이다.
const StyledCardConatiner = styled.div`
width: 100%;
overflow-x: scroll; // PC
-webkit-overflow-scrolling: touch; // mobile
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
&::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
}
`;
스크롤될 때마다 active된 dot의 색을 변경시킬 수 있다. 지금 이 상태에서 하는 것보다 absoulte, relative의 관계로 바꿔서 하는 게 훨씬 편하다. 아니면 수식이 아주 더러워진다. 스크롤되었을 때 sliceIndex
를 바꾸고, dot이 눌렸을 때만 transformX가 변경되게 하면 된다.