иконка discount

Скидка 15% по промокоду

кибер понедельник до 01.12иконка discount
CYBER2025
логотип PurpleSchool
логотип PurpleSchool

Группа колонок HTML colgroup

Автор

Олег Марков

Введение

Тег <colgroup> в HTML часто остается «за кадром», потому что визуально он ничего не рисует и не влияет на содержимое таблицы напрямую. Но когда вы начинаете верстать сложные таблицы, особенно с фиксированной шириной колонок, единым стилем для целых столбцов и адаптивным поведением, <colgroup> оказывается очень полезным инструментом.

В этой статье вы увидите, как с помощью <colgroup>:

  • задавать ширину и стили сразу для целых колонок, а не для каждой ячейки;
  • удобно управлять оформлением: скрывать столбцы, задавать общий фон, границы и выравнивание;
  • улучшать структуру и семантику таблиц;
  • настраивать поведение таблиц в адаптивной верстке.

Давайте постепенно разберем, как работает <colgroup>, какие у него ограничения и где он действительно помогает упростить код.

Что такое <colgroup> и зачем он нужен

Основная идея тега <colgroup>

<colgroup> — это контейнер, который описывает группу колонок таблицы. Он размещается внутри <table> и до строк <tr>. Вместе с тегом <col> он позволяет:

  • задавать свойства сразу для всего столбца (ширина, стили);
  • логически группировать несколько колонок, например: «колонки с ценами» или «колонки с контактами»;
  • отделить описание структуры таблицы от ее содержимого.

Упрощенно структура таблицы с использованием <colgroup> выглядит так:

<table>
  <colgroup>
    <!-- Здесь мы описываем столбцы -->
    <col>
    <col>
  </colgroup>
  <!-- А здесь уже идет содержимое -->
  <tr>
    <td>...</td>
    <td>...</td>
  </tr>
</table>

Зачем использовать <colgroup>, если есть CSS классы

Многие задают вопрос: «Почему бы просто не навесить классы на td или th?». Использовать только классы — вполне рабочий вариант, но у <colgroup> есть несколько преимуществ:

  • Стили применяются сразу ко всем ячейкам столбца
    Вам не нужно дублировать класс в каждой ячейке.

  • Семантика структуры
    Вы явно описываете архитектуру таблицы: какие есть колонки, как они сгруппированы.

  • Одно место для управления шириной колонок
    Ширину удобнее задавать на уровне <col> — браузеры довольно предсказуемо ее учитывают при рендеринге.

  • Удобство при генерации таблиц на бэкенде или в JS
    Содержимое может меняться, а структура колонок остается неизменной и управляется отдельным фрагментом кода.

Синтаксис и базовое использование <colgroup> и <col>

Где и как размещать <colgroup>

<colgroup> всегда размещается внутри <table> и только до первой строки <tr> или секций <thead>, <tbody>, <tfoot>.

Корректное размещение:

<table>
  <!-- Сначала colgroup -->
  <colgroup>
    <col span="1">
    <col span="2">
  </colgroup>

  <!-- Затем заголовок и тело таблицы -->
  <thead>
    <tr>
      <th>Имя</th>
      <th>Возраст</th>
      <th>Город</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Анна</td>
      <td>28</td>
      <td>Москва</td>
    </tr>
  </tbody>
</table>

Если попытаться вставить <colgroup> после строк, браузер, как правило, перенесет его в начало таблицы или просто проигнорирует.

Атрибуты <colgroup>

У тега <colgroup> по сути есть два важных атрибута:

  • span — количество колонок, к которым относится эта группа (когда внутри нет <col>);
  • глобальные атрибуты (например, class, id, style, data-*), которые вы можете использовать для CSS или JavaScript.

Пример с span на <colgroup> без вложенных <col>:

<table>
  <colgroup span="3" class="summary-columns">
    <!-- Здесь нет отдельных <col> внутри -->
  </colgroup>

  <tr>
    <th>Товар</th>
    <th>Количество</th>
    <th>Цена</th>
  </tr>
  <tr>
    <td>Ноутбук</td>
    <td>2</td>
    <td>120000</td>
  </tr>
</table>

Комментарии к примеру:

