иконка discount

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

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

Заголовок details в HTML - summary

Автор

Олег Марков

Введение

Элементы details и summary в HTML позволяют создавать раскрывающиеся блоки без единой строчки JavaScript. Вы можете сделать «спойлер», FAQ, секцию с дополнительными параметрами формы или техническими подробностями буквально парой строк разметки.

Смотрите, я покажу вам, как это выглядит в самой простой форме:

<details>
  <summary>Показать подробности</summary>
  <p>Здесь находится дополнительная информация.</p>
</details>

Как только вы откроете такую страницу в браузере, заголовок с текстом «Показать подробности» станет кликабельным, а содержимое будет скрыто до первого клика. При повторном клике блок снова свернется.

В этой статье мы разберем, как именно устроены details и summary, какие у них семантические особенности, как они влияют на доступность, как их стилизовать и чего стоит избегать. Покажу вам, как использовать их грамотно и в простых проектах, и в интерфейсах посложнее.


Что такое details и summary

Назначение элемента details

Элемент <details> — это контейнер, который:

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

Если говорить проще, <details> — это семантический «раскрывающийся блок».

Важные особенности:

  • по умолчанию содержимое свернуто, если атрибут open не указан;
  • браузер добавляет собственный маркер (обычно треугольник или стрелку);
  • переключение состояния происходит без JavaScript, на чистом HTML.

Роль элемента summary

Элемент <summary> — это краткий заголовок или аннотация к содержимому <details>. По сути, это «кнопка», по которой пользователь раскрывает или сворачивает блок. Но при этом:

  • формально это не <button>, а именно заголовок/текст;
  • он кликабелен и фокусируется с клавиатуры;
  • по клику или нажатию Enter/Space переключает состояние родительского <details>.

Простой пример, чтобы вы увидели базовую структуру:

<details>
  <summary>Условия доставки</summary>
  <p>Мы осуществляем доставку по всей стране в течение 3–5 рабочих дней.</p>
</details>

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

  • <details> — оборачивает и заголовок, и содержимое;
  • <summary> — первая строка, которая отображается всегда и по которой можно кликать;
  • <p> — то, что показывается только в открытом состоянии.

Базовый синтаксис и атрибут open

Минимально рабочий пример

Давайте разберемся на самом простом примере с атрибутом open:

<details open>
  <summary>Раскрытый по умолчанию блок</summary>
  <p>Этот текст виден сразу, потому что атрибут open указан.</p>
</details>

<details>
  <summary>Скрытый по умолчанию блок</summary>
  <p>Этот текст будет показан только после клика по summary.</p>
</details>

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

  • open без значения — логический атрибут; его наличие означает «открыто»;
  • отсутствие open — блок закрыт при загрузке страницы;
  • браузер сам переключает open при взаимодействии пользователя.

Как работает атрибут open

При взаимодействии:

  • если <details> закрыт, то после клика по <summary> браузер добавляет атрибут open в DOM;
  • если открыт, атрибут удаляется.

Покажу вам, как это увидеть в браузере:

  1. Откройте страницу с <details> в браузере.
  2. Откройте DevTools (обычно F12).
  3. Найдите элемент <details> в DOM-дереве.
  4. Кликните по <summary> на странице.
  5. Обратите внимание, как атрибут open появляется и исчезает в разметке в реальном времени.

Это поведение важно, если вы планируете синхронизировать состояние с JavaScript или стилями (через селектор [open]).


Вложенное содержимое details

Какие элементы можно помещать внутрь

Внутрь <details> можно помещать практически любые блочные и строчные элементы:

  • параграфы <p>;
  • списки <ul>, <ol>, <dl>;
  • таблицы <table>;
  • формы <form>;
  • картинки <img>;
  • вложенные <details>.

Главное правило — первый дочерний <summary> будет считаться заголовком. Всё остальное станет раскрываемым содержимым.

Пример:

<details>
  <summary>Технические характеристики</summary>

  <!-- Любое содержимое, которое вы хотите скрывать -->
  <ul>
    <li>Процессор - 8 ядер</li>
    <li>Оперативная память - 16 ГБ</li>
    <li>Накопитель - 512 ГБ SSD</li>
  </ul>

  <p>Гарантия - 2 года при условии соблюдения условий эксплуатации.</p>
</details>

Здесь <summary> — только первый заголовок. Все остальные элементы не влияют на поведение раскрытия.

Обязательно ли использовать summary

Формально <summary> не является строго обязательным. <details> без <summary> будет считаться корректным HTML, но:

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

Поэтому на практике <summary> нужен почти всегда. Без него теряется ключевой смысл элемента — контролируемый пользователем «спойлер».


