اذهب إلى المحتوى

مكون البطاقة Card ومكون الشرائح الدوارة Carousel في بوتستراب


حسام برهان

سنتعرّف في هذا الدرس على مكوّنين جديدين من مكوّنات بوتستراب 5، وهما مكوّن البطاقة Card، ومكوّن الشرائح الدوّارة Carousel. ومن ثمّ سنطبّق ما سنتعلّمه هنا في متابعة عملنا في إكمال تصميم موقع "نبيه".

سنعمل في هذا الدرس على:

  • التعرّف على مكوّن البطاقة Card في بوتستراب.
  • التعرّف على مكوّن الشرائح الدوّارة Carousel في بوتستراب.
  • إنجاز قسم الدورات الأكثر مبيعًا Best Selling.
  • إنجاز القسم الخاص بأصناف الدورات Course Categories.
  • أيقونات Bootstrap 5
  • إنجاز قسم التذييل Footer.

هذا الفصل جزء من سلسلة فصول عن بوتستراب 5، وإليك كامل فهرس السلسلة:

التعرف على مكون البطاقة Card في بوتستراب

لمكوّن البطاقة Card في بوتستراب استخدامات متعدّدة. فغالبًا ما يُستخدم عندما نود توضيح أو وصف شيء محدّد، كوصف منتج ما مثلًا، أو وصف صنف كامل من من المنتجات.في درسنا هذا سنستخدم مكوّن البطاقة لوصف دورة محدّدة يقدّمها موقع نبيه، وأيضًا لتصنيف مجالات الدورات التي تُقدّم في الموقع. بُنيت البطاقة في بوتستراب باستعمال التخطيط المرن Flex Box وهي لا تحوي أية هوامش بشكل افتراضي.

أي بطاقة في بوتستراب يجب أن يكون لها "حاوية". هذه الحاوية عبارة عن عنصر div له الصنف التنسيقي ‎.card. بالنسبة لمحتويات الحاوية فلدينا العديد من الإمكانيات. يمكن بشكل أساسي، أن تحتوي البطاقة على نص عادي فحسب. أمّا بالنسبة للشكل النموذجي، فيمكن أن يكون لها التنسيق التالي:

  • صورة توضيحية في الأعلى.
  • جسم البطاقة، والذي يحتوي على عنوان البطاقة ونص توضيحي.

انظر إلى البطاقة النموذجية التالية:

<div class="card" style="width: 18rem;">
    <img src="..." class="card-img-top" alt="image-description">
    <div class="card-body">
      <h5 class="card-title">عنوان البطاقة</h5>
      <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p>
      <a href="#" class="btn btn-primary">زر عادي</a>
    </div>
  </div>

سيشكل العنصر div مع الصنف ‎ .card الحاوية الخاصة بالبطاقة ككل. داخل هذا الحاوية، لاحظ وجود عنصر الصورة img مع الصنف ‎ .card-img-top، ستلاحظ أيضًا وجود عنصر div آخر يمثّل جسم البطاقة له الصنف ‎ .card-body. يتكوّن جسم البطاقة في مثالنا هذا من قسمين:

  • القسم الأول هو عنوان البطاقة باستخدام الصنف ‎.card-title
  • القسم الثاني هو نص البطاقة باستخدام الصنف ‎.card-text . يمكن بشكل اختياري إضافة زر لهذا القسم كما فعلنا في مثالنا هذا.

عند معاينة الشيفرة السابقة ستحصل على شكل شبيه بما يلي:

1.png

كما أسلفت قبل قليل توجد الكثير من الإمكانيات التي توفرها البطاقة. يمكن مثلًا إضافة عنوان فرعي باستخدام الصنف ‎.card-subtitle ويُوضع هذا العنوان الفرعي كما هو واضح أسفل العنوان الرئيسي في حال الرغبة. كما يمكن وضع روابط ضمن جسم البطاقة، بتنسيق متوافق معها باستخدام عنصر a مع الصنف ‎.card-link

يمكن أيضًا جعل البطاقة تعرض قائمة من مجموعة من العناصر . انظر إلى التعديل التالي الذي أجريته على الشيفرة السابقة:

<div class="card" style="width: 18rem;">
    <img src="images/tmp.png" class="card-img-top" alt="image-description">
    <div class="card-body">
      <h5 class="card-title">عنوان البطاقة</h5>
      <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p>
      <a href="#" class="btn btn-primary">زر عادي</a>
    </div>