// colgroup c span="3" означает - эта группа относится к трем первым столбцам
// class="summary-columns" можно использовать в CSS для стилизации всех этих трех колонок

Если вы используете вложенные <col>, атрибут span уже применяете к каждому <col>, а не к <colgroup>.

Тег <col> и его атрибуты

Чаще всего вы будете работать именно с <col> внутри <colgroup>. У <col> есть несколько полезных атрибутов:

  • span — задает, на сколько колонок распространяется этот <col>;
  • width — рекомендуемая ширина колонок (про нее мы еще поговорим подробно);
  • глобальные атрибуты (class, style, id и т.д.).

Пример:

<table>
  <colgroup>
    <col span="1" style="width: 30%;">
    <!-- Один столбец шириной 30% -->
    <col span="2" style="width: 35%;">
    <!-- Два столбца, каждый по 35% -->
  </colgroup>
  <tr>
    <th>Имя</th>
    <th>Компания</th>
    <th>Должность</th>
  </tr>
  <tr>
    <td>Игорь</td>
    <td>Example Corp</td>
    <td>Разработчик</td>
  </tr>
</table>

Комментарии:

// Первый col - описывает первую колонку
// Второй col со span="2" - описывает вторую и третью колонки
// Ширина задается через inline-стиль, но лучше выносить такие вещи в CSS

Управление шириной колонок через <colgroup>

Как работает атрибут width и CSS-свойство width

Смотрите, я покажу вам два способа задать ширину колонок:

  1. через атрибут width:
  2. через CSS width (inline или через класс).

Рекомендуемая практика — использовать CSS, но атрибут width все еще поддерживается и работает примерно как style="width: ...".

Пример с CSS:

<style>
  /* Здесь мы задаем ширину столбцов через класс */
  col.col-name {
    width: 40%;
  }

  col.col-age {
    width: 20%;
  }

  col.col-city {
    width: 40%;
  }

  /* Включаем фиксированный режим раскладки колонок */
  table.fixed-layout {
    table-layout: fixed;
    width: 100%;
  }
</style>

<table class="fixed-layout">
  <colgroup>
    <col class="col-name">
    <col class="col-age">
    <col class="col-city">
  </colgroup>
  <tr>
    <th>Имя</th>
    <th>Возраст</th>
    <th>Город</th>
  </tr>
  <tr>
    <td>Мария</td>
    <td>31</td>
    <td>Санкт-Петербург</td>
  </tr>
</table>

Комментарии:

// Мы используем table-layout fixed чтобы браузер ориентировался на ширину колонок
// Каждому col присваиваем класс и через него задаем ширину
// Так ширина задается один раз и действует для всех строк и ячеек столбца

Взаимодействие с table-layout: fixed и auto

Поведение ширины колонок сильно зависит от значения table-layout у таблицы:

  • table-layout: auto (значение по умолчанию)
    Браузер рассчитывает ширину колонок на основе содержимого. Ширина из <col> — это только подсказка, не строгая гарантия.

  • table-layout: fixed
    Браузер опирается на заданную ширину колонок (через <col>, th, td или стили таблицы). Содержимое может переноситься или обрезаться, чтобы укладываться в эти ограничения.

Если вам важно фиксировано контролировать ширину колонок — задавайте table-layout: fixed и ширину через <col> или CSS.

Давайте разберемся на небольшом примере влияния длинного текста:

<style>
  table.auto-layout {
    table-layout: auto;
    width: 100%;
  }

  table.fixed-layout {
    table-layout: fixed;
    width: 100%;
  }

  col.col-narrow {
    width: 100px;
  }
</style>

<h3>table-layout auto</h3>
<table class="auto-layout">
  <colgroup>
    <col class="col-narrow">
    <col>
  </colgroup>
  <tr>
    <th>Колонка 1</th>
    <th>Колонка 2</th>
  </tr>
  <tr>
    <td>Очень длинный текст, который расширяет колонку</td>
    <td>Короткий</td>
  </tr>
</table>

<h3>table-layout fixed</h3>
<table class="fixed-layout">
  <colgroup>
    <col class="col-narrow">
    <col>
  </colgroup>
  <tr>
    <th>Колонка 1</th>
    <th>Колонка 2</th>
  </tr>
  <tr>
    <td>Очень длинный текст, который расширяет колонку</td>
    <td>Короткий</td>
  </tr>