Семантика и доступность

Как details/summary воспринимаются скринридерами

Элементы <details> и <summary> имеют встроенную семантику:

  • <details> обычно объявляется как «раскрывающаяся секция»;
  • <summary> объявляется как кнопка/заголовок, который можно развернуть;
  • атрибут open передает состояние «открыто/закрыто» в виде aria-expanded или аналогичных внутренних флагов.

Это значит, что:

  • пользователи скринридеров понимают, что блок интерактивен;
  • состояние «развернуто/свернуто» озвучивается;
  • взаимодействие клавиатурой работает из коробки.

Вы тем самым экономите время: не нужно вручную добавлять role, aria-expanded, tabindex и т.п., как при кастомной реализации на div + JS.

Навигация с клавиатуры

Проверьте, как это работает:

  1. Перейдите на страницу с <details>.
  2. Используйте клавишу Tab, чтобы перейти к <summary>.
  3. Нажмите Enter или Space.

Результат:

  • блок раскрывается/сворачивается;
  • фокус остается на <summary>;
  • все это работает без дополнительного кода.

Если вы переопределяете стили фокуса, важно не убрать визуальное выделение элемента. Иначе пользователям клавиатуры будет сложно понять, где находится фокус.

Пример кастомного стиля фокуса:

details > summary:focus {
  outline: 2px solid #005fcc; /* Подчеркиваем границу при фокусе */
  outline-offset: 2px;
}

Правильный текст summary с точки зрения UX

Чтобы интерфейс был понятен:

  • делайте текст <summary> максимально конкретным:
    • вместо «Подробнее» — «Подробнее о доставке»;
    • вместо «Показать» — «Показать технические подробности»;
  • избегайте длинных предложений, это заголовок, а не параграф;
  • не прячьте критически важную информацию в свернутом состоянии, если от нее зависит решение пользователя.

Стилизация details и summary

Базовые CSS-селекторы для стилизации

Вы можете стилизовать эти элементы как обычные блочные элементы. Вот базовые селекторы:

details {
  border: 1px solid #ccc;      /* Рамка вокруг всего блока */
  border-radius: 4px;          /* Скругление углов */
  padding: 0.5rem 1rem;        /* Внутренние отступы */
  margin-bottom: 1rem;         /* Отступ снизу между несколькими блоками */
}

details[open] {
  background-color: #f8f9fa;   /* Фон при открытом состоянии */
}

details > summary {
  cursor: pointer;             /* Курсор в виде руки, чтобы обозначить кликабельность */
  font-weight: 600;            /* Подчеркиваем заголовок визуально */
  list-style: none;            /* Убираем стандартный маркер, если он оформлен как список */
}

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

  • details[open] позволяет изменить оформление при раскрытии (например, фон, тень, рамку).
  • details > summary — стили только для заголовка внутри блока.

Убираем стандартный маркер

В разных браузерах <summary> отображается с встроенным маркером (стрелочка, треугольник). Иногда он выглядит не так, как вам нужно. Давайте посмотрим, как его убрать:

details > summary {
  list-style: none;           /* Убираем маркер в некоторых браузерах */
}

/* Для WebKit-браузеров (Chrome, Safari, Edge) */
details > summary::-webkit-details-marker {
  display: none;              /* Прячем стандартный маркер */
}

После этого вы можете добавить свой маркер, например, через псевдоэлемент:

details > summary::before {
  content: "▶";               /* Стрелка вправо */
  display: inline-block;
  margin-right: 0.5rem;       /* Отступ между стрелкой и текстом */
  transition: transform 0.2s; /* Плавный поворот */
}

/* Поворачиваем стрелку, когда блок открыт */
details[open] > summary::before {
  transform: rotate(90deg);   /* Стрелка вниз */
}

Как видите, этот код делает управление состоянием более наглядным: стрелка поворачивается при открытии.

Стилизация содержимого внутри details

Обычно содержимое <details> вы стилизуете так же, как обычные блочные элементы. Но иногда удобно сделать небольшие отступы, чтобы отделить его от заголовка:

details > *:not(summary) {
  margin-top: 0.5rem;         /* Отступ сверху, чтобы текст не «лип» к summary */
}

Или, например, задать другой шрифт, цвет текста и т.д.


Практические примеры использования

Простой FAQ без JavaScript

Давайте посмотрим, как сделать блок часто задаваемых вопросов (FAQ), не прибегая к скриптам:

<section>
  <h2>Часто задаваемые вопросы</h2>

  <details>
    <summary>Как оформить заказ</summary>
    <p>Выберите товар, добавьте его в корзину и перейдите к оформлению заказа.</p>
  </details>

  <details>
    <summary>Какие способы оплаты вы принимаете</summary>
    <p>Мы принимаем банковские карты, электронные кошельки и оплату при доставке.</p>
  </details>

  <details>
    <summary>Можно ли изменить адрес доставки после оформления</summary>
    <p>Да, напишите в службу поддержки до передачи заказа курьерской службе.</p>
  </details>
</section>

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

  • каждый <details> — отдельный вопрос;
  • <summary> — текст вопроса;
  • <p> внутри — ответ.

Такой FAQ:

  • легко читается;
  • хорошо индексируется поисковыми системами;
  • не требует JS и при этом интерактивен.

Дополнительные параметры в форме

Элементы details/summary хорошо смотрятся, когда нужно скрыть неосновные настройки. Например, дополнительные параметры фильтра:

<form>
  <label>
    Поиск по названию
    <input type="text" name="q">
  </label>

  <details>
    <summary>Дополнительные фильтры</summary>

    <!-- Скрытые по умолчанию параметры -->
    <div>
      <label>
        Минимальная цена
        <input type="number" name="price_min">
      </label>
    </div>

    <div>
      <label>
        Максимальная цена
        <input type="number" name="price_max">
      </label>
    </div>

    <div>
      <label>
        Только в наличии
        <input type="checkbox" name="in_stock" value="1">
      </label>
    </div>

  </details>

  <button type="submit">Искать</button>
</form>

Покажу вам, зачем это удобно:

  • основное поле поиска всегда на виду;
  • дополнительные параметры не загромождают интерфейс;
  • при этом они доступны при необходимости одним кликом.

Технические подробности, «спойлеры», описания

Еще один частый сценарий — скрывать второстепенную техническую информацию, чтобы не перегружать текст.

<article>
  <h2>Как мы измеряем производительность</h2>
  <p>
    В главной части статьи мы используем усредненные значения времени
    ответа системы в реальных условиях эксплуатации.
  </p>

  <details>
    <summary>Показать методику измерений</summary>
    <p>
      Для измерений мы использовали синтетические нагрузки с профилем,
      близким к боевой эксплуатации системы.
    </p>
    <ul>
      <li>Нагрузка - 1000 запросов в секунду</li>
      <li>Продолжительность теста - 30 минут</li>
      <li>Система мониторинга - Prometheus</li>
    </ul>
  </details>
</article>

Так вы оставляете основную мысль на виду, а те, кто хочет углубиться, легко добираются до деталей.


Работа с details и summary в JavaScript

Чтение и изменение состояния open

Хотя <details> отлично работает и без JS, иногда вам нужно управлять его состоянием программно. Например, открыть все блоки по кнопке.

Вот базовый пример:

<button id="expand-all">Развернуть все</button>
<button id="collapse-all">Свернуть все</button>

<details class="faq-item">
  <summary>Вопрос 1</summary>
  <p>Ответ 1</p>
</details>

<details class="faq-item">
  <summary>Вопрос 2</summary>
  <p>Ответ 2</p>
</details>

<script>
// Находим кнопки управления
const expandAllBtn = document.getElementById('expand-all')
const collapseAllBtn = document.getElementById('collapse-all')

// Находим все элементы details
const detailsList = document.querySelectorAll('details.faq-item')

// Открываем все details при клике на кнопку "Развернуть все"
expandAllBtn.addEventListener('click', () => {
  detailsList.forEach(details => {
    details.open = true      // Свойство .open управляет состоянием
  })
})

// Закрываем все details при клике на кнопку "Свернуть все"
collapseAllBtn.addEventListener('click', () => {
  detailsList.forEach(details => {
    details.open = false
  })
})
</script>

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

  • у элемента <details> есть DOM-свойство open (boolean);
  • details.open = true; — раскрывает блок;
  • details.open = false; — сворачивает блок;
  • изменения отражаются в разметке: атрибут open добавляется/удаляется.

Обработка событий toggle

У <details> есть специальное событие toggle. Оно вызывается каждый раз, когда состояние блока меняется (раскрыт/свернут).

Давайте посмотрим, как это использовать:

<details id="loggable-details">
  <summary>Логи работы системы</summary>
  <p>Здесь будут показаны последние события.</p>
</details>

<script>
// Находим элемент details
const loggableDetails = document.getElementById('loggable-details')

// Подписываемся на событие toggle
loggableDetails.addEventListener('toggle', () => {
  // Проверяем текущее состояние
  if (loggableDetails.open) {
    console.log('Блок с логами открыт')
    // Здесь вы можете, например, подгрузить данные с сервера
  } else {
    console.log('Блок с логами закрыт')
  }
})
</script>