<!--بداية التعديل -->
    <ul class="list-group list-group-flush">
      <li class="list-group-item">عنصر 1</li>
      <li class="list-group-item">عنصر 2</li>
      <li class="list-group-item">عنصر 3</li>
    </ul>
<!--نهاية التعديل -->
  </div>

لاحظ الشيفرة الجديدة من المثال الأخير. وضعت عنصر قائمة غير مرتبة ul مع الصنف ‎.list-group و الصنف ‎.list-group-flush. الصنف الأخير وظيفته جمالية فقط، حاول إزالته وانظر الفرق.

عند معاينة الشيفرة السابقة ستحصل على شكل شبيه بما يلي:

2.png

يمكن أيضًا الاستغناء عن الصورة التوضيحية في الأعلى واستخدام ترويسة بدلًا منها. كما ويمكن أيضًا وضع تذييل للبطاقة. انظر إلى الشيفرة التالية:

<div class="card" style="width: 18rem;">
    <div class="card-header">ترويسة مناسبة</div>

    <div class="card-body">
      <p class="card-text">نص بسيط لوصف المنتج أو أي شيء تود الحديث عنه</p>
      <a href="#" class="btn btn-primary">زر عادي</a>
    </div>

    <div class="card-footer text-muted">تذييل مناسب</div>
  </div>

لاحظ اولًا أن كلًا من الترويسة والتذييل موجودان خارج جسم البطاقة ضمن عنصر يdiv منفصلين. لعنصر div الذي يحوي الترويسة الصنف ‎.card-header أما لعنصر div الذي يحوي التذييل الصنف ‎.card-footer. لاحظ أيضًا كيف استخدمت الصنف ‎.text-muted لجعل نص التذييل باهتًا بعض الشيء. يمكنك بالطبع إزالة هذا التنسيق إن أحببت. ستحصل على الشكل التالي عند معاينة الشيفرة السابقة:

3.png

يمكنك الإطلاع على المزيد من الخيارات المتاحة بزيارة صفحة التوثيق الرسمية لمكوّن البطاقة Card.

التعرّف على مكون الشرائح الدوارة Carousel في بوتستراب

هو من المكوّنات المفيدة ضمن صفحات الويب. فمن خلاله يمكن عرض شرائح للمستخدمين ذات محتوى متنوّع وقابل للدوران بشكل تلقائي، أو بالنقر على أزرار تنقّل أو بمزيج بينهما. يمكن أن يكون هذا المحتوى عبارة عن صورة مع نص وصفي، أو يمكن حتى أن يكون محتوى مخصّص للغاية كما سنفعل في مشروعنا "نبيه". ولا يمكن في بوتستراب أن تكون مكوّنات Carousel متداخلة nested فيما بينها.

يمكن استخدام هذا المكوّن من خلال عنصر div مع التنسيقين ‎.carousel و ‎.slide. يحتوي كل مكّون Carousel على عنصر div آخر له التنسيق ‎.carousel-inner يحتوي بدوره على الشرائح الفعلية التي ستظهر للمستخدم. كل شريحة من هذه الشرائح عبارة عن عنصر div له التنسيق ‎.carousel-item. يجب أن يكون لإحدى هذه الشرائح تنسيق آخر هو ‎.active للدلالة إلى الشريحة الحالية (الفعّالة) التي سُتعرض أولًا للمستخدم.

انظر إلى مكوّن Carousel نموذجي ضمن الشيفرة التالية:

<div id="carouselComponent" class="carousel slide" data-bs-ride="carousel">
  <div class="carousel-inner">
    <div class="carousel-item active">
      <img src="..." class="d-block w-100" alt="...">
    </div>
    <div class="carousel-item">
      <img src="..." class="d-block w-100" alt="...">
    </div>
    <div class="carousel-item">
      <img src="..." class="d-block w-100" alt="...">
    </div>
  </div>
</div>

ستظهر الشريحة التي تحمل التنسيق active أولًا أمام المستخدم. ثم ستدور الشرائح بالتناوب أمام المستخدم بشكل تلقائي ضمن فترات زمنية محّددة. يمكنك وضع صور مناسبة ضمن السمة src لكل صورة لكي ترى النتيجة بشكل فعلي.

يمكن وكخيار إضافي، استخدام التنسيق ‎.carousel-dark (يُوضع بجوار التنسيقين ‎.carousel و ‎.slide لعنصر div الذي يمثّل الحاوية الرئيسية لمكوّن Carousel)، وذلك لإكساب مكوّن carousel تنسيقًا داكنًا بعض الشيء.