</table>

Комментарии:

// В первой таблице длинный текст может «раздуть» колонку
// Во второй таблице ширина первой колонки останется ближе к 100px
// При необходимости используйте word-wrap или text-overflow для контроля текста

Стилизация столбцов: цвет, фон, границы, видимость

Какие CSS-свойства работают через <col> и <colgroup>

Важно понимать, что столбец — не реальный визуальный элемент, поэтому не все CSS-свойства, которые вы привыкли задавать для td/th, сработают, если задать их на <col> или <colgroup>.

В современных браузерах обычно можно рассчитывать на:

  • width
  • background / background-color
  • border (в комбинации с border-collapse: collapse)
  • некоторые свойства, влияющие на макет (например, visibility)

Но, например, padding или text-align, заданные на <col>, как правило, не применятся к содержимому автоматически.

Пример:

<style>
  table.col-styles {
    border-collapse: collapse;
    width: 100%;
  }

  table.col-styles th,
  table.col-styles td {
    border: 1px solid #ccc;
    padding: 4px 8px;
  }

  /* Задаем фон и рамку для всех ячеек первого столбца */
  col.first-col {
    background-color: #f0f8ff;
    border-right: 2px solid #007acc;
  }

  /* Делаем второй столбец визуально "выключенным" */
  col.second-col {
    background-color: #f9f9f9;
  }
</style>

<table class="col-styles">
  <colgroup>
    <col class="first-col">
    <col class="second-col">
    <col>
  </colgroup>
  <tr>
    <th>Параметр</th>
    <th>Значение</th>
    <th>Комментарий</th>
  </tr>
  <tr>
    <td>Размер</td>
    <td>XL</td>
    <td>Свободный крой</td>
  </tr>
</table>

Комментарии:

// col.first-col задает фон и правую рамку всей первой колонке
// col.second-col задает фон только второй колонке
// Паддинги и выравнивание мы по-прежнему задаем на th и td

Как скрыть целый столбец

Иногда удобно скрывать целые столбцы, не трогая разметку строк. Для этого можно использовать visibility: collapse или display: none на <col>.

Например:

<style>
  table.collapsible {
    border-collapse: collapse;
  }

  table.collapsible th,
  table.collapsible td {
    border: 1px solid #ccc;
    padding: 4px 8px;
  }

  /* Скрываем второй столбец */
  col.hidden-col {
    visibility: collapse;
    /* В некоторых браузерах может понадобиться display:none */
  }
</style>

<table class="collapsible">
  <colgroup>
    <col>
    <col class="hidden-col">
    <col>
  </colgroup>
  <tr>
    <th>Имя</th>
    <th>Телефон</th>
    <th>Email</th>
  </tr>
  <tr>
    <td>Сергей</td>
    <td>+7 900 000-00-00</td>
    <td>sergey@example.com</td>
  </tr>
</table>

Комментарии:

// col.hidden-col управляет видимостью сразу всего второго столбца
// visibility collapse ведет себя по-разному в браузерах - иногда лучше использовать display none
// Иногда полезно комбинировать это с медиа-запросами для адаптивных таблиц

Группировка колонок и несколько <colgroup> в одной таблице

Несколько <colgroup> и их порядок

В одной таблице вы можете объявить несколько <colgroup>. Браузер интерпретирует их последовательно: количество колонок, описанное в каждом <colgroup>, «накладывается» друг за другом слева направо.

Пример:

<table>
  <colgroup span="2" class="info-group">
    <!-- Описывает первые две колонки -->
  </colgroup>
  <colgroup span="1" class="price-group">
    <!-- Описывает третью колонку -->
  </colgroup>

  <tr>
    <th>Товар</th>
    <th>Категория</th>
    <th>Цена</th>
  </tr>
  <tr>
    <td>Монитор</td>
    <td>Электроника</td>
    <td>12000</td>
  </tr>
</table>

Комментарии:

// Первый colgroup применится к колонкам 1 и 2
// Второй colgroup - к колонке 3
// Классы info-group и price-group можно использовать в CSS чтобы выделять группы колонок

