استكشف في مدونة أوعي وشك عالم الابتكار

اكتشف الحلول المتطورة في تطبيقات الأجهزة المحمولة والتكنولوجيا والتعليم وموضوعات بلوجر. كن على اطلاع دائم بمقالات الخبراء والموارد الإبداعية والأدوات القوية لتعزيز مشاريعك الرقمية.

آخر الأخبار

إنشاء خط زمني عمودي باستخدام CSS ولمسة من JavaScript

الجداول الزمنية باستخدامcss توفر حلًا مثاليًا لعرض المعلومات الزمنية بطريقة جذابة وسهلة الفهم مع الحفاظ على أداء الموقع وسرعته.
Timeline

فوائد استخدام الجدول الزمني (Timeline) باستخدام CSS

HTML CSS JavaScript
📊 تحسين تجربة المستخدم (UX)
  • تقديم المعلومات بطريقة زمنية مرتبة ومنطقية
  • تسهيل فهم التسلسل الزمني للأحداث
  • جعل المحتوى أكثر جاذبية وتنظيمًا
⚙️ فوائد تقنية
  • أداء عالي: لا يحتاج إلى مكتبات خارجية أو JavaScript معقد
  • سرعة التحميل: تأثيرات CSS أخف من الصور أو الفيديوهات
  • سهولة الصيانة: تعديل المحتوى دون الحاجة لتغيير الهيكل الأساسي
🎨 فوائد تصميمية
  • مرونة في التصميم: يمكن تخصيص الشكل والألوان بسهولة
  • تأثيرات بصرية جذابة: حركات وتغيرات عند التحويم أو التمرير
  • تنسيق متسق: مظهر موحد لجميع العناصر
📱 فوائد للتوافقية
  • تجاوب كامل: يعمل على جميع أحجام الشاشات
  • توافق مع المتصفحات: يدعمه جميع المتصفحات الحديثة
  • إمكانية الوصول: يمكن تحسينه لذوي الاحتياجات الخاصة
💻 فوائد للتطوير
  • سهولة التنفيذ: لا يحتاج لمهارات برمجة متقدمة
  • إعادة الاستخدام: يمكن استخدام النموذج لمشاريع متعددة
  • تحديثات سهلة: إضافة أو حذف عناصر دون التأثير على التصميم

🔍 حالات الاستخدام الشائعة:

سير ذاتية (CV)
تاريخ الشركات
خطط المشاريع
أحداث تاريخية
مسارات تعليمية
جداول إطلاق المنتجات

الجداول الزمنية باستخدام CSS توفر حلًا مثاليًا لعرض المعلومات الزمنية بطريقة جذابة وسهلة الفهم مع الحفاظ على أداء الموقع وسرعته.

شرح الجدول الزمني العمودي (Vertical Timeline)

البنية الأساسية (HTML)

قسم المقدمة (Intro Section)
<section class="intro">
  <div class="container">
    <h1>Vertical Timeline>
  </div>
</section>
  • يعرض عنوان رئيسي مع سهم لأسفل
  • يحتوي على رابط للإصدار السابق من الجدول الزمني
قسم الجدول الزمني (Timeline Section)
<section class="timeline">
  <ol>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1934</time>
        </div>
        <div class="details">
          <h6>Heading Here</h6>
          <p>Content here...</p>
        </div>
      </div>
    </li>
    <!-- عناصر أخرى مماثلة -->
  </ol>
</section>
  • يستخدم قائمة مرتبة (<ol>) لتمثيل العناصر الزمنية
  • كل عنصر زمني (<li>) يحتوي على:
    • قسم للوقت (time-wrapper) يعرض السنة
    • قسم للتفاصيل (details) يعرض العنوان والمحتوى

التنسيقات (CSS Styles)

المتغيرات العامة
:root {
  --red: #f45b69;
  --dark-blue: #227c9d;
  --turquoise: #17c3b2;
  --white: #fff;
}
  • تعريف ألوان ثابتة لإعادة استخدامها
تنسيق الخط الزمني الأساسي
.timeline ol {
  position: relative;
  list-style: none;
}

.timeline ol::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
  background: var(--turquoise);
}
  • إنشاء خط عمودي على الجانب الأيسر يمثل الخط الزمني
  • إزالة علامات القائمة الافتراضية
تأثيرات الرسم
.timeline ol li .time-wrapper::before,
.timeline ol li .time-wrapper::after {
  content: "";
  position: absolute;
  background: var(--turquoise);
}

.timeline ol li .time-wrapper::before {
  /* خط أفقي */
}

.timeline ol li .time-wrapper::after {
  /* دائرة صغيرة */
}
  • إنشاء خط أفقي ودائرة صغيرة لكل عنصر زمني

تأثيرات الحركة (Animations)

الحالة الأولية (قبل الظهور)
.timeline ol li time,
.timeline ol li .details > * {
  opacity: 0;
}

