← HTML & CSS/CSS Grid: сетка страницы#26 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

CSS Grid: сетка страницы

Лейаут страницы с шапкой, двумя колонками и подвалом. Галерея фотографий в три колонки. Дашборд с плитками разного размера. Flexbox справляется с одним измерением (строка или колонка), а CSS Grid — с двумя одновременно. Это самый мощный инструмент компоновки в CSS.

Основы Grid

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;  /* 3 колонки */
  grid-template-rows: auto;               /* Строки авто-высоты */
  gap: 16px;
}

Дочерние элементы автоматически распределяются по ячейкам сетки.

grid-template-columns и единица fr

fr (fraction) — дробная единица, делит доступное пространство.

grid-template-columns: 1fr 1fr 1fr;     /* Три равные колонки */
grid-template-columns: 1fr 2fr 1fr;     /* Средняя в 2 раза шире */
grid-template-columns: 200px 1fr;       /* Фиксированная + растягивающаяся */
grid-template-columns: 200px 1fr 300px; /* Фикс + флюид + фикс */

repeat() — повторение

grid-template-columns: repeat(3, 1fr);         /* = 1fr 1fr 1fr */
grid-template-columns: repeat(4, minmax(200px, 1fr));  /* 4 колонки min 200px */

minmax() — диапазон размера

/* Колонка от 200px до 1fr — адаптивный грид */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

Это магия адаптивности без media queries: сколько влезет колонок по 200px — столько и будет.

gap — промежутки

gap: 16px;            /* Все промежутки */
gap: 8px 16px;        /* row-gap column-gap */
row-gap: 8px;
column-gap: 16px;

Позиционирование элементов в сетке

grid-column и grid-row

/* Элемент занимает с 1-й по 3-ю линию колонок = 2 колонки */
.header { grid-column: 1 / 3; }

/* Сокращение: span N — занять N ячеек */
.header { grid-column: span 2; }
.wide-card { grid-column: span 3; }
.tall-item { grid-row: span 2; }

/* Занять всю ширину */
.footer { grid-column: 1 / -1; }  /* -1 = последняя линия */

grid-template-areas — именованные области

Визуальное описание раскладки:

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 8px;
  height: 100vh;
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }

Невероятно читабельно — лейаут прямо в CSS.

auto-placement — автоматическое размещение

По умолчанию Grid сам расставляет элементы слева направо, сверху вниз. Настройки:

grid-auto-flow: row;     /* По умолчанию — строками */
grid-auto-flow: column;  /* По столбцам */
grid-auto-flow: dense;   /* Заполняет дыры — для плотной галереи */

Типичные ошибки

Ошибка 1: Перепутать grid-column с grid-template-columns

/* grid-template-columns — на КОНТЕЙНЕРЕ, задаёт структуру */
.container { grid-template-columns: 1fr 1fr; }

/* grid-column — на ДОЧЕРНЕМ, задаёт его позицию */
.item { grid-column: 1 / 3; }

/* Не наоборот! */

Ошибка 2: fr без явного размера контейнера

/* Если контейнер не имеет размера, fr ведёт себя как auto */
.container { display: grid; grid-template-columns: 1fr 1fr; }
/* Нормально — ширина по родителю */

.container { display: inline-grid; grid-template-columns: 1fr 1fr; }
/* fr = 0, если нет явной ширины */

В реальных проектах

Grid идеален для макросетки страницы: хедер, сайдбар, контент, футер. Внутри секций — обычно Flexbox для рядов элементов. Правило большого пальца: Grid для страницы, Flex для компонентов. Но оба работают на любом уровне — выбирай то, что удобнее для конкретной задачи.

Tailwind CSS предоставляет: grid, grid-cols-3, col-span-2, gap-4 — всё те же концепции.

Примеры

CSS Grid: страничный лейаут и адаптивная галерея

const style = document.createElement('style')
style.textContent = `
  * { box-sizing: border-box; }
  body { font-family: Arial, sans-serif; padding: 16px; }
`
document.head.appendChild(style)

// === Лейаут страницы с grid-template-areas ===
const page = document.createElement('div')
page.style.display = 'grid'
page.style.gridTemplateColumns = '160px 1fr'
page.style.gridTemplateRows = '50px 1fr 40px'
page.style.gridTemplateAreas = '"header header" "sidebar main" "footer footer"'
page.style.gap = '8px'
page.style.height = '200px'
page.style.marginBottom = '24px'
document.body.appendChild(page)

const areas = [
  { name: 'header',  area: 'header',  bg: '#4a5568', color: 'white', text: 'Header' },
  { name: 'sidebar', area: 'sidebar', bg: '#718096', color: 'white', text: 'Sidebar' },
  { name: 'main',    area: 'main',    bg: '#e2e8f0', color: '#333',  text: 'Main Content' },
  { name: 'footer',  area: 'footer',  bg: '#4a5568', color: 'white', text: 'Footer' },
]