Так вы можете логически разделять зоны таблицы: «основная информация», «финансовые показатели», «служебные данные» и т.п.

Смешивание <colgroup> с <col>

Вы можете комбинировать <colgroup> с атрибутом span и с вложенными <col>, но важно помнить правило:

  • либо <colgroup span="N"> без <col> внутри,
  • либо <colgroup>…<col>…</colgroup> без span у самого <colgroup>.

Пример корректной комбинации нескольких групп с <col>:

<style>
  col.main-info {
    background-color: #f5f5f5;
  }

  col.prices {
    background-color: #fffbe6;
  }
</style>

<table>
  <!-- Группа из двух колонок с заданными col -->
  <colgroup>
    <col class="main-info">
    <col class="main-info">
  </colgroup>

  <!-- Группа из одной колонки через span -->
  <colgroup span="1" class="prices-group">
  </colgroup>

  <tr>
    <th>Товар</th>
    <th>Категория</th>
    <th>Цена</th>
  </tr>
  <tr>
    <td>Стол</td>
    <td>Мебель</td>
    <td>8500</td>
  </tr>
</table>

Комментарии:

// Первый colgroup управляет первыми двумя колонками через col.main-info
// Второй colgroup через span="1" отвечает за третью колонку
// Класс prices-group можно использовать для общих стилей всей группы

Взаимодействие <colgroup> с rowspan и colspan

Как работает colspan с <colgroup>

Когда вы используете colspan в th или td, вы объединяете несколько колонок. <colgroup> и <col> при этом все равно считаются слева направо.

Например:

<table>
  <colgroup>
    <col class="col-a">
    <col class="col-b">
    <col class="col-c">
  </colgroup>
  <tr>
    <th colspan="2">Основная информация</th>
    <th>Статус</th>
  </tr>
  <tr>
    <td>Заказ 123</td>
    <td>Клиент Иванов</td>
    <td>Оплачен</td>
  </tr>
</table>

Комментарии:

// col-a относится к первой колонке (часть "Основной информации")
// col-b - ко второй колонке (тоже часть "Основной информации")
// col-c - к третьей колонке "Статус"
// colspan не меняет того, как колонки нумеруются для colgroup

Если вам нужно стилизовать объединенные колонки одинаково, вы можете:

  • задать одинаковые стили для нескольких <col> (например, .group-1 { ... });
  • или использовать один <col span="N">, если не нужны индивидуальные стили.

Что важно знать про rowspan

rowspan объединяет ячейки по вертикали, но не влияет на количество колонок. Для <colgroup> количество колонок всегда определяется по максимальному количеству ячеек по горизонтали с учетом colspan, а не rowspan.

Из этого следует:

  • стили через <col> будут применяться независимо от того, объединены ли ячейки по вертикали;
  • rowspan не сбивает нумерацию колонок.

Адаптивные и динамические таблицы с <colgroup>

Управление таблицами на CSS при разных ширинах экрана

Часто таблицы на мобильных устройствах должны выглядеть иначе: какие-то столбцы скрываются, какие-то меняют ширину. <colgroup> дает удобную «точку управления» для таких изменений.

Пример с медиа-запросом:

<style>
  table.orders {
    border-collapse: collapse;
    width: 100%;
  }

  table.orders th,
  table.orders td {
    border: 1px solid #ddd;
    padding: 4px 6px;
  }

  /* По умолчанию все колонки видны */
  col.order-id    { width: 15%; }
  col.order-date  { width: 25%; }
  col.order-name  { width: 40%; }
  col.order-total { width: 20%; }

  /* На маленьких экранах скрываем ID, расширяем остальные */
  @media (max-width: 600px) {
    col.order-id {
      display: none; /* Скрываем первый столбец */
    }

    col.order-date,
    col.order-name,
    col.order-total {
      width: auto;
    }
  }
</style>

<table class="orders">
  <colgroup>
    <col class="order-id">
    <col class="order-date">
    <col class="order-name">
    <col class="order-total">
  </colgroup>
  <tr>
    <th>ID</th>
    <th>Дата</th>
    <th>Клиент</th>
    <th>Сумма</th>
  </tr>
  <tr>
    <td>1001</td>
    <td>01.10.2025</td>
    <td>ООО Ромашка</td>
    <td>150000</td>
  </tr>