.timeline ol li time {
  transform: translateY(-30px);
}

.timeline ol li .details > * {
  transform: translateY(30px);
}
  • إخفاء المحتوى في البداية
  • تحريك العناصر لأعلى أو لأسفل
الحالة النشطة (عند الظهور)
.timeline ol li.in-view .time-wrapper::before {
  width: 120px; /* توسيع الخط الأفقي */
}

.timeline ol li.in-view .time-wrapper::after {
  transform: scale(1.5); /* تكبير الدائرة */
}

.timeline ol li.in-view time,
.timeline ol li.in-view .details > * {
  opacity: 1;
  transform: none; /* إعادة العناصر لمكانها */
}
  • تأثيرات متتابعة مع تأخير زمني:
    1. الخط الأفقي أولاً
    2. ثم الدائرة
    3. ثم التاريخ
    4. ثم العنوان
    5. وأخيراً المحتوى

جافاسكريبت (JavaScript)

كود المراقبة (Intersection Observer)
const targets = document.querySelectorAll(".timeline ol li");
const observer = new IntersectionObserver(callback, { threshold: 0.5 });

function callback(entries) {
  entries.forEach(entry => {
    if (entry.intersectionRatio >= 0.5) {
      entry.target.classList.add("in-view");
      observer.unobserve(entry.target);
    } else {
      entry.target.classList.remove("in-view");
    }
  });
}

targets.forEach(target => observer.observe(target));
  • يراقب متى يصبح كل عنصر زمني مرئياً بنسبة 50% أو أكثر
  • يضيف/يزيل كلاس in-view لتفعيل/إلغاء تأثيرات الحركة
  • يتوقف عن المراقبة بعد تفعيل الحركة للمرة الأولى
فوائد هذا التصميم
  • تجربة مستخدم جذابة: تأثيرات حركية متتابعة تجعل التصفح ممتعاً
  • تصميم نظيف: استخدام مساحات بيضاء وخطوط واضحة
  • سهولة التخصيص: يمكن تغيير الألوان والمسافات بسهولة
  • أداء عالي: استخدام CSS للحركات بدلاً من JavaScript
  • تجاوب كامل: يعمل على جميع أحجام الشاشات
الكــود كاملا

<section class="timeline">
  <ol>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1934</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1937</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>Proin quam velit, efficitur vel neque vitae, rhoncus commodo mi. Suspendisse finibus mauris et bibendum molestie. Aenean ex augue, varius et pulvinar in, pretium non nisi.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1940</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>Proin iaculis, nibh eget efficitur varius, libero tellus porta dolor, at pulvinar tortor ex eget ligula. Integer eu dapibus arcu, sit amet sollicitudin eros.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1943</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1946</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1956</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>Proin iaculis, nibh eget efficitur varius, libero tellus porta dolor, at pulvinar tortor ex eget ligula. Integer eu dapibus arcu, sit amet sollicitudin eros</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1967</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>1985</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>Proin iaculis, nibh eget efficitur varius, libero tellus porta dolor, at pulvinar tortor ex eget ligula. Integer eu dapibus arcu, sit amet sollicitudin eros</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>2000</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>In mattis elit vitae odio posuere, nec maximus massa varius. Suspendisse varius volutpat mattis. Vestibulum id magna est.</p>
        </div>
      </div>
    </li>
    <li>
      <div class="item-inner">
        <div class="time-wrapper">
          <time>2012</time>
        </div>
        <div class="details">
          <h3>Heading Here</h3>
          <p>Proin iaculis, nibh eget efficitur varius, libero tellus porta dolor, at pulvinar tortor ex eget ligula. Integer eu dapibus arcu, sit amet sollicitudin eros</p>
        </div>
      </div>
    </li>
  </ol>

</section>
    

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap");

:root {
  --red: #f45b69;
  --dark-blue: #227c9d;
  --turquoise: #17c3b2;
  --white: #fff;
}

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

a {
  color: inherit;
}

body {
  font: normal 16px/1.5 "Inter", sans-serif;
  padding-bottom: 50px;
}