areas.forEach(({ area, bg, color, text }) => {
  const el = document.createElement('div')
  el.style.gridArea = area
  el.style.backgroundColor = bg
  el.style.color = color
  el.style.display = 'flex'
  el.style.alignItems = 'center'
  el.style.justifyContent = 'center'
  el.style.borderRadius = '4px'
  el.style.fontSize = '13px'
  el.textContent = text
  page.appendChild(el)
})

// === Адаптивная галерея с minmax ===
const gallery = document.createElement('div')
gallery.style.display = 'grid'
gallery.style.gridTemplateColumns = 'repeat(3, 1fr)'
gallery.style.gap = '8px'
document.body.appendChild(gallery)

for (let i = 1; i <= 6; i++) {
  const cell = document.createElement('div')
  cell.style.backgroundColor = `hsl(${i * 40}, 70%, 75%)`
  cell.style.height = '60px'
  cell.style.borderRadius = '8px'
  cell.style.display = 'flex'
  cell.style.alignItems = 'center'
  cell.style.justifyContent = 'center'
  cell.style.fontWeight = '600'
  cell.textContent = 'Фото ' + i

  // Первый элемент занимает 2 колонки
  if (i === 1) {
    cell.style.gridColumn = 'span 2'
    cell.textContent += ' (span 2)'
  }
  gallery.appendChild(cell)
}

// Логирование
const pageStyle = window.getComputedStyle(page)
console.log('Page display:', pageStyle.display)                   // grid
console.log('Page columns:', pageStyle.gridTemplateColumns)       // 160px 1fr
console.log('Page gap:', pageStyle.gap)                           // 8px

const galleryStyle = window.getComputedStyle(gallery)
console.log('Gallery columns:', galleryStyle.gridTemplateColumns)
// Примерно: Xpx Xpx Xpx — три равные колонки

const firstCell = gallery.children[0]
const firstStyle = window.getComputedStyle(firstCell)
console.log('Первая ячейка gridColumn:', firstStyle.gridColumn)   // span 2 / span 2

CSS Grid: сетка страницы

Лейаут страницы с шапкой, двумя колонками и подвалом. Галерея фотографий в три колонки. Дашборд с плитками разного размера. Flexbox справляется с одним измерением (строка или колонка), а CSS Grid — с двумя одновременно. Это самый мощный инструмент компоновки в CSS.

Основы Grid

.container {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;  /* 3 колонки */
  grid-template-rows: auto;               /* Строки авто-высоты */
  gap: 16px;
}

Дочерние элементы автоматически распределяются по ячейкам сетки.

grid-template-columns и единица fr

fr (fraction) — дробная единица, делит доступное пространство.

grid-template-columns: 1fr 1fr 1fr;     /* Три равные колонки */
grid-template-columns: 1fr 2fr 1fr;     /* Средняя в 2 раза шире */
grid-template-columns: 200px 1fr;       /* Фиксированная + растягивающаяся */
grid-template-columns: 200px 1fr 300px; /* Фикс + флюид + фикс */

repeat() — повторение

grid-template-columns: repeat(3, 1fr);         /* = 1fr 1fr 1fr */
grid-template-columns: repeat(4, minmax(200px, 1fr));  /* 4 колонки min 200px */

minmax() — диапазон размера

/* Колонка от 200px до 1fr — адаптивный грид */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

Это магия адаптивности без media queries: сколько влезет колонок по 200px — столько и будет.

gap — промежутки

gap: 16px;            /* Все промежутки */
gap: 8px 16px;        /* row-gap column-gap */
row-gap: 8px;
column-gap: 16px;

Позиционирование элементов в сетке

grid-column и grid-row

/* Элемент занимает с 1-й по 3-ю линию колонок = 2 колонки */
.header { grid-column: 1 / 3; }

/* Сокращение: span N — занять N ячеек */
.header { grid-column: span 2; }
.wide-card { grid-column: span 3; }
.tall-item { grid-row: span 2; }

/* Занять всю ширину */
.footer { grid-column: 1 / -1; }  /* -1 = последняя линия */

grid-template-areas — именованные области

Визуальное описание раскладки:

.page {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 60px 1fr 50px;
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
  gap: 8px;
  height: 100vh;
}

.page-header  { grid-area: header; }
.page-sidebar { grid-area: sidebar; }
.page-main    { grid-area: main; }
.page-footer  { grid-area: footer; }

Невероятно читабельно — лейаут прямо в CSS.

auto-placement — автоматическое размещение

По умолчанию Grid сам расставляет элементы слева направо, сверху вниз. Настройки:

grid-auto-flow: row;     /* По умолчанию — строками */
grid-auto-flow: column;  /* По столбцам */
grid-auto-flow: dense;   /* Заполняет дыры — для плотной галереи */

Типичные ошибки