Как видите, этот код выполняет простую задачу: реагирует на раскрытие и скрытие содержимого. Это удобно, если вы хотите загружать данные только при первом открытии или отправлять аналитику.


Вложенные details: аккордеоны и сложные структуры

Вложенные раскрывающиеся блоки

Иногда вам нужно сделать многоуровневые раскрывающиеся структуры (например, в документации).

<details>
  <summary>Установка</summary>

  <p>Ниже вы найдете инструкции по установке под разные операционные системы.</p>

  <details>
    <summary>Windows</summary>
    <p>Скачайте установщик и следуйте шагам мастера установки.</p>
  </details>

  <details>
    <summary>Linux</summary>
    <p>Используйте пакетный менеджер вашей системы или сборку из исходников.</p>
  </details>
</details>

Особенности:

  • внутренние <details> работают независимо от внешнего;
  • если внешний блок свернуть, внутренние скрываются вместе с ним;
  • при повторном открытии внешний блок не меняет внутреннее состояние (если оно было открыто, таким и останется).

Аккордеон на базе details

Классический «аккордеон» — это список секций, где в каждый момент может быть открыт только один блок. Смотрите, как сделать это с помощью <details> и немного JS:

<section id="faq-accordion">
  <h2>FAQ</h2>

  <details>
    <summary>Вопрос 1</summary>
    <p>Ответ 1</p>
  </details>

  <details>
    <summary>Вопрос 2</summary>
    <p>Ответ 2</p>
  </details>

  <details>
    <summary>Вопрос 3</summary>
    <p>Ответ 3</p>
  </details>
</section>

<script>
// Находим контейнер с аккордеоном
const faqAccordion = document.getElementById('faq-accordion')

// Находим все details внутри
const items = faqAccordion.querySelectorAll('details')

// Для каждого details добавляем обработчик toggle
items.forEach(item => {
  item.addEventListener('toggle', () => {
    // Если текущий элемент открыт, закрываем остальные
    if (item.open) {
      items.forEach(otherItem => {
        if (otherItem !== item) {
          otherItem.open = false     // Закрываем все остальные блоки
        }
      })
    }
  })
})
</script>

Обратите внимание, как этот фрагмент кода решает задачу:

  • событие toggle срабатывает при каждом переключении;
  • если блок открылся (item.open === true), все остальные блоки закрываются;
  • при закрытии блока вручную другие не открываются — логика остается простой и предсказуемой.

Особенности поведения и подводные камни

Не вкладывайте интерактивные элементы внутрь summary без необходимости

Хотя технически в <summary> можно поместить ссылки, кнопки и другие интерактивные элементы, это часто создает конфликт поведения:

  • клики по вложенному элементу могут одновременно:
    • активировать сам элемент (например, ссылку),
    • открыть/закрыть блок <details>;
  • поведение может отличаться в разных браузерах.

Без крайней необходимости лучше ограничиться простым текстом и, возможно, иконками (<span>, <svg> и т.п.).

Если все-таки нужно добавить ссылку, стоит предотвращать всплытие клика:

<details>
  <summary>
    О продукте
    <a href="/more" id="more-link">Подробнее</a>
  </summary>
  <p>Краткое описание товара.</p>
</details>

<script>
// Находим ссылку внутри summary
const moreLink = document.getElementById('more-link')

moreLink.addEventListener('click', event => {
  event.stopPropagation()   // Останавливаем всплытие события
  // Теперь клик по ссылке не переключит details
})
</script>

Этот код гарантирует, что клик по ссылке не будет сворачивать или разворачивать родительский блок.

Поддержка в браузерах

На момент последних лет <details> и <summary> поддерживаются современными версиями:

  • Chrome;
  • Firefox;
  • Safari;
  • Edge;
  • мобильные браузеры на популярных платформах.

Старые Internet Explorer эти элементы не поддерживают. Если вам важно их поддерживать, необходим полифилл на JS. Сейчас такие случаи редки, но в корпоративных системах с очень старыми браузерами это все еще встречается.

SEO и индексация

Поисковые системы умеют индексировать содержимое <details>. Но важно учитывать:

  • информация внутри <details> может считаться менее приоритетной;
  • лучше не прятать в свернутом блоке ключевой контент страницы:
    • основные заголовки;
    • главный текст;
    • критически важные описания товара и услуг.

Используйте <details> для дополнительной, поясняющей и технической информации.


Рекомендации по использованию в реальных проектах

Когда использовать details/summary

Подходящие сценарии:

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

В общем, это хороший способ «сжать» интерфейс, когда контента много, но не все нужно показывать сразу.

