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

Таблицы

Таблицы долгое время использовались для вёрстки всего подряд — это была огромная ошибка. Сегодня таблицы вернулись на своё законное место: для отображения табличных данных. Расписание электричек, прайс-лист, статистика продаж — всё это идеально подходит для таблицы.

Когда таблицы УМЕСТНЫ

  • Расписание (время, маршрут, цена)
  • Прайс-листы и тарифные сетки
  • Сравнительные таблицы тарифов (как у Telegram Premium)
  • Финансовые отчёты и статистика
  • Технические характеристики товара
  • Если данные можно описать словами «строки и столбцы», «для каждого X значение Y» — это таблица.

    Базовая структура

    <table>
      <thead>
        <tr>
          <th>Товар</th>
          <th>Цена</th>
          <th>Количество</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Nike Air Max</td>
          <td>7 990 ₽</td>
          <td>3</td>
        </tr>
        <tr>
          <td>Adidas Superstar</td>
          <td>5 490 ₽</td>
          <td>1</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td>Итого</td>
          <td>29 460 ₽</td>
          <td>4</td>
        </tr>
      </tfoot>
    </table>

    Теги таблицы

    | Тег | Назначение |

    |---|---|

    | <table> | Корень таблицы |

    | <thead> | Группа заголовков |

    | <tbody> | Группа данных |

    | <tfoot> | Группа итогов |

    | <tr> | Строка (table row) |

    | <th> | Ячейка-заголовок (жирный, по центру) |

    | <td> | Обычная ячейка данных (table data) |

    colspan и rowspan — объединение ячеек

    <table>
      <tr>
        <!-- colspan — объединить 2 ячейки по горизонтали -->
        <td colspan="2">Ячейка занимает 2 столбца</td>
      </tr>
      <tr>
        <td>Ячейка 1</td>
        <td>Ячейка 2</td>
      </tr>
    </table>
    <table>
      <tr>
        <!-- rowspan — объединить 2 ячейки по вертикали -->
        <td rowspan="2">Объединено 2 строки</td>
        <td>Строка 1</td>
      </tr>
      <tr>
        <td>Строка 2</td>
      </tr>
    </table>

    scope в th — доступность

    <thead>
      <tr>
        <th scope="col">Товар</th>
        <th scope="col">Цена</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Nike Air Max</th>
        <td>7 990 ₽</td>
      </tr>
    </tbody>

    Атрибут scope говорит скринридерам: этот заголовок относится к столбцу (col) или строке (row).

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

    Ошибка 1: Использовать таблицы для вёрстки

    <!-- Так делали в 2000-х — теперь это антипаттерн -->
    <table>
      <tr>
        <td>Сайдбар</td>
        <td>Основной контент</td>
        <td>Реклама</td>
      </tr>
    </table>
    <!-- Используй CSS Grid или Flexbox для макета -->

    Ошибка 2: Забыть thead и tbody

    <!-- Работает, но некорректно семантически -->
    <table>
      <tr><th>Имя</th><th>Возраст</th></tr>
      <tr><td>Иван</td><td>25</td></tr>
    </table>
    
    <!-- Правильно — с thead и tbody -->
    <table>
      <thead><tr><th>Имя</th><th>Возраст</th></tr></thead>
      <tbody><tr><td>Иван</td><td>25</td></tr></tbody>
    </table>

    Ошибка 3: Неправильный colspan

    Если в строке три столбца, и ты объединяешь два, суммарное количество ячеек должно оставаться три. Иначе таблица «сломается».

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

    Таблицы активно используются в административных панелях, CRM-системах, дашбордах аналитики. Библиотеки TanStack Table (React), Vuetify DataTable — все строятся поверх обычного <table>. Понимание структуры таблицы обязательно при работе с такими компонентами.

    Примеры

    Создание таблицы прайс-листа через DOM

    // Создаём таблицу прайс-листа
    const table = document.createElement('table')
    
    // Данные товаров
    const products = [
      { name: 'Nike Air Max 90', category: 'Кроссовки', price: 7990, qty: 42 },
      { name: 'Adidas Superstar', category: 'Кроссовки', price: 5490, qty: 18 },
      { name: 'Puma RS-X', category: 'Кроссовки', price: 6290, qty: 7 },
    ]
    
    // Создаём thead
    const thead = document.createElement('thead')
    const headerRow = document.createElement('tr')
    const headers = ['Товар', 'Категория', 'Цена', 'Склад']
    
    headers.forEach(text => {
      const th = document.createElement('th')
      th.textContent = text
      headerRow.appendChild(th)
    })
    thead.appendChild(headerRow)
    table.appendChild(thead)
    
    // Создаём tbody
    const tbody = document.createElement('tbody')
    products.forEach(product => {
      const tr = document.createElement('tr')
      const cells = [product.name, product.category, product.price + ' ₽', product.qty + ' шт.']
      cells.forEach(text => {
        const td = document.createElement('td')
        td.textContent = text
        tr.appendChild(td)
      })
      tbody.appendChild(tr)
    })
    table.appendChild(tbody)
    
    // Выводим структуру
    console.log('Таблица создана:', table.tagName)
    console.log('Строк в заголовке:', table.tHead.rows.length)
    console.log('Строк в теле:', table.tBodies[0].rows.length)
    console.log('Столбцов:', table.tHead.rows[0].cells.length)
    
    // Первая строка данных
    const firstRow = table.tBodies[0].rows[0]
    console.log('Первый товар:', firstRow.cells[0].textContent)
    console.log('Цена:', firstRow.cells[2].textContent)

    Вычисление итогов по таблице — как в Excel

    // Данные заказов (имитация таблицы в браузере)
    const orders = [
      { id: 1, product: 'Nike Air Max', price: 7990, qty: 2 },
      { id: 2, product: 'Adidas Stan Smith', price: 4990, qty: 1 },
      { id: 3, product: 'Puma Suede', price: 5490, qty: 3 },
    ]
    
    // Печатаем таблицу в консоль
    console.log('ID  | Товар              | Цена    | Кол-во | Сумма')
    console.log('----|--------------------|---------|--------|------')
    
    let totalSum = 0
    let totalQty = 0
    
    orders.forEach(order => {
      const sum = order.price * order.qty
      totalSum += sum
      totalQty += order.qty
    
      const row = [
        String(order.id).padEnd(4),
        order.product.padEnd(20),
        (order.price + ' ₽').padEnd(9),
        String(order.qty).padEnd(8),
        sum + ' ₽'
      ].join('| ')
    
      console.log(row)
    })
    
    // tfoot — итоговая строка
    console.log('----|--------------------|---------|--------|------')
    console.log('ИТОГО: ' + totalQty + ' товаров на сумму ' + totalSum + ' ₽')

    Таблицы

    Таблицы долгое время использовались для вёрстки всего подряд — это была огромная ошибка. Сегодня таблицы вернулись на своё законное место: для отображения табличных данных. Расписание электричек, прайс-лист, статистика продаж — всё это идеально подходит для таблицы.

    Когда таблицы УМЕСТНЫ

  • Расписание (время, маршрут, цена)
  • Прайс-листы и тарифные сетки
  • Сравнительные таблицы тарифов (как у Telegram Premium)
  • Финансовые отчёты и статистика
  • Технические характеристики товара
  • Если данные можно описать словами «строки и столбцы», «для каждого X значение Y» — это таблица.

    Базовая структура

    <table>
      <thead>
        <tr>
          <th>Товар</th>
          <th>Цена</th>
          <th>Количество</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Nike Air Max</td>
          <td>7 990 ₽</td>
          <td>3</td>
        </tr>
        <tr>
          <td>Adidas Superstar</td>
          <td>5 490 ₽</td>
          <td>1</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td>Итого</td>
          <td>29 460 ₽</td>
          <td>4</td>
        </tr>
      </tfoot>
    </table>

    Теги таблицы

    | Тег | Назначение |

    |---|---|

    | <table> | Корень таблицы |

    | <thead> | Группа заголовков |

    | <tbody> | Группа данных |

    | <tfoot> | Группа итогов |

    | <tr> | Строка (table row) |

    | <th> | Ячейка-заголовок (жирный, по центру) |

    | <td> | Обычная ячейка данных (table data) |

    colspan и rowspan — объединение ячеек

    <table>
      <tr>
        <!-- colspan — объединить 2 ячейки по горизонтали -->
        <td colspan="2">Ячейка занимает 2 столбца</td>
      </tr>
      <tr>
        <td>Ячейка 1</td>
        <td>Ячейка 2</td>
      </tr>
    </table>
    <table>
      <tr>
        <!-- rowspan — объединить 2 ячейки по вертикали -->
        <td rowspan="2">Объединено 2 строки</td>
        <td>Строка 1</td>
      </tr>
      <tr>
        <td>Строка 2</td>
      </tr>
    </table>

    scope в th — доступность

    <thead>
      <tr>
        <th scope="col">Товар</th>
        <th scope="col">Цена</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Nike Air Max</th>
        <td>7 990 ₽</td>
      </tr>
    </tbody>

    Атрибут scope говорит скринридерам: этот заголовок относится к столбцу (col) или строке (row).

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

    Ошибка 1: Использовать таблицы для вёрстки

    <!-- Так делали в 2000-х — теперь это антипаттерн -->
    <table>
      <tr>
        <td>Сайдбар</td>
        <td>Основной контент</td>
        <td>Реклама</td>
      </tr>
    </table>
    <!-- Используй CSS Grid или Flexbox для макета -->

    Ошибка 2: Забыть thead и tbody

    <!-- Работает, но некорректно семантически -->
    <table>
      <tr><th>Имя</th><th>Возраст</th></tr>
      <tr><td>Иван</td><td>25</td></tr>
    </table>
    
    <!-- Правильно — с thead и tbody -->
    <table>
      <thead><tr><th>Имя</th><th>Возраст</th></tr></thead>
      <tbody><tr><td>Иван</td><td>25</td></tr></tbody>
    </table>

    Ошибка 3: Неправильный colspan

    Если в строке три столбца, и ты объединяешь два, суммарное количество ячеек должно оставаться три. Иначе таблица «сломается».

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

    Таблицы активно используются в административных панелях, CRM-системах, дашбордах аналитики. Библиотеки TanStack Table (React), Vuetify DataTable — все строятся поверх обычного <table>. Понимание структуры таблицы обязательно при работе с такими компонентами.

    Примеры

    Создание таблицы прайс-листа через DOM

    // Создаём таблицу прайс-листа
    const table = document.createElement('table')
    
    // Данные товаров
    const products = [
      { name: 'Nike Air Max 90', category: 'Кроссовки', price: 7990, qty: 42 },
      { name: 'Adidas Superstar', category: 'Кроссовки', price: 5490, qty: 18 },
      { name: 'Puma RS-X', category: 'Кроссовки', price: 6290, qty: 7 },
    ]
    
    // Создаём thead
    const thead = document.createElement('thead')
    const headerRow = document.createElement('tr')
    const headers = ['Товар', 'Категория', 'Цена', 'Склад']
    
    headers.forEach(text => {
      const th = document.createElement('th')
      th.textContent = text
      headerRow.appendChild(th)
    })
    thead.appendChild(headerRow)
    table.appendChild(thead)
    
    // Создаём tbody
    const tbody = document.createElement('tbody')
    products.forEach(product => {
      const tr = document.createElement('tr')
      const cells = [product.name, product.category, product.price + ' ₽', product.qty + ' шт.']
      cells.forEach(text => {
        const td = document.createElement('td')
        td.textContent = text
        tr.appendChild(td)
      })
      tbody.appendChild(tr)
    })
    table.appendChild(tbody)
    
    // Выводим структуру
    console.log('Таблица создана:', table.tagName)
    console.log('Строк в заголовке:', table.tHead.rows.length)
    console.log('Строк в теле:', table.tBodies[0].rows.length)
    console.log('Столбцов:', table.tHead.rows[0].cells.length)
    
    // Первая строка данных
    const firstRow = table.tBodies[0].rows[0]
    console.log('Первый товар:', firstRow.cells[0].textContent)
    console.log('Цена:', firstRow.cells[2].textContent)

    Вычисление итогов по таблице — как в Excel

    // Данные заказов (имитация таблицы в браузере)
    const orders = [
      { id: 1, product: 'Nike Air Max', price: 7990, qty: 2 },
      { id: 2, product: 'Adidas Stan Smith', price: 4990, qty: 1 },
      { id: 3, product: 'Puma Suede', price: 5490, qty: 3 },
    ]
    
    // Печатаем таблицу в консоль
    console.log('ID  | Товар              | Цена    | Кол-во | Сумма')
    console.log('----|--------------------|---------|--------|------')
    
    let totalSum = 0
    let totalQty = 0
    
    orders.forEach(order => {
      const sum = order.price * order.qty
      totalSum += sum
      totalQty += order.qty
    
      const row = [
        String(order.id).padEnd(4),
        order.product.padEnd(20),
        (order.price + ' ₽').padEnd(9),
        String(order.qty).padEnd(8),
        sum + ' ₽'
      ].join('| ')
    
      console.log(row)
    })
    
    // tfoot — итоговая строка
    console.log('----|--------------------|---------|--------|------')
    console.log('ИТОГО: ' + totalQty + ' товаров на сумму ' + totalSum + ' ₽')

    Задание

    Напиши HTML-таблицу расписания уроков: thead с заголовками "День", "Урок 1", "Урок 2", "Урок 3". В tbody три строки: Понедельник (Математика, Физика, Химия), Вторник (История, Биология, Математика), Среда (Физика, Литература, Информатика). Добавь caption "Расписание на неделю". Ячейкам с "Математика" задай жёлтый фон через class="math".

    Подсказка

    caption — подпись таблицы. th — ячейка заголовка. td — ячейка данных. Класс применяется атрибутом class="math". border-collapse: collapse убирает двойные границы. Строки таблицы должны иметь одинаковое количество ячеек.

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