كما وسبق أن رأينا في عنصر البطاقة ، يحتوي عنصر Carousel على تشكيلة متنوّعة من الخيارات في العرض. يمكن مثلًا إضافة أزرار انتقال تسمح للمستخدم بالتنقّل اليدوي عوضًا عن التنقّل التلقائي. أضف إلى الشيفرة السابقة، الشيفرة التالية (ضعها قبل آخر وسم إغلاق <‎/div>):

<button class="carousel-control-prev" type="button" data-bs-target="#carouselComponent" data-bs-slide="prev">
    <span class="carousel-control-prev-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Previous</span>
  </button>
  <button class="carousel-control-next" type="button" data-bs-target="#carouselComponent" data-bs-slide="next">
    <span class="carousel-control-next-icon" aria-hidden="true"></span>
    <span class="visually-hidden">Next</span>
  </button>

يمكن أيضًا وضع مؤشّر يظهر أسفل مكوّن Carousel للدلالة على عدد الشرائح الموجودة بالإضافة إلى موقعك الحالي ضمن هذه الشرائح. يمكن وضع هذا المؤشّر من خلال عنصر div له التنسيق ‎.carousel-indicators. انظر إلى الشيفرة التالية (ضعها قبل عنصر div ذي التنسيق ‎.carousel-inner مباشرةً):

<div class="carousel-indicators">
    <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
    <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="1" aria-label="Slide 2"></button>
    <button type="button" data-bs-target="#carouselComponent" data-bs-slide-to="2" aria-label="Slide 3"></button>
  </div>

يمكنك الإطلاع على المزيد من الخيارات المتاحة بزيارة صفحة التوثيق الرسمية لمكوّن Carousel.

إنجاز قسم الدورات الأكثر مبيعًا

سنطبّق ما تعلّمناه في الفقرتين السابقتين في إنجاز قسم الدورات الأكثر مبيعًا Best Selling ضمن موقع نبيه. أدرج الشيفرة التالية ضمن القسم best-selling في الملف index.html:

<div class="section-title">الدورات الأكثر مبيعًا</div>
    <div id="bestSellingCourses" class="carousel carousel-dark slide" data-bs-ride="carousel">
      <div class="carousel-inner">
        <div class="carousel-item active"> <!-- الموضع 1-->

          <div class="row">

            <div class="col-lg-3">
              <div class="card"> <!-- الموضع 2-->
                <img src="images/python-product.jpg" class="card-img-top product-image" alt="python-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام بايثون</h5>
                  <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة بايثون</p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>

            <div class="col-lg-3">
              <div class="card"> <!-- الموضع 3-->
                <img src="images/github-product.jpg" class="card-img-top product-image" alt="github-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة التعامل مع GitHub</h5>
                  <p class="product-text card-text">تعلّم كيف تدير مشاريعك البرمجية من حيث إدارة الإصدار والمساهة في مشاريع برمجية أخرى.</p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>

            <div class="col-lg-3">
              <div class="card"> <!-- الموضع 4-->
                <img src="images/python-django-product.jpg" class="card-img-top product-image" alt="django-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة تطوير تطبيقات ويب باستخدام بايثون مع Django</h5>
                  <p class="product-text card-text">تعلّم كيف تبني تطبيقات ويب باستخدام لغة بايثون مع Django </p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>

            <div class="col-lg-3">
              <div class="card"> <!-- الموضع 5-->
                <img src="images/javascript-product.jpg" class="card-img-top product-image" alt="javascript-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام جافاسكريبت</h5>
                  <p class="product-text card-text"> سنتعلّم في هذه الدورة كيفية تطوير تطبيقات الواجهة الأمامية باستخدام جافاسكريبت</p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="carousel-item">
          <div class="row">
            <div class="col-lg-3">
              <div class="card">  <!-- الموضع 6-->
                <img src="images/php-product.jpg" class="card-img-top product-image" alt="php-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة أساسيات البرمجة باستخدام PHP</h5>
                  <p class="product-text card-text">في هذه الدورة سنتعلّم مبادئ البرمجة في لغة PHP</p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>

            <div class="col-lg-3">
              <div class="card">  <!-- الموضع 7-->
                <img src="images/arduino-product.jpg" class="card-img-top product-image" alt="arduino-course">
                <div class="card-body">
                  <h5 class="product-title card-title">دورة التعامل مع أساسيات Arduino</h5>
                  <p class="product-text card-text">تعلّم كيف تبني أنظمة مضمنة تتضمّن مشاريع بسيطة باستخدام Arduino</p>
                  <a href="#" class="btn btn-primary">أضف إلى السلة</a>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
 <!-- الموضع 8-->
      <button class="carousel-control-prev" type="button" data-bs-target="#bestSellingCourses"
        data-bs-slide="prev">        
          <span class="carousel-control-prev-icon" aria-hidden="true"></span>      
      </button>
      <button class="carousel-control-next" type="button" data-bs-target="#bestSellingCourses"
        data-bs-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
      </button>
    </div>