Когда лучше отказаться от details/summary

Не стоит использовать <details>:

  • для критически важного контента, который должен быть виден сразу;
  • если вам нужна сложная анимация высоты и индивидуальные сценарии;
  • если нужен сложный аккордеон с возможностью сохранять состояние между страницами без участия JS (в этом случае вы все равно придете к JavaScript и, возможно, к другой структуре).

Иногда проще реализовать собственный компонент на <button> + <div> и полностью контролировать его поведение, особенно если у вас уже есть библиотека UI-компонентов.

Тестирование доступности

Перед тем как запускать блоки на <details> в продакшн, проверьте:

  • как они работают только с клавиатурой:
    • Tab, Shift+Tab, Enter, Space;
  • как они читаются скринридером (NVDA, VoiceOver и т.д.);
  • не исчезает ли фокус при кастомной стилизации;
  • не прячете ли вы важную информацию в закрытом состоянии.

Если вы вносите изменения через JavaScript (например, делаете аккордеон), убедитесь, что:

  • не ломаете стандартное поведение;
  • не добавляете избыточные ARIA-атрибуты, которые конфликтуют со встроенной семантикой.

Заключение

Элементы details и summary — это простой способ добавить интерактивные раскрывающиеся блоки на страницу без JavaScript. Вы получаете:

  • семантическую разметку, понятную и браузеру, и вспомогательным технологиям;
  • встроенное управление состоянием через атрибут open;
  • поддержку клавиатуры и базовой доступности «из коробки»;
  • гибкие возможности стилизации через CSS и управления через JS при необходимости.

Если вы хотите сделать FAQ, скрыть дополнительные параметры формы, спрятать технические детали или реализовать простой аккордеон, имеет смысл сначала попробовать именно details/summary. В большинстве типичных сценариев этого достаточно, и вам не понадобится сложный самописный компонент.


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

Как сделать плавную анимацию раскрытия и сворачивания details

По умолчанию <details> переключается мгновенно. Для плавной анимации можно использовать max-height и JS:

details[open] > div.content {
  max-height: 500px;              /* Достаточно большое значение */
  transition: max-height 0.3s;
}

details > div.content {
  max-height: 0;
  overflow: hidden;               /* Скрываем содержимое при малой высоте */
}
<details>
  <summary>Заголовок</summary>
  <div class="content">
    <p>Анимируемое содержимое.</p>
  </div>
</details>

Атрибут open переключает состояние, а CSS-анимация срабатывает на изменении max-height. Важно подобрать значение max-height под максимальный ожидаемый размер блока.

Почему псевдоэлемент ::marker не работает с summary

Псевдоэлемент ::marker корректно работает с элементами списка (li). <summary> не является элементом списка, поэтому маркер списка может появляться, но поведение непредсказуемо и зависит от браузера. Для кастомного маркера надежнее использовать ::before:

details > summary::before {
  content: "▶";
}

Так вы получаете единое поведение во всех современных браузерах.

Как сделать так, чтобы один из блоков details был всегда открыт

Уберите возможность закрывать последний открытый блок. Например, в аккордеоне:

const items = document.querySelectorAll('#faq details')

items.forEach(item => {
  item.addEventListener('toggle', () => {
    const opened = Array.from(items).filter(i => i.open)

    if (opened.length === 0) {
      // Если все закрыты, снова открываем текущий
      item.open = true
    }
  })
})

Теперь пользователь не сможет оставить все блоки закрытыми.

Можно ли управлять details через атрибуты data-*

Можно: вы можете добавлять к <details> собственные атрибуты data-* и использовать их в JS. Например, чтобы открыть только те блоки, где data-group="advanced":

document
  .querySelectorAll('details[data-group="advanced"]')
  .forEach(d => d.open = true)

Это удобно для группировки логики, не перегружая классами.

Как синхронизировать состояние details с URL (хеш)

Используйте хеш в адресной строке и id у <details>:

<details id="shipping">
  <summary>Доставка</summary>
  <p>Условия доставки...</p>
</details>
// Открываем блок, если его id совпадает с хешем
const idFromHash = location.hash.slice(1)
const target = document.getElementById(idFromHash)
if (target && target.tagName === 'DETAILS') {
  target.open = true
}

// Обновляем хеш при открытии
document.querySelectorAll('details').forEach(d => {
  d.addEventListener('toggle', () => {
    if (d.open) {
      history.replaceState(null, '', '#' + d.id)
    }
  })
})

Так вы позволяете делиться ссылками на уже раскрытый блок.

Контекстное меню в HTML - menuСтрелочка вправо

Постройте личный план изучения 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 ₽
Подробнее

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