</table>

Комментарии:

// На больших экранах видны все колонки
// На узких экранах col.order-id скрывается и первый столбец исчезает
// Остальные колонки перераспределяют ширину автоматически

Имейте в виду, что поддержка display: none для <col> может немного отличаться между браузерами. Если столкнетесь с проблемами, можно использовать классы на td/th совместно с <colgroup>.

Динамическое управление колонками через JavaScript

Если таблица генерируется динамически (например, данные приходят с сервера), управление колонками можно делать тоже динамически — изменять DOM внутри <colgroup>.

Простейший пример на JavaScript:

<table id="users-table">
  <colgroup id="users-colgroup">
    <col class="col-name">
    <col class="col-email">
    <col class="col-role">
  </colgroup>
  <tr>
    <th>Имя</th>
    <th>Email</th>
    <th>Роль</th>
  </tr>
  <tr>
    <td>Антон</td>
    <td>anton@example.com</td>
    <td>Админ</td>
  </tr>
</table>

<script>
  // Здесь мы программно добавляем еще одну колонку "Статус"
  const colgroup = document.getElementById('users-colgroup');

  // Создаем новый элемент col
  const statusCol = document.createElement('col');
  statusCol.className = 'col-status';

  // Добавляем его в конец colgroup
  colgroup.appendChild(statusCol);

  // Теперь нужно добавить новую ячейку в каждую строку таблицы
  const table = document.getElementById('users-table');
  const rows = table.rows; // HTMLCollection всех строк

  // Пробегаемся по строкам и добавляем ячейки
  for (let i = 0; i < rows.length; i++) {
    const row = rows[i];

    // Для первой строки добавляем заголовок
    if (i === 0) {
      const th = document.createElement('th');
      th.textContent = 'Статус';
      row.appendChild(th);
    } else {
      // Для остальных строк добавляем обычную ячейку
      const td = document.createElement('td');
      td.textContent = 'Активен';
      row.appendChild(td);
    }
  }
</script>

Комментарии:

// Мы добавляем новый col в colgroup чтобы описать новую колонку
// После этого добавляем ячейки в каждую строку - структура таблицы должна быть согласованной
// Такой подход удобен если набор колонок зависит от настроек пользователя

Лучшие практики и типичные ошибки при использовании <colgroup>

Когда <colgroup> использовать стоит

Использование <colgroup> оправдано, когда:

  • у вас таблица с большим количеством строк и повторяющимися стилями колонок;
  • важно централизованно управлять шириной и фоном столбцов;
  • есть логическое разделение колонок на группы (например, «контактная информация», «финансовые показатели»);
  • нужно динамически скрывать/показывать столбцы по условию (адаптивная верстка, фильтры).

В таких случаях <colgroup>:

  • сокращает дублирование стилей;
  • упрощает поддержку и расширение таблицы;
  • делает структуру таблицы понятнее другому разработчику.

Когда <colgroup> можно не использовать

<colgroup> избыточен, если:

  • у таблицы всего 2–3 колонки и нет сложного управления шириной;
  • стилизация идет по ячейкам (например, разный фон для строк в зависимости от данных);
  • таблица минимальная и редко меняется.

Тогда проще обойтись классами на th/td или использовать более «карточный» формат, а не таблицу.

Частые ошибки

Вот несколько распространенных проблем, с которыми сталкиваются при работе с <colgroup>:

  1. Неправильный порядок элементов внутри <table>
    Размещение <colgroup> после <tr> приводит к тому, что браузер либо перемещает его, либо игнорирует.

  2. Смешивание span и <col> внутри одного <colgroup>
    По спецификации, если в <colgroup> есть <col>, атрибут span у <colgroup> использовать нельзя.

  3. Ожидание, что все CSS-свойства будут работать через <col>
    Паддинги, выравнивание текста и прочие визуальные детали все равно нужно задавать на th/td.

  4. Несоответствие количества колонок описанию в <colgroup>
    Если таблица изменяется динамически, а <colgroup> нет — стили могут применяться не к тем столбцам, к которым вы ожидаете.

  5. Использование только атрибута width без table-layout: fixed
    В режиме auto браузер ориентируется больше на содержимое. Для строгого контроля ширины колонок включайте фиксированную раскладку.