انتقل الآن الى الملف styles.css وأضف إليه التنسيق التالي قبل تنسيقات قسم الترويسة Header Section:

.section-title{
    text-align: center;
    font-size: xx-large;
    padding: 3rem 0;
}

الهدف من ذلك هو فقط تنظيم الملف styles.css. ثم بعد ذلك أضف التنسيقات التالية إلى آخر محتويات الملف:

/*Best Selling Section*/

.carousel-inner{
    padding: 0 5%;
}
.carousel-control-prev {
    background: linear-gradient(to right, rgba(200,200,200,0), rgba(200,200,200,1));
}

.carousel-control-next {
    background: linear-gradient(to left, rgba(200,200,200,0), rgba(200,200,200,1));
}

.product-image{
    height: 12rem;
}

.product-title{
    height: 4rem;    
}

.product-text{
    height: 6rem;
}

بالنسبة لشيفرة HTML، نبدأ قسم المنتجات الأكثر مبيعًا بنص توضيحي يُشير إلى بداية هذا القسم له التنسيق ‎.section-title ثم يبدأ بعد ذلك مكوّن Carousel بتنسيق داكن ‎.carousel-dark وبمعرّف bestSellingCourses. يبدأ بعد ذلك مباشرةً الجسم الداخلي له ‎.carousel-inner.

في الواقع سيكون مكوّن Carousel هنا بسيطًا للغاية. سيحتوي هذا المكوّن على عنصري ‎.carousel-item وبعبارة أخرى سيحتوي على شريحتين. ستحمل الشريحة الأول الصنف ‎.active كما هو واضح (الموضع 1). يوجد ضمن الشريحة الأولى أربعة منتجات وُضعت ضمن سطر ‎.row ووُزّعت على أربعة أعمدة ‎.col-lg-3. وُضِع كل منتج ضمن بطاقة card منفصلة (انظر إلى المواضع 2 و 3 و 4 و 5). أمّا الشريحة الثانية فتحتوي على منتجين فقط (انظر إلى الموضعين 6 و 7).

بالنسبة إلى زري التنقّل لمكوّن الشرائح الدوّارة فيمكنك أن تجدهما اعتبارًا من الموضع 8. لاحظ أنني قد أجريت بعض التعديل على الصنفين ‎ .carousel-control-prev و ‎ .carousel-control-next ضمن الملف styles.css حيث أنّني قد أضفت تدرّجًا لونيًا لهذين الزرّين كي يسهل للمستخدم تمييزهما فورًا.

بمعاينة الشيفرة السابقة ضمن المتصفّح ستحصل على شكل شبيه بما يلي:

4.png

5.png

إنجاز القسم الخاص بأصناف الدورات

لنبدأ الآن بتجهيز القسم الخاص بأصناف الدورات، والذي سيتكوّن في مشروعنا هذا من ستة أقسام وهي:

سنستخدم من أجل كل قسم مكوّن البطاقة من بوتستراب، وسنوزّع هذه البطاقات على سطرين مستقلين كما في الشكل التالي:

6.png

أضف الآن شيفرة HTML التالية إلى القسم course-categories:

<div class="section-title">الأقسام المتاحة</div>
    <div class="row">
      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/programming-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">البرمجة</p>
            </div>
          </div>
        </a>
      </div>

      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/marketing-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">التسويق</p>
            </div>
          </div>
        </a>
      </div>

      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/freelance-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">العمل الحر</p>
            </div>
          </div>
        </a>
      </div>
    </div>

    <div class="row">
      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/cloud-computing-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">التطبيقات السحابية</p>
            </div>
          </div>
        </a>
      </div>

      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/certificates-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">الشهادات العالمية</p>
            </div>
          </div>
        </a>
      </div>

      <div class="col-lg-4">
        <a class="category-link" href="#">
          <div class="card category-card">
            <img src="images/apps-category.png" class="card-img-top category-image"
              alt="certifications-category">
            <div class="card-body">
              <p class="card-text category-text">البرامج والتطبيقات</p>
            </div>
          </div>
        </a>
      </div>
    </div>

