지식 정리 📝

기존의 Loding Bar -> Skeleton UI 교체

엄성준 2023. 11. 20. 15:27

기존의 Loding bar로 표현되었던 걸 Skeleton UI를 직접 구현하여서 교체하였다.

교체 한 이유는 기존의 Loading Bar보다 사용자에게 좀 더 자연스러운 UI를 보여주고 싶어서입니다.

아래는 제가 직접 구현 한 코드입니다.

<Container>
      <Wrapper>
        {Array.from({ length: 6 }).map((_, index) => {
          return (
            <Box key={index}>
              <ImgBox />
              <ContentBox>
                <ItemBox>
                  <div>
                    <TopBox />
                    <BottomBox />
                  </div>
                  <img style={{ scale: '0.7' }} src={arrowImg} alt="arrowImg" />
                  <div>
                    <TopBox />
                    <BottomBox />
                  </div>
                </ItemBox>
                <ItemBox style={{ marginTop: '1.5rem' }}>
                  <div>
                    <TopBox />
                    <BottomBox />
                  </div>
                  <div>
                    <TopBox />
                    <BottomBox />
                  </div>
                </ItemBox>
                <PriceBox>
                  <div />
                </PriceBox>
                <CommentBox>
                  <div />
                  <div />
                </CommentBox>
                <ButtonBox>
                  <div />
                </ButtonBox>
              </ContentBox>
            </Box>
          );
        })}
      </Wrapper>
    </Container>
const loading = keyframes`{
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 1;
  }
}`;

const Container = styled.div`
  padding-top: 27rem;
  width: 100%;
  display: flex;
  justify-content: center;
`;

const Wrapper = styled.div`
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;

  @media screen and (max-width: 599px) {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
  }
`;

const Box = styled.div`
  width: 35rem;
  height: 50rem;
  border: 1px solid rgb(217, 217, 217);
  border-radius: 18px;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;

  @media screen and (max-width: 599px) {
    width: 90%;
  }
`;

const ImgBox = styled.div`
  height: 17rem;
  background: #f4f4f4;
  background-size: 200% 100%;
  animation: ${loading} 2.5s infinite;
`;

const ContentBox = styled.div`
  padding: 25px 25px 30px;
`;

const ItemBox = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;

  & > div {
    width: 33%;
    display: flex;
    flex-direction: column;
    gap: 1rem;
  }
`;

const TopBox = styled.div`
  height: 1.5rem;
  border-radius: 1rem;
  background: #f4f4f4;
  background-size: 200% 100%;
  animation: ${loading} 2.5s infinite;
`;

const BottomBox = styled.div`
  height: 3rem;
  background: #f4f4f4;
  background-size: 200% 100%;
  animation: ${loading} 2.5s infinite;
`;

const PriceBox = styled.div`
  display: flex;
  justify-content: flex-end;
  margin-top: 2rem;

  & > div {
    width: 12rem;
    height: 3.5rem;
    border-radius: 1rem;
    background: #f4f4f4;
    background-size: 200% 100%;
    animation: ${loading} 2.5s infinite;
  }
`;

const CommentBox = styled.div`
  margin-top: 2rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;

  & > div {
    height: 1.3rem;
    border-radius: 1rem;
    background: #f4f4f4;
    background-size: 200% 100%;
    animation: ${loading} 2.5s infinite;
  }

  & > div:first-child {
    width: 13rem;
  }

  & > div:last-child {
    width: 17rem;
  }
`;

const ButtonBox = styled.div`
  display: flex;
  justify-content: center;
  height: 4rem;
  margin-top: 2rem;

  & > div {
    width: 100%;
    border-radius: 1rem;
    background: #f4f4f4;
    background-size: 200% 100%;
    animation: ${loading} 2.5s infinite;
  }
`;​