Краткое резюме по <colgroup>

  • <colgroup> описывает группы колонок таблицы и всегда располагается в начале <table>, до строк.
  • Внутри <colgroup> чаще всего используются <col>, к которым вы привязываете ширину и базовые стили.
  • Через <col> удобно управлять шириной и фоном столбцов, а также скрывать колонки.
  • table-layout: fixed делает ширину колонок более предсказуемой и контролируемой.
  • <colgroup> особенно полезен в больших, динамических и адаптивных таблицах.

Если вы верстаете сложные таблицы регулярно, имеет смысл привыкнуть задавать структуру колонок с помощью <colgroup> — это делает код более прозрачным и управляемым.

Частозадаваемые технические вопросы по теме и ответы

Как задать разную ширину для нескольких колонок одним <col> с span

Никак. Атрибут span на <col> распространяет один и тот же набор стилей на несколько соседних колонок. Если вам нужна разная ширина, создайте несколько <col>:

<colgroup>
  <col style="width: 20%;">
  <col style="width: 30%;">
  <col style="width: 50%;">
</colgroup>

Можно ли через <colgroup> задать text-align для всего столбца

Браузеры обычно не применяют text-align с <col> или <colgroup> к содержимому. Надежнее использовать:

<style>
  td.price,
  th.price {
    text-align: right;
  }
</style>

и назначать класс price для ячеек нужного столбца. <colgroup> в этом случае можно использовать только для ширины и фона.

Как сделать так, чтобы ширина колонок из <col> учитывалась при автоподборе ширины таблицы

Если таблица не должна растягиваться на 100% ширины контейнера, уберите фиксированную ширину у table (не задавайте width: 100%) и оставьте ширину на <col>. Тогда браузер подстроит ширину таблицы под суммарную ширину колонок и содержимое. При сложных таблицах используйте table-layout: fixed и явно задавайте ширину.

Почему фон, заданный через <col>, не всегда виден

Фон через <col> может не быть заметен, если:

  • у ячеек (td, th) уже задан собственный background;
  • высота ячейки определяется содержимым, а не растягивается.

Проверьте, нет ли у ячеек своего фона, и попробуйте убрать background у td/th. Если нужен фон только для части столбца, проще задать класс ячейкам и стилизовать их напрямую.

Как сделать, чтобы <colgroup> работал в сочетании с фреймворками (например, Bootstrap таблицами)

Фреймворки часто задают стили таблиц через классы (.table, .table-striped и т.п.). <colgroup> вы можете использовать параллельно:

  • оставляете классы фреймворка на <table>;
  • добавляете <colgroup> для дополнительного контроля ширины или фона;
  • если стили конфликтуют, используйте более специфичные селекторы, например table.table col.col-price { ... }.

Следите, чтобы фреймворк не задавал жесткую ширину на th/td, которая может перекрывать настройки <col>.

Стрелочка влевоHTML тег table - как создавать и оформлять таблицы на практике

Постройте личный план изучения Html до уровня Middle — бесплатно!

Html — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Все гайды по Html

Тег section в HTML - семантическая разметка структуры страницыТег nav в HTML - полное руководство по семантической навигацииТег main в HTML - подробное руководство по использованиюТег header в HTML - полное практическое руководствоТег footer в HTML - назначение семантика и практические примерыТег figure в HTML - как правильно оформлять иллюстрации и подписиТег figcaption в HTML - подробное руководство с примерамиТег aside в HTML - назначение правильная семантика и примеры
Текстовая область HTML textarea - практическое руководствоВыпадающий список HTML select - полное руководство для разработчиковОпция списка HTML option - как работает и как правильно использоватьАтрибут method в HTML - как правильно отправлять данные формыЗаголовок группы HTML legend - как правильно использовать и оформлятьТег input в HTML - типы атрибуты валидация и примерыТег формы form в HTMLГруппа полей HTML fieldsetАтрибут action в HTML - как правильно задавать адрес отправки формы
Открыть базу знаний

Лучшие курсы по теме

изображение курса

HTML и CSS

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий