Placeholder shimmer animation
Placeholder shimmer animation
by Csaba Hellinger
HTML
<div id="app"></div>
CSS
body {
background: #111;
padding: 3vw;
font-family: Helvetica, sans-serif;
}
.item {
border: 1px solid #fff;
color: #fff;
padding: 4vw;
margin-bottom: 1vw;
display: grid;
grid-template-areas:
"img title"
"img sub"
"img .";
grid-template-columns: min-content 1fr;
grid-template-rows: min-content;
}
.item-image {
grid-area: img;
background: pink;
width: 15vw;
height: 15vw;
margin-right: 4vw;
}
.item-title {
grid-area: title;
margin-bottom: 1vw;
font-size: 1.2rem;
font-weight: 700;
}
.item-sub {
grid-area: sub;
}
React
const LOAD_DELAY = 6000;
const people = [
{ id: 1, name: 'Gipsz Jakab', job: 'Ablakjavító' },
{ id: 2, name: 'Óh Pál', job: 'Drágaköves' },
{ id: 3, name: 'Óh Teréz', job: 'Színesfém gyűjtő' }
];
const Item = ({ title, sub, isLoaded }) => {
if (!isLoaded) {
return (
<svg viewBox="0 0 100 25">
<defs>
<mask id="mask" x="0" y="0" width="100" height="30">
<rect x="0" y="0" width="100" height="25" stroke="#fff" fill="#000" />
<rect x="5" y="5" width="15" height="15" fill="#fff" />
<rect x="25" y="5" width="25" height="5" fill="#fff" />
<rect x="25" y="12" width="45" height="3" fill="#fff" />
</mask>
<linearGradient id="gradient" x1="99%" y1="59%" x2="1%" y2="41%">
<stop offset="0%" stopColor="#fff1" />
<stop offset="35%" stopColor="#fff1" />
<stop offset="50%" stopColor="#fff2" />
<stop offset="65%" stopColor="#fff1" />
<stop offset="100%" stopColor="#fff1" />
<animateTransform attributeName="gradientTransform"
type="translate"
from="-1 0"
to="1 0"
begin="0s"
dur="2s"
repeatCount="indefinite"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="100" height="30" fill="url(#gradient)" stroke="none" mask="url(#mask)" />
</svg>
);
}
return (
<div className="item">
<div className="item-image"></div>
<div className="item-title">{title}</div>
<div className="item-sub">{sub}</div>
</div>
);
};
const App = () => {
const [isLoaded, setLoaded] = React.useState(false);
React.useEffect(() => {
setTimeout(() => setLoaded(true), LOAD_DELAY);
},[]);
return (
<React.Fragment>
{people.map(person =>
<Item
key={person.id}
title={person.name}
sub={person.job}
...