العناصر النائبة

يمكن أن يكون إنشاء العناصر النائبة لمحتوى الصفحة في بعض الأحيان أمرًا بسيطًا مثل إضافة تأثير خلفية إلى عناصر الصفحة الحالية. في هذا المثال، تشترك جميع عناصر القائمة في نفس بنية HTML الأساسية. ومع ذلك، يتم تصميم العناصر النائبة بخلفية رمادية تستخدم الرسوم المتحركة من CSS لإنشاء تأثير تحميل وامض.

وبناءً على طريقة تنفيذ عناصر صفحتك، قد تحتاج أيضًا إلى ضبط CSS قليلاً لضمان استمرار العناصر النائبة في شغل مساحة على الرغم من عدم احتوائها على محتوى. وغالبًا ما يكون ذلك على شكل إضافة خصائص width أو height إلى عناصر الصفحة الحالية. على سبيل المثال، في هذا المثال، تؤدي إضافة height: 1.5em إلى .text-container إلى ضمان بقاء العنصر النائب الخاص به مرئيًا على الرغم من عدم احتوائه على أي نص.

HTML

<div class="grid">
    <div class="item">
        <div class="image-container">
            <img src="hats.jpg">
        </div>
        <div class="text-container">Hats</div>
    </div>
    <div class="item empty">
        <div class="image-container">
            <img src="">
        </div>
        <div class="text-container">Watches</div>
    </div>
    <div class="item empty">
        <div class="image-container">
            <img src="">
        </div>
        <div class="text-container"></div>
    </div>
    <div class="item empty">
        <div class="image-container">
            <img src="">
        </div>
        <div class="text-container"></div>
    </div>
    <div class="item empty">
        <div class="image-container">
            <img src="">
        </div>
        <div class="text-container"></div>
    </div>
    <div class="item empty">
        <div class="image-container">
            <img src="">
        </div>
        <div class="text-container"></div>
    </div>
</div>

CSS


        :root {
    --placeholder-primary: #eeeeee;
    --placeholder-secondary: #cccccc;
}
.grid {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1em;
    width: 100%;
    max-width: 650px;
    margin: 1em 0;
}
.item {
    display: grid;
    gap: .5em;
    width: 200px;
}
.text-container {
    font-size: 1em;
    height: 1.5em;
    text-align: center;
    font-weight: bold;
}
.image-container {
    width: 200px;
    height: 200px;;
    animation: placeholder ease-in-out 2s infinite;
}
.image-container img {
    width: 100%;
}
@keyframes placeholder {
    0% {
        background-color: var(--placeholder-primary);
    }
    50% {
        background-color: var(--placeholder-secondary);
    }
    100% {
        background-color: var(--placeholder-primary);
    }
}
@keyframes fadeIn {
    0% {
        opacity: 0%;
    }
    100% {
        opacity: 100%;
    }
}
.item.loaded .image-container {
    animation: none;
}
.item.loaded .image-container img{
    animation: fadeIn linear .5s;
}
        

JS


        const data = [
    {
        description: "Watches",
        // 
        // src: "https://web-dev.imgix.net/image/j2RDdG43oidUy6AL6LovThjeX9c2/GMPpoERpp9aM5Rihk5F2.jpg"
    },
    {
        description: "Shirt",
        src: "shirt.jpg"
    },
    {
        description: "Shorts",
        src: "shorts.jpg"
    },
    {
        description: "Sunglasses",
        src: "sunglasses.jpg"
    },
    {
        description: "Shoes",
        src: "shoes.jpg"
    }
];
document.querySelectorAll(".item.empty").forEach((el, index) => {
    if (data[index]) {
        el.classList = "item loaded";
        el.querySelector("img").src = data[index].src;
        el.querySelector(".text-container").innerHTML = data[index].description;
    }
});