CSS3 · كورس عربي شامل · 2026

تعلمCSS3

CASCADING STYLE SHEETS · JUNE 2026

لما بتكمّل HTML — الصفحة بتكون هيكل بدون روح.
CSS هي اللي بتحوّل الهيكل لتحفة بصرية. هنتعلمها من الصفر لأحدث مميزات 2026.

🎓
// طريقة المذاكرة الصح

CSS مش بتُحفظ — بتُفهم وبتُجرَّب. لكل property تتعلمها، غيّر قيمتها في DevTools وشوف اللي بيتغير فوراً. ده بيبني حدس تصميمي حقيقي. أحسن مبرمج CSS هو اللي جرّب أكتر.

💻// اختصارات VS Code ستحتاجها دايماً في CSS
CtrlSpace
Autocomplete — يعرض كل الـ properties المتاحة
Alt↑↓
نقل سطر كامل فوق أو تحت
ShiftAlt
نسخ سطر تحته مباشرة
Ctrl/
تحويل السطر لـ comment
F12
DevTools — صديقك الأول في CSS
CtrlD
تحديد الكلمة التالية المشابهة
CtrlShiftP
Command Palette — كل الأوامر
CtrlKCtrlF
Format Document — تنسيق CSS تلقائي
🎨
// مشروع الدبلومة
Portfolio Page — تجميل صفحتك
هتاخد الـ HTML اللي بنيناه وتحوّله لتصميم احترافي مذهل بـ CSS كامل
HTML ✓
CSS ◄
JS
6
وحدات
21
درس
7
تاسكات
1
مشروع
01
الأساسيات
02
الألوان والخطوط
03
Flexbox & Grid
04
Animations
05
Responsive
06
Modern CSS
🎨
المشروع
// تقدمك
0% بداية الكورس
01
// UNIT ONE
الأساسيات — كيف يفكر CSS
قبل ما تكتب سطر CSS، لازم تفهم كيف المتصفح بيقرأ وبيطبق الـ styles. ده الأساس اللي كل حاجة بعده بتبنى عليه.
4 دروس1 مطب برمجي1 تاسك~60 دقيقة
01
// FOUNDATION

ما هو CSS؟ وكيف يعمل

Cascading Style Sheets — اللغة اللي بتلوّن الإنترنت

CSS اختصار لـ Cascading Style Sheets. كل كلمة فيها معنى مهم:

  • Cascading (متدرج) — لما في أكثر من قاعدة بتأثر على نفس العنصر، CSS بيختار الأقوى. هنشرح ده تفصيلاً في درس Specificity.
  • Style — بنتكلم عن المظهر: الألوان، الأحجام، المسافات، التخطيط.
  • Sheets — بتُكتب في ملفات منفصلة (.css) زي ما HTML في ملفاتها.

كل قاعدة CSS عندها 3 أجزاء: selector (مين اللي هتأثر عليه؟) + property (إيه اللي عايز تغيّره؟) + value (هتغيّره لإيه؟). مثلاً: h1 { color: blue; } — المحدد هو h1، الخاصية color، القيمة blue.

لما المتصفح يفتح صفحتك بيعمل 5 خطوات:

  1. يقرأ الـ HTML ويحوّله لشجرة عناصر اسمها DOM Tree
  2. يقرأ الـ CSS ويحوّله لشجرة ثانية اسمها CSSOM Tree
  3. يدمج الاتنين في "Render Tree" — بس العناصر الظاهرة
  4. يحسب المواضع (Layout/Reflow) — كل عنصر فين وقد إيه
  5. يرسم على الشاشة (Paint) — ألوان، ظلال، صور
ليه ده مهم؟ لأن بعض الـ CSS properties زي width وmargin بتعمل إعادة حساب للـ Layout كاملة (Reflow) وده بطيء. لكن properties زي transform وopacity بيشتغلوا على الـ GPU مباشرةً وأسرع بكتير. عشان كده animations بتستخدم transform مش left/top.

أسرع طريقة تتعلم CSS هي DevTools. افتح أي صفحة، اضغط F12، روح Styles panel، وعدّل أي قيمة وهتشوف التغيير فوراً. ده مش غش — ده طريقة كل المحترفين بيجربوا فيها.

02
// LINKING

طرق ربط CSS بـ HTML

ثلاث طرق — واحدة بس الصح في كل المشاريع
⚡ مهم للـ performance

في 3 طرق تحط فيها CSS في صفحتك. كل طريقة ليها مكانها الصح، ومش هتستخدم إلا واحدة أساساً.

linking-css.html
/* ══ الطريقة 1: External CSS ← دي اللي هتستخدمها دايماً ══ */
/* ملف style.css منفصل، تربطه جوه <head> */
<link rel="stylesheet" href="style.css">

