1.5 פלקסבוקס הרצאה
פלקסבוקס - Flexbox¶
פלקסבוקס (Flexible Box Layout) הוא מודל layout חד-ממדי ב-CSS שמקל מאוד על סידור אלמנטים בשורה או בעמודה. לפני Flexbox, סידור אלמנטים היה סיוט עם float-ים, inline-block ושאר פתרונות מסורבלים. היום Flexbox הוא הכלי העיקרי ל-layout בCSS.
הרעיון הבסיסי: ציר ראשי וציר משני¶
בפלקסבוקס יש שני צירים:
- ציר ראשי - main axis - הכיוון שבו האלמנטים מסודרים (ברירת מחדל: אופקי, שמאל לימין)
- ציר משני - cross axis - הכיוון הניצב לציר הראשי (ברירת מחדל: אנכי, למעלה למטה)
כל Flexbox מורכב משני חלקים:
- קונטיינר - flex container - ההורה שמגדירים עליו display: flex
- פריטים - flex items - הילדים הישירים של הקונטיינר
<div class="container"> <!-- flex container -->
<div class="item">1</div> <!-- flex item -->
<div class="item">2</div> <!-- flex item -->
<div class="item">3</div> <!-- flex item -->
</div>
ברגע שמוסיפים display: flex, כל הילדים הישירים הופכים לflex items ומסתדרים בשורה אחת אופקית. זה כל מה שצריך כדי להתחיל.
מאפייני הקונטיינר¶
כיוון - flex-direction¶
קובע את כיוון הציר הראשי:
.container {
display: flex;
flex-direction: row; /* default: horizontal, left to right */
}
.container-column {
display: flex;
flex-direction: column; /* vertical, top to bottom */
}
.container-reverse {
display: flex;
flex-direction: row-reverse; /* horizontal, right to left */
}
.container-column-reverse {
display: flex;
flex-direction: column-reverse; /* vertical, bottom to top */
}
row(ברירת מחדל) - שורה אופקיתcolumn- עמודה אנכיתrow-reverse- שורה אופקית הפוכהcolumn-reverse- עמודה אנכית הפוכה
יישור על הציר הראשי - justify-content¶
שולט איך הפריטים מתפלגים על הציר הראשי:
.start {
display: flex;
justify-content: flex-start; /* default: items at the start */
}
.center {
display: flex;
justify-content: center; /* items centered */
}
.end {
display: flex;
justify-content: flex-end; /* items at the end */
}
.between {
display: flex;
justify-content: space-between; /* first item at start, last at end, equal space between */
}
.around {
display: flex;
justify-content: space-around; /* equal space around each item */
}
.evenly {
display: flex;
justify-content: space-evenly; /* equal space between all items and edges */
}
נדמיין שורה אופקית עם שלושה פריטים (A, B, C):
- flex-start: [A B C ]
- center: [ A B C ]
- flex-end: [ A B C]
- space-between: [A B C]
- space-around: [ A B C ]
- space-evenly: [ A B C ]
ההבדל בין around ל-evenly: ב-around, הרווח בצדדים הוא חצי מהרווח בין הפריטים. ב-evenly, כל הרווחים שווים.
יישור על הציר המשני - align-items¶
שולט איך הפריטים מיושרים על הציר המשני (אנכי כשהכיוון הוא row):
.stretch {
display: flex;
align-items: stretch; /* default: items stretch to fill container height */
}
.top {
display: flex;
align-items: flex-start; /* items at the top */
}
.middle {
display: flex;
align-items: center; /* items vertically centered */
}
.bottom {
display: flex;
align-items: flex-end; /* items at the bottom */
}
.baseline {
display: flex;
align-items: baseline; /* items aligned by text baseline */
}
stretch(ברירת מחדל) - הפריטים נמתחים למלא את כל הגובה של הקונטיינרflex-start- הפריטים למעלהcenter- הפריטים באמצעflex-end- הפריטים למטהbaseline- הפריטים מיושרים לפי קו הבסיס של הטקסט (שימושי כשלפריטים גדלי טקסט שונים)
שבירת שורות - flex-wrap¶
.no-wrap {
display: flex;
flex-wrap: nowrap; /* default: all items in one line, may overflow */
}
.wrap {
display: flex;
flex-wrap: wrap; /* items wrap to next line when needed */
}
.wrap-reverse {
display: flex;
flex-wrap: wrap-reverse; /* wraps in reverse direction */
}
nowrap(ברירת מחדל) - כל הפריטים בשורה אחת, גם אם הם צריכים להתכווץwrap- פריטים שלא נכנסים עוברים לשורה הבאה- בדרך כלל נרצה wrap כשיש הרבה פריטים
קיצור - flex-flow¶
שילוב של flex-direction ו-flex-wrap:
.container {
display: flex;
flex-flow: row wrap; /* same as flex-direction: row; flex-wrap: wrap; */
}
יישור שורות מרובות - align-content¶
כשיש flex-wrap ומספר שורות, align-content שולט על הפילוג האנכי של השורות:
.container {
display: flex;
flex-wrap: wrap;
height: 500px;
align-content: flex-start; /* lines packed at top */
}
.container-center {
display: flex;
flex-wrap: wrap;
height: 500px;
align-content: center; /* lines centered vertically */
}
.container-between {
display: flex;
flex-wrap: wrap;
height: 500px;
align-content: space-between; /* first line at top, last at bottom */
}
- align-content עובד רק כשיש מספר שורות (flex-wrap: wrap)
- הערכים דומים ל-justify-content: flex-start, center, flex-end, space-between, space-around, space-evenly, stretch
מרווח - gap¶
.container {
display: flex;
gap: 20px; /* 20px gap between all items */
}
.container-custom {
display: flex;
row-gap: 15px; /* gap between rows */
column-gap: 25px; /* gap between columns */
}
.container-shorthand {
display: flex;
gap: 15px 25px; /* row-gap column-gap */
}
gapמגדיר מרווח בין הפריטים (לא בצדדים)- הרבה יותר נוח מ-margin על כל פריט
- עובד גם ב-Flexbox וגם ב-Grid
מאפייני הפריטים¶
המאפיינים הבאים מוגדרים על הפריטים עצמם (הילדים), לא על הקונטיינר.
סדר - order¶
משנה את סדר ההצגה של פריט בלי לשנות את ה-HTML:
- ברירת מחדל: 0 לכל הפריטים
- מספר נמוך = מוצג קודם
- אפשר להשתמש במספרים שליליים
גדילה - flex-grow¶
קובע כמה פריט יכול לגדול ביחס לאחרים כשיש מקום פנוי:
.item-a { flex-grow: 1; } /* gets 1 share of extra space */
.item-b { flex-grow: 2; } /* gets 2 shares of extra space */
.item-c { flex-grow: 1; } /* gets 1 share of extra space */
- ברירת מחדל: 0 (לא גדל)
- אם לכולם flex-grow: 1, כולם מתחלקים שווה בשווה במקום הפנוי
- אם לאחד flex-grow: 2 ולשאר 1, הוא מקבל פי 2 מהמקום הפנוי
דוגמה מעשית - שדה חיפוש שתופס את כל הרוחב הפנוי:
<div class="search-bar">
<input class="search-input" type="text" placeholder="Search...">
<button class="search-btn">Search</button>
</div>
.search-bar {
display: flex;
gap: 10px;
}
.search-input {
flex-grow: 1; /* takes all available space */
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
.search-btn {
padding: 10px 20px;
/* doesn't grow - stays at its natural size */
}
כיווץ - flex-shrink¶
קובע כמה פריט יכול להתכווץ כשאין מספיק מקום:
.item-a { flex-shrink: 1; } /* default: can shrink */
.item-b { flex-shrink: 0; } /* won't shrink at all */
.item-c { flex-shrink: 2; } /* shrinks twice as much */
- ברירת מחדל: 1 (מתכווץ)
- flex-shrink: 0 = הפריט לא יתכווץ בשום מקרה
גודל בסיסי - flex-basis¶
מגדיר את הגודל ההתחלתי של פריט לפני שflex-grow ו-flex-shrink נכנסים לפעולה:
.item {
flex-basis: 200px; /* starts at 200px wide */
}
.item-auto {
flex-basis: auto; /* default: uses width/content */
}
.item-zero {
flex-basis: 0; /* starts at 0, size determined by flex-grow */
}
auto(ברירת מחדל) - משתמש ב-width של הפריט, או גודל התוכן- ערך ספציפי (px, %, rem) - מגדיר גודל בסיסי
קיצור - flex¶
שילוב של flex-grow, flex-shrink ו-flex-basis:
.item {
flex: 0 1 auto; /* default: don't grow, can shrink, auto basis */
}
.item-grow {
flex: 1; /* same as: flex: 1 1 0 */
/* grow=1, shrink=1, basis=0 (splits space equally) */
}
.item-fixed {
flex: 0 0 200px; /* don't grow, don't shrink, 200px */
}
.item-half {
flex: 1 1 50%; /* grow and shrink, start at 50% */
}
ערכים נפוצים:
- flex: 1 - פריט גמיש שתופס חלק שווה מהמקום (הכי נפוץ)
- flex: none = flex: 0 0 auto - פריט קשיח שלא גדל ולא מתכווץ
- flex: auto = flex: 1 1 auto - פריט גמיש שמתחיל מהגודל הטבעי שלו
יישור עצמי - align-self¶
דורס את align-items של הקונטיינר עבור פריט ספציפי:
.container {
display: flex;
align-items: flex-start; /* all items at top */
}
.special-item {
align-self: flex-end; /* this one goes to bottom */
}
.center-item {
align-self: center; /* this one centered vertically */
}
דפוסים נפוצים¶
Navbar - סרגל ניווט¶
<nav class="navbar">
<div class="navbar-logo">Logo</div>
<div class="navbar-links">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Services</a>
<a href="#">Contact</a>
</div>
</nav>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px;
background-color: #2c3e50;
}
.navbar-logo {
color: white;
font-size: 20px;
font-weight: bold;
}
.navbar-links {
display: flex;
gap: 10px;
}
.navbar-links a {
color: white;
text-decoration: none;
padding: 8px 16px;
}
- space-between שם את הלוגו בצד אחד והקישורים בצד השני
- align-items: center מיישר הכל אנכית במרכז
מרכוז מושלם¶
.center-both {
display: flex;
justify-content: center; /* horizontal center */
align-items: center; /* vertical center */
height: 100vh; /* full viewport height */
}
שלוש שורות וזה עובד. זה כל מה שצריך למרכוז מושלם.
רשת כרטיסים - card grid¶
<div class="card-grid">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
<div class="card">Card 5</div>
<div class="card">Card 6</div>
</div>
.card-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 300px; /* grow, shrink, minimum 300px */
background: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
}
flex: 1 1 300pxאומר: כל כרטיס מינימום 300px רוחב, ואם יש מקום - כולם גדלים שווהflex-wrap: wrapמעביר כרטיסים לשורה הבאה כשאין מספיק מקום- התוצאה: רשת שמתאימה את עצמה למסך
Footer עם 3 עמודות¶
<footer class="footer">
<div class="footer-col">
<h4>About</h4>
<p>We build great websites.</p>
</div>
<div class="footer-col">
<h4>Links</h4>
<a href="#">Home</a>
<a href="#">Blog</a>
<a href="#">Contact</a>
</div>
<div class="footer-col">
<h4>Contact</h4>
<p>email@example.com</p>
<p>+972-50-1234567</p>
</div>
</footer>
.footer {
display: flex;
justify-content: space-between;
gap: 30px;
padding: 40px 30px;
background-color: #2c3e50;
color: white;
}
.footer-col {
flex: 1;
}
.footer-col h4 {
margin-bottom: 15px;
font-size: 18px;
}
.footer-col a {
display: block;
color: #bdc3c7;
text-decoration: none;
margin-bottom: 8px;
}
.footer-col p {
color: #bdc3c7;
margin-bottom: 8px;
}
Holy Grail Layout¶
הlayout הקלאסי של אתרים: header, footer, ובאמצע sidebar + content + sidebar:
<div class="layout">
<header class="layout-header">Header</header>
<div class="layout-body">
<aside class="layout-sidebar">Sidebar Left</aside>
<main class="layout-content">Main Content</main>
<aside class="layout-sidebar">Sidebar Right</aside>
</div>
<footer class="layout-footer">Footer</footer>
</div>
.layout {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.layout-header {
background-color: #2c3e50;
color: white;
padding: 20px;
}
.layout-body {
display: flex;
flex: 1; /* takes all remaining vertical space */
}
.layout-sidebar {
flex: 0 0 200px; /* fixed 200px wide, won't grow or shrink */
background-color: #ecf0f1;
padding: 20px;
}
.layout-content {
flex: 1; /* takes all remaining horizontal space */
padding: 20px;
}
.layout-footer {
background-color: #2c3e50;
color: white;
padding: 20px;
text-align: center;
}
- הlayout החיצוני הוא flex column (אנכי)
- ה-body הוא flex row (אופקי)
flex: 1על body ועל content גורם להם לתפוס את כל המקום הפנויflex: 0 0 200pxעל sidebars שומר אותם ב-200px קבועים
דוגמה מסכמת¶
נבנה דף שלם שמשלב הרבה מהדפוסים:
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<title>Flexbox Layout</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<nav class="nav">
<div class="nav-logo">FlexSite</div>
<div class="nav-links">
<a href="#">Home</a>
<a href="#">Products</a>
<a href="#">About</a>
<a href="#">Contact</a>
</div>
</nav>
<section class="hero">
<h1>Build Layouts with Flexbox</h1>
<p>The modern way to create responsive CSS layouts</p>
</section>
<main class="main">
<h2 class="section-title">Our Products</h2>
<div class="products">
<div class="product-card">
<h3>Product A</h3>
<p>Amazing product description</p>
<span class="price">$29</span>
</div>
<div class="product-card">
<h3>Product B</h3>
<p>Another great product</p>
<span class="price">$49</span>
</div>
<div class="product-card">
<h3>Product C</h3>
<p>Premium quality item</p>
<span class="price">$99</span>
</div>
</div>
</main>
<footer class="footer">
<div class="footer-section">
<h4>Company</h4>
<p>Building great products since 2020</p>
</div>
<div class="footer-section">
<h4>Links</h4>
<a href="#">Privacy</a>
<a href="#">Terms</a>
</div>
<div class="footer-section">
<h4>Contact</h4>
<p>hello@example.com</p>
</div>
</footer>
</body>
</html>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
color: #333;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* navbar */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px;
background-color: #2c3e50;
}
.nav-logo {
color: white;
font-size: 22px;
font-weight: bold;
}
.nav-links {
display: flex;
gap: 5px;
}
.nav-links a {
color: white;
text-decoration: none;
padding: 8px 16px;
border-radius: 4px;
}
/* hero - centered content */
.hero {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 80px 20px;
background-color: #34495e;
color: white;
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 10px;
}
.hero p {
font-size: 1.2rem;
opacity: 0.8;
}
/* main content */
.main {
flex: 1; /* pushes footer to bottom */
max-width: 1000px;
margin: 0 auto;
padding: 40px 20px;
width: 100%;
}
.section-title {
margin-bottom: 25px;
font-size: 1.8rem;
color: #2c3e50;
}
/* product cards grid */
.products {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.product-card {
flex: 1 1 250px;
background: white;
border: 1px solid #ddd;
border-radius: 10px;
padding: 25px;
display: flex;
flex-direction: column;
}
.product-card h3 {
margin-bottom: 10px;
color: #2c3e50;
}
.product-card p {
color: #777;
flex: 1; /* pushes price to bottom */
margin-bottom: 15px;
}
.price {
font-size: 24px;
font-weight: bold;
color: #27ae60;
align-self: flex-start;
}
/* footer */
.footer {
display: flex;
justify-content: space-between;
gap: 30px;
padding: 30px;
background-color: #2c3e50;
color: white;
}
.footer-section {
flex: 1;
}
.footer-section h4 {
margin-bottom: 10px;
}
.footer-section a {
display: block;
color: #bdc3c7;
text-decoration: none;
margin-bottom: 5px;
}
.footer-section p {
color: #bdc3c7;
}
שימו לב לטריק ב-product-card: שמנו flex: 1 על הפסקה כדי שהיא תתפוס את כל המקום הפנוי, ובכך המחיר נדחף לתחתית הכרטיס. ככה כל הכרטיסים מסודרים אחיד גם אם התיאור באחד קצר יותר.
סיכום¶
display: flexמפעיל פלקסבוקס על הקונטיינרflex-directionקובע את כיוון הציר: row (אופקי) או column (אנכי)justify-contentמיישר על הציר הראשי: center, space-between, space-evenlyalign-itemsמיישר על הציר המשני: center, stretch, flex-start, flex-endflex-wrap: wrapמאפשר שבירת שורותgapמגדיר מרווח בין פריטיםflex: 1על פריט = תופס מקום פנוי שווהflex: 0 0 200px= גודל קבוע ללא גדילה/כיווץalign-selfדורס את align-items לפריט ספציפי- למרכוז מושלם:
display: flex; justify-content: center; align-items: center; - פלקסבוקס פותר כמעט כל בעיית layout חד-ממדית - השתמשו בו בלי פחד