تتألف كل بطاقة من صورة توضيحية، بالإضافة إلى نص وصفي تحت الصورة. ستحتاج أيضًا إلى إضافة التنسيقات التالية إلى الملف styles.css أسفل التنسيقات السابقة:

#course-categories{
    background-color: #eee;
    padding: 0 10% 8px;
}

#course-categories .row{
    margin-bottom: 72px;
}

.course-categories-title{
    text-align: center;
    font-size: xx-large;
    padding: 3rem 0;
}

.category-card{
    margin-left: 24px;
    margin-right:24px;
    padding: 48px 0px 32px;
}

.category-image{
    width: 50%;
    height: auto;
    margin: 0 auto;
}

.category-text{
    text-align: center;
    font-size: 1.3rem;
}

.category-link{
    text-decoration: none;
    color:inherit;
}

أعتقد أنّه لا جديد في التنسيقات السابقة أو حتى في شيفرة HTML الخاصّة في هذا القسم.

أيقونات Bootstrap 5

يأتي مع بوتستراب 5 مجموعة غنية من الأيقونات الجميلة والمتنوّعة التي يمكنك استخدامها في التطبيقات التي تُنشئها سواءً باستخدام بوتستراب 5 أو حتى بغيره.

لأيقونات بوتستراب 5 نوعان:

  • أيقونات على شكل خطوط ويب Web Fonts.
  • أيقونات بتنسيق SVG.

سنستخدم هنا النوع الأوّل: أيقونات Web Fonts.

تكون هذه الأيقونات منفصلة عن بوتستراب، وقبل استخدامها، ينبغي إضافة مرجع إلى الصفحة الرئيسية الخاصة بنا. أضف الشيفرة التالية إلى قسم head ضمن الملف index.html:

<!-- Boostrap 5 icons - web font -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.0/font/bootstrap-icons.css">

يمكن استخدام هذه الأيقونات بشكل مستقل كما سنفعل في الفقرة التالية. كما يمكن استخدامها مع الأزرار العادية وغيرها من العناصر.

إنجاز قسم التذييل Footer

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

كما سندرج تحت الأيقونات السابقة، نصًا بسيطًا يُشير إلى موقع نبيه كعلامة مسجلة. أضف الشيفرة البرمجية التالية ضمن القسم footer ضمن الملف index.html:

<footer>
      <div class="container-fluid">
        <i class="bi bi-facebook social-icon"></i>
        <i class="bi bi-twitter social-icon"></i>
        <i class="bi bi-instagram social-icon"></i>
        <i class="bi bi-envelope social-icon"></i>
        <p>© دورات نبيه 2021</p>
      </div>
    </footer>

التنسيقات مثل bi bi-facebook وغيرها ضرورية لاستخدام الأيقونة المطلوبة مع عنصر i ما.

أضف أيضًا التنسيقات التالية إلى الملف styles.css:

footer{
    height: 200px;
}

.social-icon {
    margin: 20px 10px;
  }

#footer .container-fluid{
    padding: 7% 15%;
    text-align: center;
}

عند المعاينة، ستحصل على شكل شبيه بما يلي:

7.png

أعتقد أنّ التنسيقات السابقة واضحة ومباشرة ولا تحتاج إلى أي تعليق إضافي. وبذلك نكون قد وصلنا إلى نهاية هذا الدرس، وبالتالي إلى نهاية تصميم الصفحة الرئيسية لموقع "نبيه". يمكنك الوصول إلى الشيفرة كاملة عن طريق زيارة هذا المستودع، ضمن المجلّد chapter05 أو من الملف المرفق في نهاية المقال، وكما ويمكنك الإطلاع على نسخة حيّة من هذه الصفحة من github.io.

خاتمة

تعرّفنا في هذا الدرس على مكوّنين مهمّين وهما البطاقة Card والشرائح الدوّارة Carousel، وتعرّفنا على أهم الخصائص المتاحة لهما. كما تعرّفنا على مكتبة أيقونات Font Awesome التي تضم تشكيلة رائعة من الأيقونات المميزة، والتي يمكنك استخدامها بشكل مجاني في تطبيقاتك المختلفة. كما عملنا على تطبيق ما تعلّمناه في تصميم وإنجاز باقي أقسام الصفحة الرئيسية لموقع نبيه (قسم الدورات الأكثر مبيعًا والقسم الخاص بأصناف الدورات و قسم التذييل).

bootstrap5-tutorial-master.zip

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...