Ошибка 1: Перепутать grid-column с grid-template-columns

/* grid-template-columns — на КОНТЕЙНЕРЕ, задаёт структуру */
.container { grid-template-columns: 1fr 1fr; }

/* grid-column — на ДОЧЕРНЕМ, задаёт его позицию */
.item { grid-column: 1 / 3; }

/* Не наоборот! */

Ошибка 2: fr без явного размера контейнера

/* Если контейнер не имеет размера, fr ведёт себя как auto */
.container { display: grid; grid-template-columns: 1fr 1fr; }
/* Нормально — ширина по родителю */

.container { display: inline-grid; grid-template-columns: 1fr 1fr; }
/* fr = 0, если нет явной ширины */

В реальных проектах

Grid идеален для макросетки страницы: хедер, сайдбар, контент, футер. Внутри секций — обычно Flexbox для рядов элементов. Правило большого пальца: Grid для страницы, Flex для компонентов. Но оба работают на любом уровне — выбирай то, что удобнее для конкретной задачи.

Tailwind CSS предоставляет: grid, grid-cols-3, col-span-2, gap-4 — всё те же концепции.

Примеры

CSS Grid: страничный лейаут и адаптивная галерея

const style = document.createElement('style')
style.textContent = `
  * { box-sizing: border-box; }
  body { font-family: Arial, sans-serif; padding: 16px; }
`
document.head.appendChild(style)

// === Лейаут страницы с grid-template-areas ===
const page = document.createElement('div')
page.style.display = 'grid'
page.style.gridTemplateColumns = '160px 1fr'
page.style.gridTemplateRows = '50px 1fr 40px'
page.style.gridTemplateAreas = '"header header" "sidebar main" "footer footer"'
page.style.gap = '8px'
page.style.height = '200px'
page.style.marginBottom = '24px'
document.body.appendChild(page)

const areas = [
  { name: 'header',  area: 'header',  bg: '#4a5568', color: 'white', text: 'Header' },
  { name: 'sidebar', area: 'sidebar', bg: '#718096', color: 'white', text: 'Sidebar' },
  { name: 'main',    area: 'main',    bg: '#e2e8f0', color: '#333',  text: 'Main Content' },
  { name: 'footer',  area: 'footer',  bg: '#4a5568', color: 'white', text: 'Footer' },
]

areas.forEach(({ area, bg, color, text }) => {
  const el = document.createElement('div')
  el.style.gridArea = area
  el.style.backgroundColor = bg
  el.style.color = color
  el.style.display = 'flex'
  el.style.alignItems = 'center'
  el.style.justifyContent = 'center'
  el.style.borderRadius = '4px'
  el.style.fontSize = '13px'
  el.textContent = text
  page.appendChild(el)
})

// === Адаптивная галерея с minmax ===
const gallery = document.createElement('div')
gallery.style.display = 'grid'
gallery.style.gridTemplateColumns = 'repeat(3, 1fr)'
gallery.style.gap = '8px'
document.body.appendChild(gallery)

for (let i = 1; i <= 6; i++) {
  const cell = document.createElement('div')
  cell.style.backgroundColor = `hsl(${i * 40}, 70%, 75%)`
  cell.style.height = '60px'
  cell.style.borderRadius = '8px'
  cell.style.display = 'flex'
  cell.style.alignItems = 'center'
  cell.style.justifyContent = 'center'
  cell.style.fontWeight = '600'
  cell.textContent = 'Фото ' + i

  // Первый элемент занимает 2 колонки
  if (i === 1) {
    cell.style.gridColumn = 'span 2'
    cell.textContent += ' (span 2)'
  }
  gallery.appendChild(cell)
}

// Логирование
const pageStyle = window.getComputedStyle(page)
console.log('Page display:', pageStyle.display)                   // grid
console.log('Page columns:', pageStyle.gridTemplateColumns)       // 160px 1fr
console.log('Page gap:', pageStyle.gap)                           // 8px

const galleryStyle = window.getComputedStyle(gallery)
console.log('Gallery columns:', galleryStyle.gridTemplateColumns)
// Примерно: Xpx Xpx Xpx — три равные колонки

const firstCell = gallery.children[0]
const firstStyle = window.getComputedStyle(firstCell)
console.log('Первая ячейка gridColumn:', firstStyle.gridColumn)   // span 2 / span 2

Задание

Создай Grid-сетку из трёх колонок с помощью `display: grid` и `grid-template-columns: repeat(3, 1fr)`. Добавь 6 ячеек с разными цветами. Сделай четвёртую ячейку широкой — она должна занимать 2 колонки через `grid-column: span 2`.

Подсказка

`display: grid` включает Grid. `grid-template-columns: repeat(3, 1fr)` создаёт три равные колонки. `grid-column: span 2` растягивает ячейку на 2 колонки.

Загружаем среду выполнения...
Загружаем AI-помощника...