Въведение в модерния CSS Layout
CSS Grid и Flexbox революционизираха начина, по който създаваме layouts в уеб разработката. Тези две технологии решиха проблеми, които мъчиха разработчиците с десетилетия - от хакове с floats до таблици за layout. В тази статия ще научите кога и как да използвате всяка от тях.
Flexbox vs Grid: Кога кое да използваме?
┌─────────────────────────────────────────────────────────────────────────────┐
│ FLEXBOX vs GRID - КОГА КОЕ? │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ FLEXBOX GRID │
│ (1 измерение) (2 измерения) │
│ │
│ ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┐ │
│ │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 1 │ 2 │ 3 │ 4 │ │
│ └───┴───┴───┴───┴───┘ ├───┼───┼───┼───┤ │
│ Един ред или колона │ 5 │ 6 │ 7 │ 8 │ │
│ ├───┼───┼───┼───┤ │
│ ┌───┐ │ 9 │10 │11 │12 │ │
│ │ 1 │ └───┴───┴───┴───┘ │
│ ├───┤ Редове И колони │
│ │ 2 │ │
│ ├───┤ │
│ │ 3 │ │
│ └───┘ │
│ │
│ ИЗПОЛЗВАЙ FLEXBOX ЗА: ИЗПОЛЗВАЙ GRID ЗА: │
│ ✓ Navigation меню ✓ Page layout │
│ ✓ Buttons с икона ✓ Card grids │
│ ✓ Центриране на елемент ✓ Form layouts │
│ ✓ Footer с распределени items ✓ Dashboard layouts │
│ ✓ Toolbar с actions ✓ Complex magazine layouts │
│ │
│ Накратко: Flexbox за компоненти, Grid за layout │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
CSS Flexbox в детайли
Основни концепции
┌─────────────────────────────────────────────────────────────────────────────┐
│ FLEXBOX AXES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ flex-direction: row (default) │
│ │
│ Main Axis (justify-content) ──────────────────────► │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ ▲ │
│ C │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ r │ │ Item │ │ Item │ │ Item │ │ Item │ │ │ Cross │
│ o │ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ │ Axis │
│ s │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ s │ │ │ (align- │
│ └─────────────────────────────────────────────────────────┘ ▼ items) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Container свойства
.flex-container {
display: flex; /* или inline-flex */
/* Посока на main axis */
flex-direction: row; /* → (default) */
flex-direction: row-reverse; /* ← */
flex-direction: column; /* ↓ */
flex-direction: column-reverse;/* ↑ */
/* Обвиване при нужда */
flex-wrap: nowrap; /* всичко на един ред (default) */
flex-wrap: wrap; /* обвий на нов ред */
flex-wrap: wrap-reverse; /* обвий нагоре */
/* Shorthand */
flex-flow: row wrap;
/* Подравняване по main axis */
justify-content: flex-start; /* ├──────────────────────── */
justify-content: flex-end; /* ──────────────────────┤ */
justify-content: center; /* ─────────┼─────────── */
justify-content: space-between; /* ├────────┼────────┤ */
justify-content: space-around; /* ──├────┼────┼────┼────├── */
justify-content: space-evenly; /* ├──┼──┼──┼──┼──┤ */
/* Подравняване по cross axis */
align-items: stretch; /* разтегли (default) */
align-items: flex-start; /* горе */
align-items: flex-end; /* долу */
align-items: center; /* център */
align-items: baseline; /* по baseline на текста */
/* Gap между items */
gap: 16px; /* еднакъв gap */
gap: 16px 24px; /* row-gap column-gap */
}
Item свойства
.flex-item {
/* Растеж - колко от свободното пространство да заеме */
flex-grow: 0; /* не расте (default) */
flex-grow: 1; /* расте пропорционално */
flex-grow: 2; /* расте 2x повече от flex-grow: 1 */
/* Свиване - колко да се свие ако няма място */
flex-shrink: 1; /* свива се (default) */
flex-shrink: 0; /* не се свива никога */
/* Базов размер преди flex */
flex-basis: auto; /* използва width/height */
flex-basis: 200px; /* започва от 200px */
flex-basis: 0; /* игнорира съдържанието */
/* Shorthand */
flex: 0 1 auto; /* grow shrink basis (default) */
flex: 1; /* flex: 1 1 0% - равномерно растене */
flex: auto; /* flex: 1 1 auto */
flex: none; /* flex: 0 0 auto - твърд размер */
/* Индивидуално подравняване */
align-self: auto | flex-start | flex-end | center | baseline | stretch;
/* Пренареждане */
order: 0; /* default */
order: -1; /* преди останалите */
order: 1; /* след останалите */
}
Практически примери с Flexbox
1. Navigation меню
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.nav__logo {
flex-shrink: 0;
}
.nav__links {
display: flex;
gap: 2rem;
}
.nav__actions {
display: flex;
gap: 1rem;
}
2. Card с footer винаги долу
.card {
display: flex;
flex-direction: column;
height: 100%;
}
.card__content {
flex: 1; /* заема останалото пространство */
}
.card__footer {
/* винаги остава долу */
margin-top: auto;
}
3. Перфектно центриране
.centered {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
CSS Grid в детайли
Основни концепции
┌─────────────────────────────────────────────────────────────────────────────┐
│ CSS GRID ANATOMY │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Column 1 Column 2 Column 3 Column 4 │
│ │ │ │ │ │
│ ┌───▼───────────▼───────────▼───────────▼───┐ ◄── Grid Line 1 │
│ │ │ │ │ │ │ │ │
│ R │ 1 │ 2 │ 3 │ 4 │ ←Track │ ◄── Grid Line 2 │
│ o │ │ │ │ │ (ред) │ │
│ w ├───────┼───────┼───────┼───────┼───────────┤ ◄── Grid Line 3 │
│ │ │ │ │ │ │
│ 1 │ 5 │ Grid │ 7 │ │ │
│ │ │ Area │ │ │ │
│ ├───────┤ (6 заема ├───────┤ │ ◄── Grid Line 4 │
│ R │ │ 2 клетки) │ │ │ │
│ o │ 8 │ │ 9 │ 10 │ │
│ w │ │ │ │ (spans │ │
│ └───────┴───────────────┴───────┴──2 rows)──┘ ◄── Grid Line 5 │
│ 2 │ │
│ ▲ ▲ ▲ ▲ ▲ │
│ Line 1 Line 2 Line 3 Line 4 Line 5 │
│ │
│ Gap ────────────► ◄────── Cell (клетка) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Container свойства
.grid-container {
display: grid; /* или inline-grid */
/* Дефиниране на колони */
grid-template-columns: 200px 200px 200px; /* 3 колони по 200px */
grid-template-columns: 1fr 1fr 1fr; /* 3 равни колони */
grid-template-columns: 1fr 2fr 1fr; /* средната е 2x */
grid-template-columns: repeat(3, 1fr); /* shorthand за 3 равни */
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); /* responsive! */
/* Дефиниране на редове */
grid-template-rows: 100px auto 100px; /* header, content, footer */
/* Автоматични редове (за items извън template) */
grid-auto-rows: minmax(100px, auto);
/* Gap */
gap: 16px; /* еднакъв gap */
row-gap: 16px; /* само между редове */
column-gap: 24px; /* само между колони */
/* Подравняване на items в клетките */
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
place-items: center; /* shorthand */
/* Подравняване на целия grid в контейнера */
justify-content: start | end | center | space-between | space-around;
align-content: start | end | center | space-between | space-around;
place-content: center; /* shorthand */
}
Grid Template Areas
.page-layout {
display: grid;
grid-template-columns: 250px 1fr 300px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
min-height: 100vh;
gap: 20px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
Визуализация:
┌─────────────────────────────────────────────────────────┐
│ HEADER │
├──────────────┬─────────────────────────┬───────────────┤
│ │ │ │
│ SIDEBAR │ CONTENT │ ASIDE │
│ (250px) │ (1fr) │ (300px) │
│ │ │ │
├──────────────┴─────────────────────────┴───────────────┤
│ FOOTER │
└─────────────────────────────────────────────────────────┘
Item свойства
.grid-item {
/* Позициониране по линии */
grid-column-start: 1;
grid-column-end: 3; /* от линия 1 до линия 3 */
grid-column: 1 / 3; /* shorthand */
grid-column: 1 / span 2; /* от 1, span 2 колони */
grid-column: 1 / -1; /* от първата до последната */
grid-row-start: 1;
grid-row-end: 3;
grid-row: 1 / 3;
/* Shorthand за двете */
grid-area: 1 / 1 / 3 / 3; /* row-start / col-start / row-end / col-end */
grid-area: header; /* или named area */
/* Индивидуално подравняване */
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
place-self: center; /* shorthand */
}
Responsive Grid без Media Queries
/* Магията на auto-fit и minmax */
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
/*
Как работи:
- auto-fit: създава колкото колони се събират
- minmax(300px, 1fr): минимум 300px, максимум 1fr
Резултат:
- На широк екран: 4+ колони
- На среден екран: 2-3 колони
- На мобилен: 1 колона
Всичко това БЕЗ media queries!
*/
Subgrid (CSS Grid Level 2)
.parent-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.child-that-spans {
grid-column: span 2;
display: grid;
/* Наследява линиите от родителя */
grid-template-columns: subgrid;
}
Комбиниране на Grid и Flexbox
/* Grid за page layout */
.page {
display: grid;
grid-template-columns: 1fr min(65ch, 100%) 1fr;
grid-template-rows: auto 1fr auto;
}
.page > * {
grid-column: 2;
}
/* Flexbox за header вътре в grid */
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
/* Grid за card grid */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 24px;
}
/* Flexbox за card вътре в grid */
.card {
display: flex;
flex-direction: column;
}
.card__content {
flex: 1;
}
.card__footer {
margin-top: auto;
display: flex;
justify-content: space-between;
}
Performance съображения
- Grid и Flexbox са hardware-accelerated
- Избягвайте layout thrashing при анимации
- Използвайте
will-changeвнимателно contain: layoutможе да помогне за изолация
Заключение
CSS Grid и Flexbox са мощни инструменти, които се допълват взаимно. Използвайте Grid за двумерни layouts и Flexbox за едномерни подравнявания. Комбинирайте ги за максимална гъвкавост.
Брой думи: 3,198