/* INTRO SECTION
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.intro {
  color: var(--white);
  background: var(--red);
  padding: 100px 0;
}

.container {
  width: 90%;
  max-width: 1200px;
  margin: 0 auto;
  text-align: center;
}

h1 {
  font-size: 2.5rem;
}

/* TIMELINE
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.timeline {
  padding: 50px 20px;
  margin: 0 auto;
  max-width: 1000px;
  color: var(--dark-blue);
}

.timeline ol {
  position: relative;
  list-style: none;
}

.timeline ol::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3px;
  height: 100%;
  background: var(--turquoise);
}

.timeline ol li .item-inner {
  padding: 20px 180px;
  margin-bottom: 8vh;
}

.timeline ol li .time-wrapper {
  position: relative;
  font-size: 4.5rem;
  font-weight: bold;
  line-height: 0.9;
}

.timeline ol li .time-wrapper::before,
.timeline ol li .time-wrapper::after {
  content: "";
  position: absolute;
  background: var(--turquoise);
}

.timeline ol li .time-wrapper::before {
  top: 50%;
  left: -180px;
  transform: translateY(-50%);
  width: 0;
  height: 3px;
  transition: width 0.8s linear;
}

.timeline ol li .time-wrapper::after {
  top: calc(50% - 8px);
  left: -60px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  transform: scale(0);
  transform-origin: left center;
  transition: all 0.4s linear;
}

.timeline ol li time,
.timeline ol li .details > * {
  opacity: 0;
  transition: 0.5s;
}

.timeline ol li time {
  display: inline-block;
  transform: translateY(-30px);
}

.timeline ol li .details > * {
  transform: translateY(30px);
}

.timeline ol li .details h3 {
  font-size: 2rem;
  line-height: 1;
  margin: 15px 0;
}

/* ANIMATION STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */

.timeline ol li.in-view .time-wrapper::before {
  width: 120px;
}

.timeline ol li.in-view .time-wrapper::after {
  transition-delay: 0.8s;
  transform: scale(1.5);
}

.timeline ol li.in-view time,
.timeline ol li.in-view .details > * {
  opacity: 1;
  transform: none;
}

.timeline ol li.in-view time {
  transition-delay: 1.3s;
}

.timeline ol li.in-view .details h3 {
  transition-delay: 1.5s;
}

.timeline ol li.in-view .details p {
  transition-delay: 1.7s;
}

/* MQ STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
@media (max-width: 700px) {
  .timeline ol li .item-inner {
    padding: 20px 40px;
  }

  .timeline ol li .time-wrapper::before {
    display: none;
  }

  .timeline ol li .time-wrapper::after {
    left: -45px;
    transform-origin: center;
  }

  .timeline ol li.in-view .time-wrapper::after {
    transition-delay: 0s;
  }

  .timeline ol li.in-view time {
    transition-delay: 0.5s;
  }

  .timeline ol li.in-view .details h3 {
    transition-delay: 0.7s;
  }

  .timeline ol li.in-view .details p {
    transition-delay: 0.9s;
  }
}

/* FOOTER STYLES
–––––––––––––––––––––––––––––––––––––––––––––––––– */
.page-footer {
  position: fixed;
  right: 0;
  bottom: 20px;
  display: flex;
  align-items: center;
  padding: 5px;
  background: rgba(255, 255, 255, 0.65);
}

.page-footer a {
  display: flex;
  margin-left: 4px;
}
    

const targets = document.querySelectorAll(".timeline ol li");
const threshold = 0.5;
const ANIMATED_CLASS = "in-view";

function callback(entries, observer) {
  entries.forEach((entry) => {
    const elem = entry.target;
    if (entry.intersectionRatio >= threshold) {
      elem.classList.add(ANIMATED_CLASS);
      observer.unobserve(elem);
    } else {
      elem.classList.remove(ANIMATED_CLASS);
    }
  });
}

const observer = new IntersectionObserver(callback, { threshold });
for (const target of targets) {
  observer.observe(target);
}
    
معــايـنة
كيف كان المقال؟

كاتب المقال

wesam elngar
إنشاء قالب مدونة هو شغفي، الفكرة الإبداعية لإنشاء قالب تأتي من هواية

🌟 انتبه عزيزي أعضاء المجتمع! 🌟
نحن متحمسون لمشاركتك في مناقشاتنا الديناميكية. لضمان بيئة محترمة وشاملة للجميع، نطلب تعاونكم مع الإرشادات التالية:
1. احترام الخصوصية: يرجى عدم مشاركة معلومات حساسة أو شخصية في تعليقاتك.
2. انشر الإيجابية: نحن نتمسك بسياسة عدم التسامح مطلقًا مع خطاب الكراهية أو اللغة المسيئة. دعونا نحافظ على محادثاتنا محترمة وودية.
3. اللغة المفضلة: لا تتردد في التعبير عن نفسك باللغة الإنجليزية أو العربية. ستساعدنا هاتان اللغتان في الحفاظ على مناقشة واضحة ومتماسكة.
4. احترام التنوع: لتعزيز جو شامل، نطلب منك بكل احترام تجنب مناقشة المسائل الدينية في تعليقاتك.
تذكر أن مساهماتك قيمة، ونحن نقدر التزامك بجعل مجتمعنا مكانًا ترحيبيًا للجميع. دعونا نواصل التعلم والنمو معًا من خلال المناقشات البناءة والاحترام المتبادل.
شكرًا لكونك جزءًا من مجتمعنا اوعي وشك! 🌟

إرسال تعليق