Issue
I saw it on the Airbnb website. The skeleton would show, then the icons and images will be displayed individually. I would like to know how this is done.
Can anyone explain how this can be done? Code examples are fine too. Is there any library that makes this easy?
Curious in particular how to do this in React.
What I have in mind is to have a setTimeout
function that shows each component per tick.
Solution
This is mostly a CSS challenge. The logic part is simply to pass from a loader to actual data. I created a simple working example below so you get a general idea:
function App() {
const [user, setUser] = React.useState(null);
React.useEffect(() => {
fetch("https://randomuser.me/api/")
.then((res) => res.json())
// The setTimeout is there so you see the animation longer.
.then((data) => setTimeout(() => setUser(data.results[0]), 2000));
}, []);
return (
<div>
{!user ? (
<div className="user skeleton">
<div className="avatar"></div>
<div>
<div className="line"> </div>
<div className="line"></div>
</div>
</div>
) : (
<div className="user">
<img className="avatar" src={user.picture.medium} alt="" />
<div>
<div className="line"> {user.name.first + " " + user.name.last}</div>
<div className="line">{user.email}</div>
</div>
</div>
)}
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
#root{
min-height:100vh;
display:grid;
place-items:center;
}
.user {
background:rgb(250, 250, 250);
border-radius:1rem;
display: flex;
width:fit-content;
margin:auto;
align-items: center;
gap: 1rem;
padding: 1rem;
}
.user .avatar {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 50%;
}
.user.skeleton .avatar{
background-image: linear-gradient(90deg, #ddd 0px, #e8e8e8 40px, #ddd 80px);
}
.user .line {
margin-block: 0.5rem;
padding: 0 0.5rem;
}
.user.skeleton .line {
background-image: linear-gradient(90deg, #ddd 0px, #e8e8e8 40px, #ddd 80px);
animation: bg-lines 2s infinite linear;
border-radius: 1rem;
min-width: 200px;
min-height: 1rem;
}
@keyframes bg-lines {
0% {
background-position: -100px;
}
100% {
background-position: 140px;
}
}
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
Answered By - yousoumar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.