데이터를 가져오는 동안 콘텐츠의 영역을 나타내는 컴포넌트로 스켈레톤 애니메이션을 화면에 노출하여 사용자의 요청을 처리하고 있다는 메시지를 줍니다.
웹 사이트 접속 시 로딩 중인 것을 알려주는 로딩바처럼 사용할 수 있습니다.
네이버 메일 스켈레톤 UI
유튜브 스켈레톤 UI
여기서 단순 콘텐츠 영역만 표시할 수도 있고 애니메이션 효과를 줄 수도 있습니다.
아래 실습은 애니메이션 효과를 넣은 컴포넌트로 만들어 보겠습니다.
const Container = () => {
const [isLoading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 5000);
}, []);
return (
<>
{isLoading ?
<Skeleton/>
: (
<li className='item-container'>
<div>
<div className='item-img'/>
</div>
<div className='item-info'>
<p className='item-info-text'>
texttexttexttexttexttexttexttexttexttexttexttexttexttexttext
</p>
<p className='item-info-text'>
texttexttexttexttexttexttexttexttexttexttexttexttexttexttext
</p>
</div>
</li>
)}
</>
)
}
const App = () => {
return <Container/>;
}
먼저 로드가 끝났을 때 보여줄 컴포넌트의 구조를 살펴 보겠습니다.
li.item-container
내 이미지, 텍스트로 구성되어 있습니다.
.item-container {
width: 500px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
margin: 30px;
border: 1px solid #ddd;
border-radius: 5px;
}
.item-container .item-img {
width: 80px;
height: 80px;
background: cadetblue;
border-radius: 50%;
}
.item-container .item-info {
width: 400px;
}
로드 후 컴포넌트
이제 스켈레톤 컴포넌트 로직을 작성해보도록 하겠습니다. 먼저, 구조는 로드 후 컴포넌트와 동일하게 짜야 합니다.
function Skeleton (){
return(
<li className='item-container-skeleton'>
<div>
<div className='item-img-skeleton'/>
</div>
<div className='item-info-skeleton'>
<p className='item-info-text-skeleton'/>
<p className='item-info-text-skeleton'/>
</div>
</li>
)
}
@keyframes loading {
0% {
transform: translateX(0);
}
100% {
transform: translateX(460px);
}
}
/* skeleton */
.item-container-skeleton {
width: 500px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px;
margin: 30px;
border: 1px solid #ddd;
border-radius: 5px;
}
.item-container-skeleton .item-img-skeleton::before {
content: '';
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(to right, #eee, #ddd, #eee);
animation: loading 2s infinite linear;
}
.item-container-skeleton .item-img-skeleton {
width: 80px;
height: 80px;
background: #eee;
border-radius: 50%;
position: relative;
overflow: hidden;
}
.item-container-skeleton .item-info-skeleton {
width: 400px;
}
.item-container-skeleton .item-info-skeleton .item-info-text-skeleton::before {
content: '';
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(to right, #eee, #ddd, #eee);
animation: loading 2s infinite linear;
}
.item-container-skeleton .item-info-skeleton .item-info-text-skeleton {
width: 100%;
height: 20px;
background: #eee;
position: relative;
overflow: hidden;
}
로드 전 컴포넌트(스켈레톤 UI)
스켈레톤 컴포넌트를 작성해주었고 애니메이션까지 적용한 후 App.js
컴포넌트에서 setTimeout
으로 3초 후 로드시킵니다.