[UI/UX]Skeleton UIアプリケーション


ウィンドウを単調にロードしないで、ユーザーフレンドリーなSkeleton UIを使用してユーザーの離脱率を減らします.

Skeleton UIとは?


skeleton UIは、実際のデータをレンダリングする前に表示する画面の輪郭を最初に描画するロードアニメーションです.
ユーザーの流出を防ぎ、「何かが見える」という効果を事前にユーザーに伝える.
既存のSpinerよりもユーザに近く,ユーザ離脱率も小さい.

2.実施


Skeleton Item


まず,Skeleton UIを適用するコンテンツに共通するItemを定義する.
CS animationにより、一定時間、背景色の透明度を繰り返し変化させる.
import styled from 'styled-components';

const SkeletonItem = styled.div`
  width: 100%;
  height: 30px;
  background-color: #f2f2f2;
  position: relative;
  overflow: hidden;
  border-radius: 4px;

  @keyframes skeleton-gradient {
    0% {
      background-color: rgba(165, 165, 165, 0.1);
    }
    50% {
      background-color: rgba(165, 165, 165, 0.3);
    }
    100% {
      background-color: rgba(165, 165, 165, 0.1);
    }
  }

  &:before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    animation: skeleton-gradient 1.5s infinite ease-in-out;
  }
`;

export default SkeletonItem;

Card Skeleton


前に定義したSkeleton Itemを使用して、投稿カードのSkeleton UIを実現します.
import styled from 'styled-components';
import SkeletonItem from './components/SkeletonItem';

interface Props {}

const CardSkeleton = (props: Props) => {
  return (
    <Wrapper>
      {new Array(6).fill('').map((_, i) => (
        <Card key={i}>
          <Title />
          <Content />
          <Bottom>
            <Circle />
            <Title />
          </Bottom>
        </Card>
      ))}
    </Wrapper>
  );
};

const Wrapper = styled.ul`
  ...
`;

const Card = styled.li`
  ...
`;

const Title = styled(SkeletonItem)``;

const Content = styled(SkeletonItem)`
  height: 130px;
`;

const Bottom = styled.div`
  display: flex;
  gap: 12px;
`;

const Circle = styled(SkeletonItem)`
  width: 35px;
  height: 30px;
  border-radius: 50%;
  background-color: #f2f2f2;
  position: relative;
  overflow: hidden;
`;

export default CardSkeleton;

既存の構成部品を再使用するLayout


Skeleton UIは、適用するコンポーネントとできるだけ似たような優れたユーザー体験を提供します.ただし、既存のコンポーネントのデザインを変更した場合は、毎回Skeleton UIを変更する必要があります.
これを改善するために、PostCardと汎用レイアウトモジュール化されたLayoutsを導入し、必要な素子を再使用して再パッケージした.
import styled from 'styled-components';
import SkeletonItem from './components/SkeletonItem';
import { Layouts as S } from 'components/common/PostCard/Layouts';

interface Props {}

const PostCardSkeleton = (props: Props) => {
  return (
    <S.Wrapper>
      {new Array(6).fill('').map((_, i) => (
        <CardSkeleton key={i}>
          <Title />
          <Content />
          <Bottom>
            <Circle />
            <Title />
          </Bottom>
        </CardSkeleton>
      ))}
    </S.Wrapper>
  );
};

const CardSkeleton = styled(S.PostCard)`
  gap: 20px;
  cursor: default;
`;

const Title = styled(SkeletonItem)``;

const Content = styled(SkeletonItem)`
  height: 130px;
`;

const Bottom = styled.div`
  display: flex;
  gap: 12px;
`;

const Circle = styled(SkeletonItem)`
  width: 35px;
  height: 30px;
  border-radius: 50%;
  background-color: #f2f2f2;
  position: relative;
  overflow: hidden;
`;

export default PostCardSkeleton;

3.結果


レンダリングするコンテンツを事前に描画することで、ユーザーは現在ロードされていることを認識し、ロード時間をより友好的に受け入れることができます.

リファレンス


https://ui.toast.com/weekly-pick/ko_20201110