/* ══ الطريقة 2: Internal ← للتجريب السريع فقط ══ */
/* جوه <style> في نفس ملف HTML */
<style>
  body { background: #000; }
</style>

/* ══ الطريقة 3: Inline ← تجنبها إلا لو JavaScript محتاجها ══ */
/* مكتوبة مباشرة في الـ HTML element */
<div style="color: red; font-size: 18px">...</div>

ليه External CSS هي الأفضل؟ لأسباب 3:

  • الـ Cache — المتصفح بيحفظ الملف في الذاكرة. الزائر الأول يحمّله مرة واحدة، بعد كده كل الصفحات تانية بتاخده من الذاكرة مش من الإنترنت.
  • الفصل (Separation of Concerns) — HTML للهيكل، CSS للتصميم. لو غيّرت لون الـ primary color، بتغيّره في ملف واحد ومش بتدور عليه في كل ملفات HTML.
  • فريق العمل — مبرمج يشتغل على HTML وdesigner يشتغل على CSS في نفس الوقت بدون تعارض.
🚫
ليه Inline CSS مكروهة؟

أولاً: specificity عالي جداً، بيكسر الـ CSS التانية وصعب تعمل override عليه. ثانياً: مش بيتحفظ في الـ cache. ثالثاً: لو عندك 50 button بنفس الـ style لازم تكرر الكود 50 مرة. الاستثناء الوحيد: لما JavaScript بتغير style ديناميكياً زي element.style.transform = 'rotate(45deg)'.

ترتيب CSS في المشاريع الكبيرة: المحترفين مش بيكتبوا كل CSS في ملف واحد. بيقسموها: reset.css (إعادة تعيين styles المتصفح) ← variables.css (الألوان والمتغيرات) ← base.css (styles الأساسية) ← components.css (الـ buttons والـ cards) ← utilities.css (classes مساعدة). أو بيستخدموا Sass/SCSS اللي بيقسم الكود لـ partials ويجمعهم تلقائياً.
03
// SELECTORS

Selectors — المحددات

أهم مهارة في CSS — إزاي تقول "الكود ده لمين بالظبط؟"
⚡ الأهم في CSS

الـ Selector هو الجزء اللي بتحدد فيه على أي عنصر هتطبق الـ CSS. اختيار الـ selector الصح فرق بين كود نظيف وكود فوضى. في أنواع كتير — هنتعلم الأهم:

selectors.css
/* ── 1. Element Selector: يأثر على كل عناصر من نوعه ── */
h1   { color: #2965f1; }   /* كل h1 في الصفحة */
p    { line-height: 1.7; }  /* كل p في الصفحة */

/* ── 2. Class Selector (.): الأكثر استخداماً ── */
/* يأثر على كل عنصر عنده class="card" في الـ HTML */
.card        { background: white; }
.card.active { border: 2px solid blue; } /* عنده الاتنين */

/* ── 3. ID Selector (#): لعنصر واحد بس في الصفحة ── */
/* يأثر على العنصر اللي عنده id="hero" — استخدمه نادر في CSS */
#hero        { min-height: 100vh; }

/* ── 4. Universal (*): كل عنصر في الصفحة ── */
/* بنستخدمه في الـ reset بس */
*            { box-sizing: border-box; }

/* ── 5. Descendant ( ): عنصر جوّا عنصر تاني ── */
/* كل p جوّا .card — حتى لو متداخل 10 مستويات */
.card p      { color: gray; }

/* ── 6. Child (>): الأبناء المباشرون فقط ── */
/* li الابن المباشر لـ .nav — مش أي li جوّاه */
.nav > li    { display: inline-block; }

/* ── 7. Adjacent Sibling (+): العنصر التالي مباشرة ── */
/* أول p جاي بعد h2 مباشرةً */
h2 + p       { font-size: 18px; }

/* ── 8. General Sibling (~): كل الأخوة بعده ── */
/* كل p جاية بعد h2 في نفس المستوى */
h2 ~ p       { color: gray; }

/* ── 9. Attribute []: بناءً على خاصية HTML ── */
input[type="email"] { border: 2px solid blue; }
a[href^="https"]   { color: green; }  /* href يبدأ بـ https */
a[href$=".pdf"]    { color: red; }    /* href ينتهي بـ .pdf */
a[href*="github"]  { font-weight: 700; } /* href يحتوي github */

/* ── 10. Multi (,): عدة selectors بنفس الـ style ── */
h1, h2, h3, h4 { font-weight: 700; }

Class vs ID — الفرق الحقيقي: ID لازم يكون فريداً في الصفحة كلها (واحد بس). Class ممكن تتكرر على عناصر كتير. في CSS، استخدم classes دايماً للـ styling لأنها قابلة للاستخدام أكثر من مرة. IDs استخدمها للـ JavaScript التحديد وللـ anchor links (#about).

نصيحة محترف: مش لازم تحفظ كل الـ selectors. الأهم إنك تفهم الـ 4 الأساسية (element، class، id، descendant) وتعرف إن باقيهم موجودين وترجعلهم وقت الحاجة.

04
// BOX MODEL

Box Model — كل عنصر صندوق

أهم مفهوم في CSS — لو فهمته صح هتوفر ساعات من الـ debugging
⚡ أساسي جداً

كل عنصر HTML — سواء كان h1 أو div أو img — هو في الأساس مستطيل. ومفيش استثناء. الـ Box Model بيقول إن كل مستطيل بيتكون من 4 طبقات متداخلة من الخارج للداخل:

  • Margin — المسافة خارج العنصر، بتبعّده عن العناصر التانية
  • Border — حدود العنصر، ممكن تكون مرئية أو لأ
  • Padding — المسافة داخل العنصر، بين الـ border والمحتوى
  • Content — المحتوى نفسه: النص أو الصورة
Box Model مرئي
← margin →
← border →
← padding →
content
box-model.css
/* ══ أول حاجة في كل ملف CSS تكتبها — RESET ══ */
*, *::before, *::after {
  box-sizing: border-box; /* شرحه جاي ↓ */
  margin: 0;
  padding: 0;
}

.card {
  /* ── Content ── */
  width:  300px;
  height: 200px;

  /* ── Padding: مسافة داخلية ── */
  padding: 20px;                   /* كل الجهات الأربعة */
  padding: 10px 20px;             /* فوق/تحت  يمين/شمال */
  padding: 5px 10px 15px 20px; /* top right bottom left */
  padding-top: 8px;               /* جهة واحدة بس */

  /* ── Border ── */
  border: 2px solid #2965f1;    /* سُمك | نوع | لون */
  border-radius: 12px;           /* زوايا دائرية */
  border-radius: 50%;            /* دائرة كاملة */

  /* ── Margin: مسافة خارجية ── */
  margin: 0 auto;               /* توسيط أفقي — auto على اليمين واليسار */
  margin-bottom: 24px;
}

/* ══ box-sizing: border-box — ليه مهم؟ ══ */
/* بدونه: width=300px + padding=20px = 340px فعلي! */
/* معاه:  width=300px يشمل الـ padding والـ border */
/* يعني الـ 300px هو الحجم النهائي مهما حطيت padding */
Margin Collapse — ظاهرة غريبة: لما عندك عنصرين فوق بعض وكل واحد عنده margin-bottom/top، المسافة بينهم مش هتبقى الاتنين مع بعض — هتبقى الأكبر فقط. مثلاً: h2 عنده margin-bottom: 30px، و p تحته عنده margin-top: 20px — المسافة هتبقى 30px مش 50px. ده "Margin Collapse" وبيحصل في الـ block elements العمودية بس.
💡
DevTools لفهم الـ Box Model

في DevTools (F12)، لما تختار أي عنصر هتلاقي في أسفل الـ Styles panel رسم للـ Box Model بالأرقام الفعلية. ده أفضل طريقة تفهم ليه العنصر ده حجمه كده.

⚠️
مطبات برمجية شائعة — الوحدة الأولى

1. نسيان نقطة قبل اسم الـ class

/* مفيش error في الـ Console — لكن الـ style مش بيتطبق خالص */ card { background: white; } /* المفروض .card مش card */
الحل: CSS مش بتدّيك أي تحذير لو كتبت selector غلط — بس الـ style مش هيتطبق بصمت. لو كتبت card بدل .card، أنت فعلياً بتستهدف عنصر HTML اسمه <card> (مش موجود) بدل العنصر اللي عنده class="card". افحص دايماً في DevTools إن الـ selector بتاعك "مشطوب" (strikethrough) ولا لأ — لو مشطوب يبقى فيه قاعدة أقوى بتلغيه.

2. نسيان box-sizing: border-box

/* مفيش error — لكن الـ layout بيتكسر بشكل غريب */ .box { width: 300px; padding: 20px; border: 2px solid; } /* العرض الفعلي بقى 344px مش 300px! */
الحل: بدون box-sizing: border-box، الـ padding والـ border بيتضافوا فوق الـ width المحدد، مش بياخدوا من جواه. الحل: حط *, *::before, *::after { box-sizing: border-box; } في أول كل ملف CSS — قاعدة دايماً بدون استثناء.

3. الخلط بين margin و padding

/* مفيش error — لكن النتيجة البصرية مش زي المتوقع */ .card { margin: 20px; } /* المسافة جوّا الـ border ولا برّاها؟ */
الحل: margin = مسافة خارج العنصر (بتبعده عن العناصر التانية). padding = مسافة داخل العنصر (بين الحدود والمحتوى). لو الخلفية (background) بتاعة العنصر مش بتوصل لحتة فاضية، فدي padding. لو في فراغ برّا العنصر نفسه، فده margin.
TASK 01
أنشئ ملف style.css وابدأ الـ Portfolio
الوحدة الأولى · الأساسيات
  • أنشئ ملف style.css وربطه في <head> بـ <link>
  • أضف الـ Reset في أول سطر: *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  • حدد الـ body وغيّر background-color وfont-family وcolor
  • استخدم 5 أنواع مختلفة من الـ selectors على عناصر الـ portfolio
  • افتح DevTools، اختار أي عنصر، وشوف الـ Box Model بتاعه في الـ Styles panel
  • استخدم attribute selector لتنسيق links خارجية (href^="https") بشكل مختلف
  • جرّب child selector (>) على قائمة الـ nav وشوف الفرق عن descendant
Portfolio Step 1 — style.cssأول خطوة في تجميل الـ portfolio! الصفحة دلوقتي عندها ملف CSS مربوط وجاهزة للتصميم.
  • "CSS Selectors game CSS Diner" — لعبة ممتعة بتتعلم فيها كل الـ selectors
  • "Chrome DevTools CSS overview" — شوف كل حاجة تقدر تعملها في DevTools
UNIT 02
02
// UNIT TWO
الألوان والخطوط والـ Variables
الهوية البصرية لأي موقع بتتحدد بالألوان والخطوط. CSS Variables بتخلي الكود قابل للصيانة بشكل مذهل — غيّر لون الـ primary في مكان واحد وكل الموقع يتغيّر.
3 دروس1 مطب برمجي1 تاسك~60 دقيقة
05
// COLORS

الألوان والخلفيات

HEX، RGB، HSL، OKLCH — وكيف تختار النظام الصح
⚡ OKLCH هو المستقبل

CSS بتدعم أكثر من طريقة لكتابة الألوان. كل طريقة ليها مزايا، بس في الآخر بتعطي نفس النتيجة — فرقهم في سهولة التعديل والمنطقية.

HEX#2965f1
RGBrgb(41,101,241)
RGBAalpha .6
HSL227° 88% 55%
OKLCH2026 ✦
mix()50/50
LinearGradient
ConicGradient
colors.css
.el {
  /* ── HEX: الأشهر استخداماً، مفيش بصيرة فيه ── */
  color: #2965f1;  /* #RRGGBB — حمر، أخضر، أزرق بـ hex */
  color: #2965f1aa; /* الأخيرين للشفافية (alpha) */

  /* ── RGB: أوضح من HEX، الأرقام من 0 لـ 255 ── */
  color: rgb(41, 101, 241);
  color: rgba(41, 101, 241, 0.5); /* 0=شفاف 1=معتم */

  /* ── HSL: الأسهل للتفكير والتعديل ── */
  /* Hue(الدرجة 0-360) Saturation(التشبع%) Lightness(السطوع%) */
  color: hsl(227, 88%, 55%);
  /* عايز نفس اللون أفتح؟ غيّر 55% لـ 75% */
  /* عايز شفافية؟ */
  color: hsl(227 88% 55% / 0.5); /* نفس اللون بـ 50% شفافية */

  /* ── OKLCH: الأحدث والأدق — 2026 ── */
  /* Lightness(0-1) Chroma(تشبع) Hue(0-360) */
  color: oklch(60% 0.22 250);
  /* ميزته: Lightness متسقة — 60% أزرق = 60% أحمر في الإضاءة */

  /* ── color-mix: خلط لونين مع بعض ── */
  color: color-mix(in srgb, #2965f1 70%, #e91e8c 30%);

  /* ── Named Colors: 140+ اسم جاهز ── */
  color: tomato;
  color: cornflowerblue;
  color: transparent; /* شفاف كامل */

  /* ══ Backgrounds ══ */

  /* لون عادي */
  background-color: #f8f9fa;

  /* linear-gradient: خط من لون للتاني ── */
  /* الرقم هو الاتجاه: 0=فوق، 90=يمين، 135=زاوية */
  background: linear-gradient(135deg, #2965f1, #e91e8c);
  /* ممكن أكثر من لونين مع positions */
  background: linear-gradient(180deg,
    #2965f1 0%,    /* أزرق من البداية */
    #8b5cf6 50%,   /* بنفسجي في المنتص */
    #e91e8c 100%   /* وردي في النهاية */
  );

  /* radial-gradient: دائري من المركز */
  background: radial-gradient(circle at center, #2965f1 0%, transparent 70%);

  /* صورة خلفية */
  background-image: url('PIC/hero-bg.jpg');
  background-size: cover;     /* يملأ المساحة مع حفظ النسبة */
  background-position: center; /* توسيط */
  background-repeat: no-repeat;

  /* صورة + overlay غامق فوقيها — شائع جداً في Hero sections */
  background:
    linear-gradient(rgba(0,0,0,0.6), rgba(0,0,0,0.3)),
    url('hero.jpg') center/cover no-repeat;
    /* الـ gradient فوق الصورة، بيخليها أغمق وبيخلي النص مقروء */
}
OKLCH هو المستقبل وليه تتعلمه؟ في الأنظمة القديمة (HEX/RGB)، الألوان مش uniform — الأزرق بيبان أغمق من الأصفر بنفس قيمة الـ lightness. OKLCH بيحل ده لأنه مبني على إدراك العين البشرية. النتيجة: لو بنيت color palette بـ OKLCH، كل الألوان بيكون ليها نفس مستوى السطوع الحقيقي. مدعوم في كل المتصفحات الحديثة من 2023.
06
// TYPOGRAPHY

Typography — فن الخطوط

font-family، size، weight، line-height، Google Fonts، gradient text

Typography هي علم وفن إخراج النص. 80% من محتوى الإنترنت نص، يعني لو عارف تتحكم في الخطوط كويس — موقعك بيبقى مختلف تلقائياً. هنتعلم الأساسيات وبعض التأثيرات الاحترافية.

typography.css
/* ══ استيراد Google Fonts — في أول الـ CSS قبل أي حاجة ══ */
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;700;900&family=Space+Mono&display=swap');
/* display=swap: بيعرض fallback font حتى الخط يتحمّل */

body {
  /* Font Stack: لو الخط الأول مش موجود بيروح للثاني وهكذا */
  font-family: 'Cairo', 'Arial', sans-serif;

  /* Base size: كل rem بيتحسب منها (16px = 1rem) */
  font-size: 16px;

  /* Line-height: المسافة بين الأسطر — بدون وحدة أفضل */
  /* 1.7 يعني 1.7 × font-size = 27.2px مسافة بين الأسطر */
  line-height: 1.7;
}

h1 {
  /* clamp(min, preferred, max) — أقوى طريقة للـ font-size */
  /* أصغر من 2rem مستحيل — أكبر من 5rem مستحيل */
  /* بينهم بيتمدد بنسبة 5vw من عرض الشاشة */
  font-size: clamp(2rem, 5vw, 5rem);

  font-weight: 900; /* 100=خفيف جداً، 400=عادي، 700=بولد، 900=ثقيل */
  letter-spacing: -2px; /* المسافة بين الحروف — سالب = أكثر تقارباً */
  line-height: 1.1;     /* عناوين بتحتاج line-height أصغر */
}

/* ══ Gradient Text — تأثير احترافي جداً ══ */
/* 3 properties لازم يكونوا مع بعض عشان يشتغل */
.gradient-text {
  background: linear-gradient(90deg, #2965f1, #00d4ff);
  -webkit-background-clip: text; /* قص الـ background على شكل النص */
  background-clip: text;
  -webkit-text-fill-color: transparent; /* بيخلي لون النص شفاف عشان الـ bg يظهر */
}

/* ══ Text Glow — نص بيضيء ══ */
.glow-text {
  text-shadow:
    0 0 20px rgba(41,101,241,0.8),  /* ظل قريب وقوي */
    0 0 40px rgba(41,101,241,0.4); /* ظل بعيد وخفيف */
}

/* ══ Truncate: نص طويل بيتقطع بـ ... ══ */
/* الثلاثة مع بعض إلزامية عشان يشتغل */
.truncate {
  white-space:   nowrap;    /* منع الـ line break */
  overflow:      hidden;    /* إخفاء ما يتجاوز الحدود */
  text-overflow: ellipsis; /* إضافة الـ ... */
}

/* ══ وحدات الحجم — مهمة تفهمها ══ */
/* px  = ثابت دايماً، مش responsive */
/* rem = نسبة من html font-size (عادة 16px) */
/*       1.5rem = 24px — بيتأثر بـ zoom المستخدم */
/* em  = نسبة من font-size الـ parent */
/*       1.5em على h2 = 1.5 × حجم font-size الـ parent */
/* vw  = نسبة من عرض الشاشة (100vw = عرض الشاشة) */
/* vh  = نسبة من ارتفاع الشاشة (100vh = ارتفاع الشاشة) */
معاينة Typography
عنوان ضخم — font-weight:900
نص عادي خفيف للمحتوى — font-weight:300, line-height:1.7
Gradient Text Effect ✨
Glow Text Effect 🌟
نص طويل جداً بيتقطع بـ ... لأنه بيتجاوز العرض المتاح
💡
نصيحة Google Fonts

بدل @import، استخدم <link> في الـ HTML. الـ link بيحمّل بشكل متوازي، والـ @import بيحمّل الـ CSS أولاً بعدين الخط. الفرق في السرعة ملحوظ على الاتصالات البطيئة. كمان، حمّل الـ weights اللي محتاجها بس — مش كل الـ weights.

07
// CSS VARIABLES

CSS Variables — Custom Properties

أقوى feature في CSS الحديث — كود قابل للصيانة والتغيير
⚡ احترافي جداً

تخيل إن عندك 200 عنصر كلهم لونهم #2965f1. القرار فجأة: نغيّر اللون الأساسي لـ أخضر. بدون Variables: بتفتح كل ملف CSS وبتعمل find & replace وبتدعي إنك ماعملتش غلطة. مع Variables: بتغيّر سطر واحد وكل الـ 200 عنصر بيتغيّروا تلقائياً.

variables.css
/* ══ تعريف المتغيرات في :root ══ */
/* :root هو الـ html element — أعلى مستوى */
/* أي متغير هنا بيكون متاح في كل الصفحة */
:root {
  /* الألوان — اسمية واضحة */
  --primary:       #2965f1;
  --primary-dim:   rgba(41,101,241, 0.1);
  --primary-glow:  rgba(41,101,241, 0.4);
  --accent:        #00d4ff;
  --bg:            #020508;
  --surface:       #080c16;
  --text:          #e8eaf6;
  --text-muted:    #7a8baa;
  --green:         #00e676;
  --pink:          #e91e8c;
  --gold:          #f0b429;

  /* Border radius — اتساق في الزوايا */
  --r-sm:  6px;
  --r-md:  12px;
  --r-lg:  24px;
  --r-full: 9999px; /* دائري كامل */

  /* المسافات — نظام موحد */
  --gap-xs: 4px;
  --gap-sm: 8px;
  --gap-md: 16px;
  --gap-lg: 32px;

  /* الخطوط */
  --font-ar:   'Cairo', sans-serif;
  --font-mono: 'Space Mono', monospace;

  /* Transition موحد للأنيميشن */
  --transition:     all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  --transition-slow: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* ══ استخدامها ══ */
.btn-primary {
  background:    var(--primary);
  color:         white;
  padding:       var(--gap-sm) var(--gap-md);
  border-radius: var(--r-sm);
  font-family:   var(--font-ar);
  transition:    var(--transition);
}
.btn-primary:hover {
  box-shadow: 0 0 20px var(--primary-glow); /* يضيء بلون الـ primary */
  transform: translateY(-2px);
}

/* ══ Dark / Light Mode بـ Variables ══ */
/* الـ default = dark mode */
/* لو المستخدم ضغط على زرار الـ toggle، 
   JavaScript بتحط data-theme="light" على الـ html */
[data-theme="light"] {
  --bg:       #f8f9fa;
  --surface:  #ffffff;
  --text:     #1a1a2e;
  --text-muted: #6b7280;
  /* باقي المتغيرات بتفضل زي ما هي */
}

/* ══ تغيير Variable بـ JavaScript ══ */
/* document.documentElement.style.setProperty('--primary', '#e91e8c'); */
/* الكود ده بيغيّر --primary للـ pink فوراً بدون reload */

/* ══ Fallback Value: لو المتغير مش موجود ══ */
.el {
  color: var(--brand-color, #2965f1); /* لو --brand-color مش معرّف، يستخدم الـ fallback */
}

الفرق بين CSS Variables وـ Sass Variables: Sass Variables ($color: blue;) بتتحوّل لـ values ثابتة وقت الـ compile — مش ممكن تغيّرها بـ JavaScript أو بـ media query. CSS Variables (--color: blue;) بتكون حية في المتصفح — JavaScript تقدر تغيّرها، ويورثها العناصر الأبناء، وتتغيّر مع الـ media queries.

⚠️
مطبات برمجية شائعة — الوحدة الثانية

1. استخدام Variable قبل ما تتعرّف

/* مفيش error — لكن القيمة بتبقى فاضية تماماً */ .btn { color: var(--primary); } /* --primary لسه ما اتعرفتش في :root */
الحل: لازم تعرّف كل الـ CSS Variables في :root في بداية الملف قبل ما تستخدمها في أي مكان. لو نسيت، الخاصية هتاخد قيمتها الافتراضية (initial) من المتصفح — مش error واضح، بس النتيجة البصرية هتبقى غريبة وصعب تكتشف السبب.

2. نسيان وحدة القياس مع الأرقام

/* مفيش error — لكن الخاصية بتتجاهل تماماً */ .box { width: 300; padding: 20; } /* المفروض 300px و20px */
الحل: كل قيمة رقمية في CSS (إلا line-height والـ z-index وبعض الاستثناءات) لازم يكون معاها وحدة قياس — px أو rem أو % أو vw. لو نسيتها، CSS بتتجاهل الخاصية كلها بصمت زي ما لو ماكتبتهاش خالص.

3. -webkit-background-clip بدون background-clip العادية

/* الـ Gradient Text بيختفي تماماً في بعض المتصفحات */ .gradient-text { -webkit-background-clip: text; -webkit-text-fill-color: transparent; /* نسيت background-clip: text العادية! */ }
الحل: دايماً حط الخاصية القياسية (background-clip: text) جنب الـ vendor-prefixed (-webkit-background-clip). بعض المتصفحات لسه محتاجة الـ prefix، لكن المعيار الرسمي هو النسخة بدون -webkit، وتجاهلها قد يكسر الستايل في تحديثات المتصفح المستقبلية.
TASK 02
ابنِ Design System بـ CSS Variables
الوحدة الثانية · الألوان والخطوط
  • عرّف CSS Variables كاملة في :root للـ portfolio: ألوان primary وsurface وtext، مسافات، border-radius، fonts
  • استورد Google Font مناسب بـ <link> في الـ HTML وطبّقه على الـ body
  • طبّق gradient background على الـ hero section وgradient text على اسمك
  • استخدم clamp() لـ font-size الـ h1 يكون responsive من غير media queries
  • نفّذ Light/Dark Mode: زرار toggle بـ JavaScript يضيف data-theme="light" على الـ html
  • استخدم color-mix() لعمل تدرج من الـ primary color
Portfolio Step 2 — Design Systemالـ portfolio دلوقتي عنده هوية بصرية واضحة: ألوان ثابتة، خطوط محددة، نظام spacing موحد.
  • "coolors.co" — أداة مجانية لتوليد color palettes متناسقة
  • "oklch.com" — color picker لـ OKLCH مع تحويل من HEX
  • "Google Fonts specimen" — اختبر كيف يبان الخط قبل ما تستخدمه
UNIT 03
03
// UNIT THREE
Flexbox & CSS Grid — تخطيط الصفحة
قبل 2012، كان المبرمجين بيبنوا layout بـ floats وهاك — كان ألم حقيقي. Flexbox وGrid غيّروا كل حاجة. هنتعلم الاتنين بالكامل وهنعرف إمتى نستخدم إيه.
3 دروس1 مطب برمجي1 تاسك~75 دقيقة
08
// DISPLAY & POSITION

Display & Position

الأساس — إزاي العناصر بتتموضع في الصفحة

كل عنصر HTML عنده display افتراضي — h1 هو block، span هو inline. لما بتغيّر الـ display بتغيّر طريقة تفاعل العنصر مع غيره.

Display Valueماذا يعني؟
blockيأخد سطر كامل، يقبل width وheight
inlineيأخد حجم محتواه بس، مش بيقبل width/height
inline-blockinline في التدفق + يقبل dimensions
flexالتخطيط المرن — الدرس الجاي
gridالتخطيط الشبكي — بعد Flexbox
noneبيختفي كامل ومش بياخد مساحة
Position Valueماذا يعني؟
staticالافتراضي — بيتبع تدفق الصفحة العادي
relativeبيتبع التدفق + تقدر تحرّكه بـ top/left
absoluteيطلع من التدفق — يتموضع نسبياً للـ parent
fixedثابت بالنسبة للشاشة — مش بيتحرك مع الـ scroll
stickyrelative حتى يوصل لـ threshold معين، بعدين يبقى fixed
position.css
/* ══ Pattern الأشهر: توسيط عنصر بـ absolute ══ */
/* الـ parent لازم يكون relative عشان الـ child يتموضع نسبياً ليه */
.parent { position: relative; }

.child-centered {
  position: absolute;
  top: 50%;    /* 50% من ارتفاع الـ parent */
  left: 50%;   /* 50% من عرض الـ parent */
  transform: translate(-50%, -50%);
  /* translate(-50%) بينقل العنصر لورا بنص حجمه، فيبقى في المنتص تماماً */
}

/* ══ Navbar ثابت فوق الصفحة ══ */
.navbar {
  position: fixed;
  top: 0; left: 0; right: 0; /* يمتد على كل العرض */
  z-index: 1000; /* يطلع فوق كل العناصر التانية */
  /* لازم تضيف padding-top على body بيساوي height الـ navbar */
  /* عشان المحتوى ما يتغطاش */
}

/* ══ Sticky sidebar — يتبع الـ scroll لحد نقطة معينة ══ */
.sidebar {
  position: sticky;
  top: 80px; /* لما يوصل لـ 80px من أعلى الشاشة يبقى fixed */
}

/* ══ z-index: مين فوق مين؟ ══ */
/* الأرقام الأعلى = فوق */
.modal   { z-index: 2000; }  /* فوق الـ navbar */
.tooltip { z-index: 1500; }
.navbar  { z-index: 1000; }
/* z-index بيشتغل بس على positioned elements (مش static) */
⚠️
z-index مش بيشتغل؟

الأكثر شيوعاً: نسيت تحط position على العنصر. z-index بيشتغل بس على العناصر اللي عندها position غير static (relative, absolute, fixed, sticky). حط position: relative وهيشتغل.

09
// FLEXBOX

Flexbox — التخطيط المرن

أداة الـ layout رقم 1 — navbar، cards، أي عناصر في صف أو عمود
⚡ الأكثر استخداماً

Flexbox بيشتغل على محورين: المحور الرئيسي (Main Axis) والمحور المتعامد (Cross Axis). الـ flex-direction بتحدد إيه المحور الرئيسي — row (أفقي) أو column (عمودي). وعشان ده، justify-content بيتحكم في المحور الرئيسي، وalign-items في المتعامد.

// جرّب بنفسك — الأزرار بتغيّر الـ CSS فعلياً
1
2
3
justify-content: flex-start
align-items: stretch
flex-direction: row
flexbox.css
/* ══ الـ Container (الأب) — هنا بتعرّف الـ flex ══ */
.flex-container {
  display: flex; /* بيحوّل الأبناء المباشرين لـ flex items */

  /* المحور: row=أفقي (افتراضي) | column=عمودي */
  flex-direction: row;

  /* التوزيع على المحور الرئيسي */
  justify-content: flex-start; /* البداية */
  justify-content: center;     /* وسط */
  justify-content: flex-end;   /* النهاية */
  justify-content: space-between; /* مسافات بين العناصر */
  justify-content: space-evenly;  /* مسافات متساوية */

  /* التوزيع على المحور المتعامد */
  align-items: stretch;    /* (افتراضي) — يتمدد ليملأ */
  align-items: center;     /* وسط — لتوسيط عمودي! */
  align-items: flex-start; /* أعلى */
  align-items: flex-end;   /* أسفل */

  /* الـ wrap: لما الأبناء مش بيدخلوا في صف واحد */
  flex-wrap: nowrap;  /* (افتراضي) — يضغط الكل في صف واحد */
  flex-wrap: wrap;    /* ينزل لسطر جديد لو مش في مساحة */

  /* المسافة بين الأبناء */
  gap: 16px;         /* بين كل العناصر */
  gap: 16px 8px;   /* row-gap | column-gap */
}

/* ══ الـ Items (الأبناء) ══ */
.flex-item {
  /* flex هو shorthand لـ: flex-grow | flex-shrink | flex-basis */
  flex: 1;      /* يتوسع ليملأ المساحة المتاحة */
  flex: 0 0 200px; /* لا يتوسع، لا يتقلص، عرضه 200px */
  flex: none;  /* = 0 0 auto: مش بيتغير */

  /* يتجاوز align-items بتاع الـ container لهذا العنصر بس */
  align-self: center;

  /* ترتيب العرض — بدون تغيير الـ HTML */
  /* 0 = الافتراضي، أصغر = يجي أول */
  order: -1; /* هيجي قبل باقي العناصر */
}

/* ══ Patterns شائعة جداً ══ */

/* Pattern 1: Navbar — logo على اليمين، روابط على اليسار */
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  height: 64px;
}

/* Pattern 2: توسيط تام أفقي وعمودي */
.fully-centered {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

/* Pattern 3: Cards Row بتتكسر على الموبايل */
.cards-row {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.cards-row .card {
  flex: 1 1 calc(33% - 14px); /* 3 في صف على ديسكتوب */
  min-width: 250px;             /* على موبايل: عمود واحد */
}
10
// CSS GRID

CSS Grid — التخطيط الشبكي

أقوى نظام layout في CSS — أعمدة وصفوف في نفس الوقت
⚡ الأقوى في الـ Layout

Flexbox vs Grid — إمتى تستخدم إيه؟

  • Flexbox: لما عندك عناصر في صف واحد أو عمود واحد وعايز تتحكم في توزيعهم ومحاذاتهم — navbar، قائمة أفقية، row من cards.
  • Grid: لما عندك layout ثنائي الأبعاد — أعمدة وصفوف مع بعض. Page layout، gallery، dashboard. ممكن تستخدم Grid للـ container وFlexbox جوّا كل card.
// جرّب الأعمدة — بتغيّر grid-template-columns فعلياً
1
2
3
4
5
6
grid.css
/* ══ Grid الأساسي ══ */
.grid {
  display: grid;

  /* grid-template-columns: بتحدد عدد وعرض الأعمدة */
  grid-template-columns: repeat(3, 1fr); /* 3 أعمدة متساوية */
  grid-template-columns: 200px 1fr 200px; /* sidebar | main | sidebar */
  grid-template-columns: 1fr 2fr; /* العمود الثاني ضعف الأول */

  gap: 20px;
}

/* ══ الـ fr — وحدة CSS Grid الخاصة ══ */
/* fr = fraction = جزء من المساحة المتاحة */
/* 1fr 2fr 1fr = المساحة بتتقسم 4 أجزاء: 1 + 2 + 1 */
/* الأول ياخد ربع، الأوسط نص، الثالث ربع */

/* ══ auto-fill + minmax: Responsive بدون media queries! ══ */
.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  /* auto-fill: المتصفح بيقرر عدد الأعمدة */
  /* minmax(250px, 1fr): كل عمود مش أصغر من 250px، مش أكبر من 1fr */
  /* على موبايل: يضغط لعمود واحد لما 250px مش بتدخل */
  /* على ديسكتوب: 3 أو 4 أعمدة حسب العرض */
  gap: 20px;
}

/* ══ Template Areas: اسمِ الأجزاء ══ */
/* طريقة بصرية جداً لتعريف الـ layout */
.page-layout {
  display: grid;
  grid-template-areas:
    "header  header"   /* header يمتد عمودين */
    "sidebar main"     /* sidebar يسار، main يمين */
    "footer  footer";  /* footer يمتد عمودين */
  grid-template-columns: 270px 1fr;
  grid-template-rows:    auto 1fr auto;
  min-height: 100vh;
}
/* كل element بياخد اسمه من المنطقة */
.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }

/* ══ Span: عنصر يمتد على أعمدة أو صفوف ══ */
.full-width  { grid-column: 1 / -1; }     /* من أول لآخر عمود */
.spans-two   { grid-column: span 2; }   /* يمتد عمودين */
.tall-item   { grid-row:    span 2; }   /* يمتد صفين */
.big-feature {
  grid-column: 1 / 3;  /* من عمود 1 لعمود 3 */
  grid-row:    1 / 3;    /* من صف 1 لصف 3 */
}

repeat(auto-fill, minmax(250px, 1fr)) — أقوى سطر CSS ممكن تكتبه للـ responsive. المتصفح بيقرر تلقائياً عدد الأعمدة حسب المساحة المتاحة. لو الشاشة ضيقة: عمود واحد. لو متوسطة: اتنين. لو واسعة: ثلاثة أو أكثر. كل ده بسطر واحد وبدون أي media queries.

⚠️
مطبات برمجية شائعة — الوحدة الثالثة

1. نسيان display: flex على الـ parent

/* مفيش error — لكن justify-content وalign-items مش بيعملوا حاجة */ .container { justify-content: center; align-items: center; /* نسيت display: flex! */ }
الحل: خصائص Flexbox (justify-content، align-items، gap، flex-wrap) بتشتغل بس لو الـ parent عنده display: flex. من غيرها، المتصفح بيتجاهل الخصائص دي بصمت تماماً وكأنك ماكتبتهاش.

2. z-index مش بيشتغل

/* مفيش error — لكن العنصر مش بيطلع فوق رغم z-index عالي */ .modal { z-index: 9999; } /* العنصر لسه تحت عناصر تانية! */
الحل: z-index بيشتغل بس على العناصر اللي عندها position غير static (relative، absolute، fixed، sticky). لو العنصر position: static (الافتراضي)، z-index بيتجاهل تماماً. أضف position: relative (أو أي قيمة تانية غير static) وهيشتغل فوراً.

3. Grid columns أكتر من المساحة المتاحة

/* مفيش error — لكن Horizontal Scrollbar غير مرغوب فيه يظهر */ .grid { display: grid; grid-template-columns: repeat(4, 300px); /* 4×300px = 1200px قد ييجي أعرض من الشاشة */ }
الحل: استخدم 1fr بدل أرقام px ثابتة لما عايز الأعمدة تتمدد مع المساحة المتاحة، أو استخدم minmax() مع auto-fill للـ responsive التلقائي. أرقام px ثابتة بتفضل ثابتة بغض النظر عن حجم الشاشة وده بيسبب overflow أفقي غير مرغوب.
TASK 03
صمّم Navbar وقسم Projects بـ Grid
الوحدة الثالثة · Flexbox & Grid
  • صمّم الـ navbar بـ Flexbox: logo على اليمين، روابط على اليسار، توسيط عمودي
  • اجعل الـ navbar fixed أعلى الصفحة مع backdrop-filter: blur(16px)
  • صمّم قسم Projects بـ Grid مع auto-fill وminmax
  • استخدم grid-template-areas للـ page layout: header + sidebar + main + footer
  • اعمل Holy Grail layout كامل بـ Grid Areas
  • جرّب Masonry-like layout بـ grid-row: span للـ cards بأحجام مختلفة
Portfolio Step 3 — Layoutالـ portfolio دلوقتي عنده navbar احترافي ثابت وprojects grid responsive.
  • "Flexbox Froggy" — لعبة بتتعلم فيها Flexbox بطريقة ممتعة
  • "CSS Grid Garden" — نفس الفكرة لـ Grid
  • "backdrop-filter glassmorphism CSS tutorial"
UNIT 04
04
// UNIT FOUR
Animations & Transitions
الفرق بين موقع جامد وموقع حي هو الحركة. هنتعلم 3 طرق مختلفة لإضافة حركة: Transitions (حركة بين حالتين)، Transforms (تغيير الشكل)، وKeyframes (animation كاملة).
3 دروس1 مطب برمجي1 تاسك~60 دقيقة
11
// TRANSITIONS

Transitions — حركة بين حالتين

أبسط وأشيع طريقة لإضافة حياة للعناصر

Transition بيقول للـ CSS: "لما أي property تتغير، مش تتغير فجأة — خد وقت ومشي بـ curve معينة". أشيع استخدام: hover effects على الأزرار والـ cards.

hover me
ease .3s
scale + rotate
hover me
bounce
cubic-bezier
hover me
linear
skew
hover me
ease .8s
border-radius
transitions.css
/* ══ الـ transition property ══ */
/* transition: property | duration | timing-function | delay */
.btn {
  background: var(--primary);
  color: white;
  /* all = كل property بتتغير هتتحرك */
  transition: all 0.25s ease;
}
.btn:hover {
  background: var(--accent);
  transform: translateY(-3px);
  box-shadow: 0 8px 24px rgba(41,101,241,0.4);
}

/* أفضل: حدد الـ properties بدل all — أسرع للـ browser */
.card {
  transition:
    transform    0.3s ease,     /* كل property على سطر */
    box-shadow   0.3s ease,
    border-color 0.2s ease;
}

/* ══ Timing Functions — الـ curve اللي بتتحرك عليها ══ */
transition-timing-function: ease;        /* سريع في الأول يهدأ في الآخر */
transition-timing-function: linear;     /* سرعة ثابتة */
transition-timing-function: ease-in;    /* يبدأ بطيء يسرع */
transition-timing-function: ease-out;   /* يبدأ سريع يهدأ */
transition-timing-function: ease-in-out;/* يبدأ بطيء، يسرع، يهدأ */
/* cubic-bezier: أي curve تخيلها — موقع cubic-bezier.com يساعدك */
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* bounce! */

/* ══ Accessibility: احترم من عنده مشكلة مع الحركة ══ */
/* بعض المستخدمين بيعانوا من الدوار مع الـ animations */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration:  0.01ms !important;
  }
}
12
// TRANSFORMS

Transforms — تغيير الشكل

تحريك، تدوير، تكبير — بدون تأثير على باقي العناصر

Transform بيغيّر المظهر البصري للعنصر بدون ما يأثر على مكانه الفعلي في التخطيط. يعني العناصر التانية مش بتعرف إن العنصر اتحرك — مساحته الأصلية فاضية. ده بيخليه أسرع في الـ rendering لأنه بيشتغل على الـ GPU مباشرةً.

transforms.css
.el {
  /* ── translate: تحريك العنصر من مكانه ── */
  transform: translateX(50px);    /* يمين 50px */
  transform: translateX(-50px);   /* يسار */
  transform: translateY(-10px);   /* فوق — ده الـ hover lift الشائع */
  transform: translate(20px, -10px); /* X وY مع بعض */
  transform: translate(-50%, -50%);
  /* الـ % بتتحسب من حجم العنصر نفسه */
  /* ده أشيع pattern للتوسيط مع position absolute */

  /* ── scale: تكبير أو تصغير ── */
  transform: scale(1.1);     /* 10% أكبر */
  transform: scale(0.95);    /* 5% أصغر — لـ click press effect */
  transform: scaleX(1.5);   /* يكبر أفقياً بس */
  transform: scaleY(0);     /* يختفي عمودياً — collapse effect */

  /* ── rotate: تدوير ── */
  transform: rotate(45deg);   /* 45 درجة عكس عقارب الساعة */
  transform: rotate(-45deg);  /* مع عقارب الساعة */
  transform: rotate(0.5turn); /* نص لفة = 180 درجة */

  /* ── skew: إمالة ── */
  transform: skewX(-10deg);   /* ميل أفقي */
  transform: skewY(5deg);     /* ميل عمودي */

  /* ── دمج transforms: بالترتيب من اليمين لليسار ── */
  transform: translateY(-5px) scale(1.03) rotate(1deg);

  /* ── transform-origin: نقطة التحويل ── */
  /* الافتراضي center — ممكن تغيّرها لأي زاوية */
  transform-origin: top left;    /* scale من الزاوية العلوية اليسرى */
  transform-origin: center bottom; /* rotate من الأسفل */
}

/* ══ مثال عملي: Card Hover Effect ══ */
.project-card {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.project-card:hover {
  transform: translateY(-8px) scale(1.01);
  box-shadow: 0 20px 40px rgba(0,0,0,0.3);
}
transform vs margin/top/left: لو عندك animation وعايزها smooth وسريعة، استخدم transform وopacity دايماً. المتصفح بيعمل "compositing" ليهم على الـ GPU مباشرةً من غير ما يعيد حساب الـ layout كله. أما margin وwidth وleft وtop فبتسبب "reflow" — إعادة حساب مواضع كل العناصر — وده بيخلي الـ animation مش ناعمة خصوصاً على الموبايل.
13
// KEYFRAMES

Keyframe Animations

@keyframes — حركة كاملة بتتحكم فيها خطوة خطوة
⚡ مذهل

Transitions بتعمل حركة بين حالتين (عادي ← hover). لو محتاج حركة أكثر تعقيداً — animation تتكرر وحدها، أو تمر بأكثر من حالتين — هنا Keyframes بييجي.

spin
rotate(360deg)
bounce
translateY
shake
translateX
pulse
scale
color
background
glow
box-shadow
keyframes.css
/* ══ تعريف الـ Animation ══ */
/* from/to = بداية ونهاية فقط */
@keyframes fadeUp {
  from {
    opacity:   0;
    transform: translateY(30px);
  }
  to {
    opacity:   1;
    transform: translateY(0);
  }
}

/* بالنسب المئوية لـ control كامل على كل مرحلة */
@keyframes bounce {
  0%   { transform: translateY(0); }
  30%  { transform: translateY(-20px); } /* طلوع */
  50%  { transform: translateY(0); }    /* نزول */
  70%  { transform: translateY(-10px); } /* ارتداد أصغر */
  100% { transform: translateY(0); }    /* نهاية */
}

/* ══ تطبيق الـ Animation ══ */
/* animation: name | duration | timing | delay | iteration | direction | fill-mode */
.hero-title {
  animation: fadeUp 0.6s ease 0.2s 1 normal both;
  /* both: بيطبق الـ from قبل ما تبدأ والـ to بعد ما تخلص */
}

.loader {
  animation: spin 1s linear infinite; /* تتكرر للأبد */
}

/* ══ Staggered: كل element يظهر بتأخير تدريجي ══ */
/* نفس الـ animation لكن delay مختلف لكل عنصر */
.card { animation: fadeUp 0.5s ease both; }
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }

/* ══ Skeleton Loading: مؤشر تحميل احترافي ══ */
/* بيبين إن المحتوى بيتحمّل بدل مربعات فاضية */
@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position:  200% 0; }
}
.skeleton {
  background: linear-gradient(90deg,
    #1a1a2e 25%,  /* لون داكن */
    #2a2a4e 50%,  /* لون أفتح شوية */
    #1a1a2e 75%   /* يرجع داكن */
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s ease-in-out infinite;
  border-radius: var(--r-sm);
}

/* ══ مثال: Floating Image Effect ══ */
@keyframes floating {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-12px); }
}
.profile-img {
  animation: floating 3s ease-in-out infinite;
}
⚠️
مطبات برمجية شائعة — الوحدة الرابعة

1. الـ transition على العنصر الغلط

/* مفيش error — لكن الـ hover effect مش بيكون smooth */ .btn:hover { transform: scale(1.1); transition: all .3s; } /* الـ transition هنا — لازم تكون على .btn نفسه مش على :hover */
الحل: الـ transition لازم تتحط على الحالة الأساسية (.btn) مش على حالة :hover. لو حطيتها بس على :hover، الانتقال بيشتغل بس وقت الدخول، لكن وقت الخروج (mouse leave) بيرجع فجأة بدون أي smoothness. القاعدة: .btn { transition: all .3s; } .btn:hover { transform: scale(1.1); }.

2. Animation مش بتشتغل من البداية

/* العنصر بيبان لمحة واحدة في حالته الطبيعية قبل الـ animation */ .card { animation: fadeUp 0.6s ease; } /* نسيت fill-mode: both أو forwards */
الحل: بدون animation-fill-mode: both (أو forwards)، العنصر بيرجع لحالته الأصلية (قبل الـ @keyframes) فور انتهاء الأنيميشن، وأحياناً بيبان "flash" غريب قبل ما الأنيميشن تبدأ. أضف both في نهاية الـ animation shorthand دايماً للـ entrance animations.

3. استخدام left/top بدل transform للحركة

/* الأنيميشن بطيئة ومتقطعة (laggy) خصوصاً على الموبايل */ .box:hover { left: 20px; transition: left .3s; }
الحل: خصائص زي left وtop وwidth وmargin بتجبر المتصفح يعيد حساب الـ Layout كامل (Reflow) في كل فريم من الأنيميشن — ده بطيء. استخدم transform: translateX(20px) بدلاً منها — بيشتغل على الـ GPU مباشرة وأسرع بكثير، خصوصاً مع animations متكررة أو على أجهزة ضعيفة.
TASK 04
أضف Animations للـ Portfolio
الوحدة الرابعة · Animations & Transitions
  • أضف transition على كل الأزرار والـ nav links — لما hover اللون يتغيّر بسلاسة
  • Card hover effect: translateY(-8px) + box-shadow بـ transition
  • @keyframes fadeUp على اسمك والوصف في الـ hero مع animation-delay
  • Staggered animation على الـ project cards — كل card تظهر بـ 0.1s تأخير عن السابقة
  • أضف prefers-reduced-motion كـ media query لإيقاف كل الـ animations
  • Skeleton loading animation على الـ project cards قبل ما تتحمّل
  • Floating animation على صورتك الشخصية في الـ hero
  • Typing animation على وصفك بـ @keyframes
Portfolio Step 4 — حياة وتفاعلالـ portfolio دلوقتي بيتحرك ومش ميت. الزائر بيحس بفرق حقيقي في التجربة.
  • "cubic-bezier.com" — بتعمل timing function مخصوصة وبتشوف شكلها
  • "CSS animation fill-mode both" — مهم جداً لفهم الـ both
  • "Intersection Observer API" — هتحتاجه في JS لتشغيل animations عند الـ scroll
UNIT 05
05
// UNIT FIVE
Responsive Design
أكثر من 60% من مستخدمي الإنترنت على الموبايل. لو موقعك مش responsive، نص الناس بترحل. هنتعلم إزاي نبني موقع يظهر صح على كل الأجهزة.
3 دروس1 مطب برمجي1 تاسك~60 دقيقة
14
// MEDIA QUERIES

Media Queries

CSS بيتغيّر بناءً على حجم الشاشة أو خصائص الجهاز
⚡ لازم تتقنه

Media Query بيقول: "لو الشاشة كبيرة (أو صغيرة، أو dark mode، أو أي condition)، طبّق الـ CSS ده". الصيغة: @media (condition) { CSS هنا }.

media-queries.css
/* ══ Breakpoints المعيارية ══ */
/* Mobile:  0px   — 639px  (مش محتاج media query - ده الـ base) */
/* Tablet:  640px — 1023px */
/* Desktop: 1024px — ∞     */

/* ── min-width: يطبق CSS من الحجم ده وما فوقه ── */
@media (min-width: 640px) {
  /* CSS بيتطبق على tablet وdesktop */
  .grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
  /* CSS بيتطبق على desktop بس */
  .grid { grid-template-columns: repeat(3, 1fr); }
  .hero h1 { font-size: 5rem; }
}

/* ── max-width: يطبق CSS لحد الحجم ده ── */
@media (max-width: 767px) {
  /* CSS بيتطبق على موبايل بس */
  .nav-links  { display: none; }
  .hamburger  { display: block; }
  .sidebar    { display: none; }
  .page-layout { grid-template-columns: 1fr; }
}

/* ── Media Queries لخصائص تانية (مش بس الحجم) ── */

/* المستخدم عنده dark mode في نظامه */
@media (prefers-color-scheme: dark) {
  :root { --bg: #0d1117; --text: #f0f6ff; }
}

/* المستخدم قلّل الـ animations في إعداداته */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* الجهاز مش بيدعم hover (موبايل/تابلت) */
@media (hover: none) {
  .tooltip { display: none; } /* tooltips ما تظهرش على touch devices */
}

/* الطابعة */
@media print {
  .navbar, .sidebar, .footer { display: none; }
  body { font-size: 12pt; color: #000; }
}

/* ── Range: بين حجمين بالظبط ── */
@media (640px <= width <= 1023px) {
  /* tablet بس — Modern syntax (2023+) */
}
ℹ️
Breakpoints مش ثابتة

الـ breakpoints اللي شرحناها (640px, 1024px) هي مجرد معيار شائع — مش قانون. بعض المشاريع بتستخدم 768px لـ tablet. الأهم إنك تختار breakpoints بناءً على محتوى موقعك نفسه، مش بناءً على أحجام أجهزة بعينها لأن الأجهزة بتتغير كل سنة.

15
// MOBILE FIRST

Mobile First Strategy

ابدأ بالموبايل — وسّع للشاشات الأكبر
⚡ Best Practice

في طريقتين للـ responsive design:

  • Desktop First (القديمة): تكتب CSS للـ desktop أولاً، وبعدين تضيف media queries بـ max-width لتقليلها على الموبايل.
  • Mobile First (الحديثة): تكتب CSS للموبايل أولاً — بدون media query — وبعدين تضيف media queries بـ min-width لتوسيعها على الشاشات الأكبر.

ليه Mobile First أحسن؟ أولاً: المتصفح بيقرأ CSS بالترتيب، الموبايل بياخد أقل كود (أسرع تحميل). ثانياً: أسهل في التفكير — تبني الـ base وتضيف عليه. ثالثاً: Google بيفضّل responsive Mobile First في الـ SEO. رابعاً: لو أضفت feature وما حطتهاش في mobile query، هتكون موجودة على كل الأجهزة تلقائياً.

mobile-first.css
/* ══ Mobile First: ابدأ بدون media query — ده للموبايل ══ */

/* Navbar: على الموبايل بسيط */
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 1rem;
  height: 58px;
}
.nav-links  { display: none; }   /* مخفي على موبايل */
.hamburger  { display: flex; }   /* ظاهر على موبايل */

/* Hero: عمودي على موبايل */
.hero h1    { font-size: 2.5rem; }
.hero       { padding: 2rem 1rem; text-align: center; }

/* Grid: عمود واحد على موبايل */
.projects-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  padding: 0 1rem;
}

/* ══ بعدين وسّع للـ Tablet ══ */
@media (min-width: 640px) {
  .projects-grid {
    grid-template-columns: repeat(2, 1fr);
    padding: 0 1.5rem;
  }
  .hero { text-align: start; }
}

/* ══ وبعدين للـ Desktop ══ */
@media (min-width: 1024px) {
  .navbar   { padding: 0 2rem; height: 64px; }
  .nav-links{ display: flex; }    /* يظهر على desktop */
  .hamburger{ display: none; }   /* يختفي على desktop */
  .hero h1  { font-size: 5rem; }
  .projects-grid {
    grid-template-columns: repeat(3, 1fr);
    padding: 0;
  }
  .page-layout {
    grid-template-columns: 270px 1fr;
  }
}
16
// FLUID UNITS

clamp() و vw و dvh والوحدات المرنة

CSS بتتكيف وحدها بدون media queries
⚡ Modern CSS

الـ Media Queries بتقفز بين قيم محددة — فجأة الـ font-size تقفز من 2.5rem لـ 5rem. clamp() بيخلي الـ value تتمدد بشكل سلس مع عرض الشاشة بدون قفزات.

fluid-units.css
/* ══ clamp(minimum, preferred, maximum) ══ */
/* المتصفح بيختار الـ preferred، لكن مش أقل من min ومش أكبر من max */
h1 {
  /* على موبايل 320px: font-size = max(2rem, min(5vw=16px, 5rem)) = 2rem */
  /* على tablet 768px: 5vw = 38.4px ≈ 2.4rem — بيتمدد */
  /* على desktop 1200px: 5vw = 60px ≈ 3.75rem — بيتمدد */
  /* فوق الحد: 5rem (80px) — بيتوقف */
  font-size: clamp(2rem, 5vw, 5rem);
}

.section-padding {
  padding: clamp(2rem, 8vw, 6rem); /* بيكبر مع الشاشة */
}

.container {
  max-width: min(1200px, 90vw); /* الأصغر من الاتنين */
  /* على شاشة 1400px: 90vw = 1260px — اختار 1200px */
  /* على موبايل 400px: 90vw = 360px — اختار 360px */
  margin: 0 auto;
  padding: clamp(1rem, 3vw, 3rem);
}

/* ══ Viewport Units ══ */
.hero {
  /* vh = viewport height */
  min-height: 100vh;   /* 100% من ارتفاع الشاشة */

  /* dvh = dynamic viewport height (2023+) */
  /* على الموبايل، الـ browser bar بتختفي عند الـ scroll */
  /* dvh بيحسب الارتفاع المتاح فعلياً، مش ارتفاع ثابت */
  /* بدونه: hero ممكن يتقطع وراء الـ address bar */
  min-height: 100dvh; /* ← استخدم ده دايماً للـ hero */
}

/* ══ Fluid Space System: نظام مسافات مرن ══ */
/* بدل ما تغيّر كل القيم في media queries، حدد variables مرنة */
:root {
  --space-xs: clamp(0.5rem,  1vw,  1rem);
  --space-sm: clamp(1rem,    2vw,  1.5rem);
  --space-md: clamp(1.5rem,  3vw,  2.5rem);
  --space-lg: clamp(2rem,    5vw,  4rem);
  --space-xl: clamp(3rem,    8vw,  6rem);
}

/* ══ Images دايماً Responsive ══ */
img {
  max-width: 100%;  /* مش تتجاوز حجم الـ container */
  height: auto;    /* بيحافظ على نسبة الارتفاع */
  object-fit: cover;   /* لتعبئة مساحة بدون تشويه */
  object-position: center; /* التوسيط في المساحة */
}
متى تستخدم clamp ومتى Media Queries؟ clamp لـ typography والـ spacing اللي بيتمدد بسلاسة. Media Queries لـ layout changes جذرية — زي تغيير عدد الأعمدة أو إخفاء عناصر كاملة. الأفضل: الاتنين مع بعض. Grid + auto-fill للـ cards (بدون media queries)، وMedia Queries للـ navbar والـ sidebar.
⚠️
مطبات برمجية شائعة — الوحدة الخامسة

1. نسيان viewport meta tag في الـ HTML

/* مفيش error في CSS — لكن كل الـ media queries مش بتشتغل صح */ /* الصفحة بتبان "مصغّرة" على الموبايل رغم وجود breakpoints */
الحل: ده غلط في HTML مش CSS، لكنه بيكسر كل الـ Responsive Design. بدون <meta name="viewport" content="width=device-width, initial-scale=1.0"> في <head>، المتصفح بيحاكي شاشة desktop عريضة على الموبايل، فكل media queries بـ max-width بتتجاهل عملياً.

2. الترتيب الغلط لـ Media Queries (Desktop First بالغلط)

/* مفيش error — لكن الـ style بيتلخبط بسبب الـ Cascade */ .box { color: blue; } @media (min-width: 1024px) { .box { color: red; } } @media (min-width: 640px) { .box { color: green; } } /* على شاشة 1200px: اللون النهائي green مش red! */
الحل: في Mobile First، الـ media queries لازم تترتب من الأصغر للأكبر (640px قبل 1024px) لأن CSS بتطبق آخر قاعدة متطابقة. لو كتبتهم بترتيب عكسي، الـ query الأكبر هتتلغي بالـ query الأصغر اللي جاي بعدها في الكود حتى لو الشاشة فعلياً أعرض من الاتنين.

3. استخدام vh بدل dvh على الموبايل

/* مفيش error — لكن الـ Hero بيتقطع وراء شريط عنوان المتصفح */ .hero { min-height: 100vh; } /* على موبايل، address bar بتاخد جزء من الـ 100vh */
الحل: على متصفحات الموبايل، الـ address bar بتظهر وتختفي مع الـ scroll، وده بيخلي 100vh تتغير قيمتها الفعلية باستمرار. استخدم min-height: 100dvh (Dynamic Viewport Height) بدلاً منها — بتحسب الارتفاع المتاح فعلياً في كل لحظة.
TASK 05
اجعل الـ Portfolio Responsive كامل
الوحدة الخامسة · Responsive Design
  • حوّل الـ CSS للـ Mobile First: اكتب base styles للموبايل، بعدين أضف min-width queries
  • الـ navbar: روابطها تختفي على الموبايل — hamburger icon يظهر بدلها
  • الـ hero h1: استخدم clamp() لـ font-size مرن بدون media query
  • الـ hero: استخدم min-height: 100dvh
  • اختبر على DevTools: اضغط Ctrl+Shift+M لـ device simulation — جرّب iPhone وiPad وDesktop
  • نفّذ Hamburger menu يفتح ويقفل بـ CSS فقط باستخدام :checked
  • أضف @media (prefers-color-scheme: dark) لـ automatic dark mode
  • استخدم clamp() لـ section padding كمان
Portfolio Step 5 — Responsiveالـ portfolio دلوقتي بيشتغل على كل الأجهزة. جاهز للنشر على GitHub Pages!
  • "CSS clamp calculator utopia.fyi" — أداة بتحسب clamp values مثالية
  • "Responsively App" — تطبيق مجاني بيعرض موقعك على كذا جهاز في نفس الوقت
  • "CSS-only hamburger menu tutorial"
UNIT 06
06
// UNIT SIX
Modern CSS 2026 — الاحتراف
الفرق بين مبتدئ ومحترف مش في عدد الـ properties اللي يعرفها. ده في فهم Specificity لما الكود ما يشتغلش، وفي معرفة الـ Pseudo لإضافة تأثيرات بدون HTML زيادة، وفي Nesting و:has() اللي وفّرت ساعات من الكود.
5 دروس1 مطب برمجي1 تاسك~90 دقيقة
17
// SPECIFICITY

Specificity & Cascade

ليه الـ CSS اللي كتبته مش بيشتغل؟ الجواب هنا 90% من الوقت
⚡ يحل 80% من المشاكل

لما تكتب CSS وتشوفه مش بيتطبق، السبب الأكثر شيوعاً هو Specificity. المتصفح بيحسب "ثقل" كل rule، والأثقل بيفوز بغض النظر عن الترتيب.

الحساب بيتم في 4 أرقام مرتبة: Inline | ID | Class/Pseudo | Element

!important — فوق كل حاجة
احتياط أخير — تجنبه!
style="" inline
1-0-0-0
#id selector
0-1-0-0
.class / :pseudo-class / [attr]
0-0-1-0
element: p, h1, div
0-0-0-1
* universal selector
0-0-0-0
specificity.css
/* ══ الحساب ══ */
p                  { color: black;  } /* 0-0-0-1: عنصر واحد */
.text              { color: blue;   } /* 0-0-1-0: class واحد — يفوز على p */
#content .text p   { color: red;    } /* 0-1-1-1: id+class+element — يفوز */
.nav .link:hover   { color: green;  } /* 0-0-2-0: class + pseudo-class */

/* ══ الـ Cascade: لما الـ Specificity متساوية ══ */
/* الأخير في الملف يفوز — CSS بيقراه من فوق لتحت */
p { color: red; }
p { color: blue; } /* يفوز لأنه جاي بعده */

/* ══ Inheritance: الخصائص اللي بتورثها الأبناء ══ */
/* بترث: color, font-family, font-size, line-height, text-align */
/* مش بترث: margin, padding, border, background, display */
body { color: #333; }
/* كل العناصر داخل body هترث color = #333 */
/* إلا لو عندهم rule بيتجاوز ده */

/* ══ Keywords خاصة للـ Inheritance ══ */
.card-link {
  color: inherit;   /* ورّث من الـ parent صراحةً */
  color: initial;  /* ارجع للـ browser default */
  color: unset;    /* لو قابلة للإرث: inherit / لو لأ: initial */
  all: unset;      /* إعادة تعيين كل الـ properties */
}

/* ══ !important: استخدامه الصح ══ */
/* المفروض تجنبه — بيشير إن التصميم عنده مشكلة */
/* الاستخدام المقبول الوحيد: override third-party CSS */
.utility-hidden { display: none !important; }
/* utility classes محتاجة !important عشان دايماً تتطبق */

/* ══ Debugging: ليه الـ CSS مش بيشتغل؟ ══ */
/* 1. افتح DevTools ← Elements ← Styles */
/* 2. لو الـ property فيها خط: مكسورة أو override */
/* 3. شوف إيه اللي بيفوز وليه — هتشوف الـ specificity */
/* 4. specificity calculator: keegan.st/tool/css-specificity-graph */
⚠️
الحل الصح لمشاكل الـ Specificity

مش إضافة !important. الحل: إعادة هيكلة الـ CSS — استخدم classes بدل IDs، وقلّل من التعشيش. لو عندك .nav .link .icon بتحتاج 3 levels لتحديد element، في مشكلة في الـ CSS architecture.

18
// PSEUDO

Pseudo-Classes & Pseudo-Elements

تأثيرات واستهداف متقدم بدون إضافة HTML زيادة

Pseudo-Class بتستهدف عنصر في حالة معينة: :hover، :first-child، :invalid. بتبدأ بـ colon واحدة :

Pseudo-Element بيعمل عنصر وهمي جوّا أو قبل/بعد العنصر الحقيقي. بتبدأ بـ colon double ::

pseudo.css
/* ══ Pseudo-Classes المهمة ══ */

/* ── User Actions ── */
a:hover         { color: var(--primary); }
button:active   { transform: scale(0.97); } /* لما يضغط */
input:focus     { border-color: var(--primary); }
/* :focus-visible أفضل من :focus — بيظهر بس لما تنقّل بالـ keyboard */
a:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }

/* ── Form Validation ── */
input:valid    { border-color: var(--green); }
input:invalid  { border-color: red; }
input:required { border-left: 3px solid var(--gold); }
/* :invalid بيطبق من اللحظة الأولى — استخدم :user-invalid لبعد الـ blur */
input:user-invalid { border-color: red; }

/* ── Structural: بناءً على مكان العنصر في الـ DOM ── */
li:first-child      { border-top: none; }        /* أول عنصر */
li:last-child       { border-bottom: none; }     /* آخر عنصر */
tr:nth-child(even)  { background: rgba(0,0,0,.02); } /* صفوف الزوجية */
tr:nth-child(3n+1)  { color: var(--primary); }   /* كل 3: 1،4،7،10 */
p:not(.special)     { color: var(--text-muted); } /* كل p ما عندهاش .special */

/* ══ Pseudo-Elements ══ */

/* ── ::before و::after: عناصر وهمية قبل وبعد المحتوى ── */
/* content إلزامي — حتى لو فارغ */
.required-label::after {
  content: ' *';  /* نص بعد الـ label */
  color: red;
}

/* تأثير Underline ينمو من اليسار */
.nav-link {
  position: relative;
  text-decoration: none;
}
.nav-link::after {
  content: '';   /* فارغ — هو بس decoration */
  position: absolute;
  bottom: -2px; left: 0;
  width: 0;          /* يبدأ بعرض صفر */
  height: 2px;
  background: var(--primary);
  transition: width 0.3s ease;
}
.nav-link:hover::after {
  width: 100%;  /* يتمدد لكامل العرض */
}

/* ── ::placeholder, ::selection, ::marker ── */
input::placeholder { color: var(--text-dim); font-style: italic; }
::selection        { background: var(--primary); color: white; }
li::marker         { color: var(--primary); }

/* ── scroll-margin-top: مهم مع الـ sticky navbar ── */
/* لما تضغط anchor link، الصفحة بتسكرول بس الـ section بيتغطى بالـ navbar */
section { scroll-margin-top: 80px; } /* نفس ارتفاع الـ navbar */
19
// NESTING & :has()

CSS Nesting & :has() & :is()

مميزات 2023+ — بقت في كل المتصفحات الحديثة
⚡ مستقبل CSS

CSS Nesting بتخليك تكتب CSS بنفس أسلوب Sass — بدون أي preprocessor. و:has() هي أقوى selector جاء لـ CSS في تاريخها — بتختار عنصر بناءً على محتواه.

modern-css.css
/* ══ CSS Nesting (2023+) ══ */
/* بدل ما تكتب .card { } ثم .card h2 { } ثم .card:hover { } */
/* بتكتبهم كلهم جوّا بعض */

.card {
  background:    var(--surface);
  border-radius: var(--r-md);
  padding:       var(--gap-md);
  transition:    var(--transition);

  /* & = نفس الـ selector الخارجي (.card) */
  & h2 {                        /* = .card h2 */
    font-size: 1.2rem;
    color: var(--text);
    margin-bottom: var(--gap-xs);
  }

  & p {                         /* = .card p */
    color: var(--text-muted);
    font-size: 0.9rem;
  }

  &:hover {                     /* = .card:hover */
    transform:  translateY(-5px);
    box-shadow: 0 16px 32px rgba(0,0,0,0.3);
  }

  /* يمكن تعشيش Media Queries جوّا! */
  @media (max-width: 640px) {
    padding: var(--gap-sm);
  }
}

/* ══ :has() — "Parent Selector" ══ */
/* كانت CSS مش بتدعم "اختار الـ parent بناءً على الـ children" */
/* :has() حلّ ده — بتقول "اختار .card لو جوّاه img" */

/* form فيها input invalid — حطّ border حمراء على الـ form كلها */
.contact-form:has(input:invalid) {
  border-color: red;
}

/* section فيها صورة — حوّل الـ layout لـ 2 أعمدة */
.about-section:has(img) {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--gap-lg);
}

/* body لما mobile menu مفتوح — منع الـ scroll */
body:has(.mobile-menu.open) {
  overflow: hidden;
}

/* nav لما فيها active link — غيّر شكله */
.navbar:has(.nav-link.active) {
  border-bottom-color: var(--primary);
}

/* ══ :is() و :where() — selector shortcuts ══ */
/* بدل تكرار نفس الـ style لكل heading */
/* القديمة: */
/* h1 { } h2 { } h3 { } h4 { } */
/* الحديثة: */
:is(h1, h2, h3, h4) {
  font-weight: 700;
  line-height: 1.2;
  color: var(--text);
}
/* :is() بيرفع الـ specificity لأعلى selector جوّاه */
/* :where() نفس الفكرة بس specificity = 0 — أسهل للـ override */
:where(h1, h2, h3, h4) {
  font-weight: 700; /* أسهل تعمل override عليه */
}
20
// CONTAINER QUERIES

Container Queries

Responsive بناءً على حجم الـ container — مش الشاشة
⚡ 2023+ مدعوم

المشكلة في Media Queries: بتسأل "الشاشة قد إيه؟" مش "المكان اللي العنصر فيه قد إيه؟". يعني لو عندك نفس الـ card في sidebar ضيق وفي main area واسعة، الـ media query مش هتقدر تميّزهم.

Container Queries حلّت ده — بتسأل "الـ container الأب قد إيه؟". النتيجة: components مستقلة تتكيف مع مكانها تلقائياً.

container-queries.css
/* ══ الخطوة 1: حوّل العنصر لـ Container ══ */
/* أي element تحط عليه container-type يبقى container */
.card-wrapper {
  container-type: inline-size; /* يراقب العرض */
  /* container-type: size — يراقب العرض والارتفاع */
}

/* لو عايز تديه اسم */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

/* ══ الخطوة 2: اكتب Container Query ══ */
/* @container بدل @media */
@container (min-width: 400px) {
  /* لو الـ container أكبر من 400px */
  .project-card {
    display: flex;  /* أفقي */
    gap: var(--gap-md);
  }
  .project-card img {
    width: 40%;
    flex-shrink: 0;
  }
}
/* لو الـ container أصغر من 400px: عمودي (الـ default) */

/* ══ باسم محدد ══ */
@container sidebar (min-width: 250px) {
  /* بيطبق بس على العناصر جوّا .sidebar */
  .nav-item { flex-direction: row; }
}

/* ══ Container Query Units ══ */
.card-title {
  /* cqw = container query width */
  font-size: clamp(1rem, 4cqw, 2rem);
  /* يتغير بناءً على عرض الـ container — مش الشاشة */
}
21
// SCROLL ANIMATIONS

Scroll-driven Animations

animations بتتحكم فيها الـ scroll — بدون JavaScript
⚡ 2024+ Chrome/Edge

قبل كده، كل scroll animation كانت محتاجة JavaScript وIntersection Observer. دلوقتي CSS بتقدر تعملها وحدها. الفكرة: بدل ما الـ animation تتحكم فيها الوقت، بيتحكم فيها مكان الـ scroll.

scroll-animations.css
/* ══ Reading Progress Bar — بدون JavaScript ══ */
@keyframes scaleProgress {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

.progress-bar {
  position: fixed;
  top: 0; left: 0;
  width: 100%; height: 3px;
  background: var(--primary);
  transform-origin: left center;

  /* animation-timeline: scroll() بيقول "اربط الـ animation بالـ scroll" */
  animation: scaleProgress linear;
  animation-timeline: scroll();
  /* بدل ما تعتمد على الوقت، بتعتمد على مكان الـ scroll */
}

/* ══ Fade in لما العنصر يدخل الشاشة ══ */
@keyframes appear {
  from { opacity: 0; transform: translateY(40px); }
  to   { opacity: 1; transform: translateY(0); }
}

.animate-on-scroll {
  animation: appear linear both;
  /* view() بيقول "اربط بـ visibility العنصر في الـ viewport" */
  animation-timeline: view();
  /* animation-range: من إمتى لإمتى */
  /* entry 0%: لما يبدأ يدخل الشاشة */
  /* cover 25%: لما 25% منه في الشاشة */
  animation-range: entry 0% cover 25%;
}

/* ══ Fallback للمتصفحات القديمة ══ */
@supports not (animation-timeline: scroll()) {
  .animate-on-scroll {
    opacity:   1;  /* بيتظهر عادي بدون animation */
    transform: none;
  }
}

/* ══ Parallax Effect ══ */
@keyframes parallax {
  from { transform: translateY(0); }
  to   { transform: translateY(200px); }
}
.hero-bg {
  animation: parallax linear;
  animation-timeline: scroll(root block);
}
ℹ️
Browser Support — يونيو 2026

Scroll-driven Animations مدعومة بالكامل في Chrome 115+ وEdge 115+. Firefox 110+. Safari لسه بيضيف الدعم تدريجياً. استخدم @supports كـ fallback، أو JavaScript مع Intersection Observer للـ full support. في كورس JavaScript هنتعلم Intersection Observer.

⚠️
مطبات برمجية شائعة — الوحدة السادسة

1. !important مالهاش حل غير !important تاني

/* مفيش error — لكن صراع specificity بلا نهاية */ .btn { color: red !important; } /* بعدين عايز تغيره: */ .btn.special { color: blue !important; } /* محتاج !important تاني عشان يفوز! */
الحل: !important بتلغي نظام الـ Cascade الطبيعي بالكامل، وأي محاولة تعديل بعدها محتاجة !important أقوى أو نفس القوة مع ترتيب لاحق. الحل الجذري مش إضافة !important تاني — هو إزالة الأول وإعادة هيكلة الـ CSS بـ specificity منطقي (classes بدل IDs، تقليل التعشيش).

2. Nesting بدون & في الاستخدام الصح

/* مفيش error واضح، لكن الـ selector بيتفسر غلط */ .card { h2 { color: red; } /* بدون & — لسه شغالة لكن ده الأسلوب الغلط */ }
الحل: رغم إن CSS Nesting بتقبل أحياناً الكتابة بدون &، الممارسة الصح والواضحة هي استخدام & دايماً صراحة: & h2 { }. ده بيخلي قصدك واضح للقارئ التاني (وللمتصفحات الأقدم اللي ممكن تتعامل مع الكتابتين بشكل مختلف).

3. :has() مش مدعومة في كل المتصفحات بعد

/* مفيش error — لكن الـ style مش بيتطبق في متصفحات قديمة */ .form:has(input:invalid) { border-color: red; } /* Safari الأقدم من 15.4 أو Firefox قديم مش بتفهم :has() */
الحل: :has() مدعومة بقوة من 2023 فما فوق في كل المتصفحات الحديثة، لكن لو موقعك محتاج يدعم متصفحات أقدم، استخدم @supports selector(:has(*)) للتأكد من توفر الدعم، أو اعتمد على JavaScript كـ fallback للمتصفحات اللي مش بتدعمها.
TASK 06
طبّق Modern CSS على الـ Portfolio
الوحدة السادسة · Modern CSS 2026
  • حوّل الـ CSS المتكرر لـ Nesting: كل .card + .card h2 + .card:hover يبقوا جوّا .card { }
  • أضف ::selection بلون الـ primary color
  • أضف scroll-margin-top على كل section
  • استخدم :has() في حالة واحدة — مثلاً body:has(.menu.open) { overflow: hidden }
  • استخدم ::before أو ::after لإضافة decorative element بدون HTML
  • أضف scroll progress bar بـ CSS فقط: animation-timeline: scroll()
  • استخدم Container Queries على الـ project cards
  • نظّم CSS بـ @layer: base, components, utilities
  • "CSS specificity calculator" — بيحسب أي selector specificity
  • "scroll-driven animations Chrome demo" — أمثلة رائعة من Google
  • "CSS @layer explained" — كيف تنظم CSS بالطبقات
FINAL PROJECT
🎨
// FINAL PROJECT
تجميل الـ Portfolio بـ CSS كامل
هتاخد الـ HTML من كورس HTML وتحوّله لتصميم احترافي
01
هيكل ملف style.css
قسّم الملف بـ comments: /* === RESET === *//* === VARIABLES === *//* === BASE === *//* === COMPONENTS === *//* === RESPONSIVE === */. الترتيب مهم.
02
Navbar Glass Effect
position:fixed + backdrop-filter:blur(16px) + border-bottom شفاف. Flexbox للتوزيع. Transition على الـ background عند الـ scroll (JavaScript لاحقاً). على موبايل: roابط تختفي وhamburger يظهر.
03
Hero Section مذهل
min-height:100dvh + gradient background + gradient text على الاسم + clamp() لـ h1 + avatar مع border وglow + fadeUp animation عند التحميل + scroll indicator متحرك.
04
Skills Cards
Grid auto-fill. كل card: icon + اسم المهارة + progress bar CSS خالص. Hover effect مع translateY + box-shadow. ألوان مختلفة لكل category.
05
Projects Grid
Grid responsive بـ auto-fill. كل card: صورة بـ object-fit:cover + overlay عند hover + staggered fadeUp animation + technology badges.
06
Contact Form
Styled inputs مع :focus animation على الـ border. :valid/:user-invalid للـ visual feedback. Submit button مع hover animation.
07
Responsive كامل
Mobile First. اختبر على 3 breakpoints: 375px موبايل، 768px تابلت، 1280px ديسكتوب. تأكد من: الخطوط مقروءة، المسافات كافية، الصور مش بتفيض.
🔗
مشروعك هينتهيش هنا — في كورس JavaScript هتضيف: Hamburger menu يفتح ويقفل، scroll animations بـ Intersection Observer، typing effect على وصفك، project filter، dark/light mode toggle، وفورم submission حقيقي. الـ CSS اللي بنيته دلوقتي هو الأساس اللي JavaScript هتتعامل معاه.
TASK FINAL 🏆
Portfolio CSS كامل + نشر على GitHub Pages
التاسك الختامي · المشروع النهائي
  • style.css منظم بـ sections وcomments واضحة
  • CSS Variables كاملة في :root — أي تغيير في اللون من مكان واحد
  • Navbar: fixed + glass effect + responsive
  • Hero: 100dvh + gradient + animation + responsive
  • Projects: Grid auto-fill + hover effects
  • Mobile First CSS — اختبر على DevTools mobile
  • رفع على GitHub Pages — شارك الرابط
  • Light/Dark Mode بـ data-theme + CSS Variables + toggle button
  • Lighthouse في Chrome DevTools — اوصل لـ 90+ في Performance وAccessibility
  • جرّب OKLCH للألوان وشوف الفرق
  • "CSS minifier online" — ضغط الـ CSS للـ production
  • "Sass SCSS beginner tutorial" — الخطوة الجاية
  • "Tailwind CSS crash course" — مكتبة CSS utility-first شائعة جداً
🎉 تهانينا! أتممت كورس CSS الـ Portfolio بتاعك دلوقتي موقع احترافي حقيقي. في كورس JavaScript هنضيف الروح — التفاعل والديناميكية. كل سطر CSS كتبته هيبقى أساس للـ JS يتعامل معاه.