иконка discount

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

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

Атрибут download в HTML

Автор

Олег Марков

Введение

Атрибут download в HTML позволяет подсказать браузеру, что по ссылке нужно не просто открыть ресурс, а скачать его как файл. Вы управляете поведением ссылки: вместо перехода на страницу или отображения картинки в браузере, файл попадает в папку загрузок пользователя.

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

<!-- При клике браузер скачает файл example.pdf -->
<a href="files/example.pdf" download>Скачать инструкцию</a>

Как видите, здесь мы просто добавили атрибут download к обычной ссылке. Но за этой простотой скрывается ряд особенностей: ограничения безопасности, поддержка браузерами, влияние кросс-доменных запросов, задание имени файла и работа с Blob-объектами.

В статье вы разберетесь:

  • что именно делает атрибут download и в чем его отличие от обычной ссылки;
  • как задавать собственное имя для скачиваемого файла;
  • какие у атрибута есть ограничения (особенно при скачивании с другого домена);
  • как сочетать download с JavaScript и Blob;
  • какие практики стоит использовать, чтобы ссылки на скачивание работали предсказуемо.

Основы атрибута download

Что такое атрибут download

Атрибут download — это булевый атрибут тега <a>, который говорит браузеру: "эту ссылку нужно обрабатывать как скачивание файла". Проще говоря, при клике должен начаться процесс загрузки файла, а не открытие ресурса в текущей вкладке.

Базовый пример:

<a href="reports/2025-report.pdf" download>Скачать отчет за 2025 год</a>

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

<!-- 
href - путь к файлу, который нужно скачать 
download - атрибут, говорящий браузеру инициировать загрузку 
Текст ссылки - то, что пользователь увидит на странице 
-->
<a href="reports/2025-report.pdf" download>Скачать отчет за 2025 год</a>

Если вы не задаете значение атрибуту download (то есть просто пишете download без значения), браузер обычно использует имя файла из URL или из заголовка Content-Disposition (если сервер его задает).

Поддерживаемые теги

Атрибут download официально поддерживается у тега <a>. В спецификациях также встречается упоминание о <area>, но на практике это используется редко. Основной рабочий вариант — именно <a>.

Неправильно:

<!-- Атрибут download у button не сработает -->
<button download>Скачать</button>

Правильно:

<a href="file.zip" download>Скачать</a>

Значение атрибута download: без значения и с именем файла

Атрибут download можно использовать двумя способами:

  1. Без значения — просто как флаг.
  2. С текстовым значением — как имя сохраняемого файла.

Использование без значения

Если вы укажете download без значения, браузер:

  • скачает ресурс по ссылке href;
  • попытается использовать имя файла из URL;
  • либо возьмет имя из заголовка Content-Disposition, если сервер его задаст.

Пример:

<a href="images/photo-2025.jpg" download>Скачать фото</a>

Здесь браузер, как правило, сохранит файл под именем photo-2025.jpg.

Задание собственного имени файла

Если вы хотите контролировать имя загружаемого файла, можете указать значение атрибута download:

<a href="images/photo-2025.jpg" download="Отчетный-снимок.jpg">
  Скачать фото как Отчетный-снимок.jpg
</a>

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

<!-- 
href - реальный путь к файлу на сервере 
download="Отчетный-снимок.jpg" - имя файла, которое браузер предложит при сохранении 
Текст ссылки - пояснение для пользователя 
-->
<a href="images/photo-2025.jpg" download="Отчетный-снимок.jpg">
  Скачать фото как Отчетный-снимок.jpg
</a>

Важно понимать, что:

  • значение download — это рекомендация для браузера;
  • некоторые браузеры или настройки безопасности могут ее игнорировать;
  • сервер может переопределить имя файла заголовком Content-Disposition (особенно при кросс-доменных запросах или строгих настройках).

Ограничения на название файла

В имени файла не стоит использовать:

  • символы, которые недопустимы в файловой системе пользователя (например, в Windows: ? * : " < > |);
  • слишком длинные имена (некоторые системы могут обрезать их).

Безопаснее использовать:

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

Пример более безопасного имени:

<a href="docs/report.pdf" download="otchet-2025.pdf">Скачать отчет</a>

Поведение ссылок с download: навигация и вкладки

Взаимодействие с target

Атрибут target управляет тем, где откроется ссылка. download влияет на поведение скачивания, но target тоже играет роль.

Посмотрите несколько вариантов:

<!-- Скачивание в текущем окне -->
<a href="files/data.csv" download>Скачать CSV</a>

<!-- Скачивание с открытием новой вкладки (в некоторых браузерах сначала откроется вкладка, но скачивание все равно начнется) -->
<a href="files/data.csv" download target="_blank">Скачать CSV в новой вкладке</a>

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

<!-- 
target="_blank" - открывает ресурс в новой вкладке 
download - инициирует загрузку файла 
Результат - в большинстве браузеров файл скачается, а вкладка может быть пустой или кратко отобразить URL 
-->
<a href="files/data.csv" download target="_blank">Скачать CSV в новой вкладке</a>

Поведение с target="_blank" зависит от браузера. Иногда вы увидите новую вкладку, которая тут же закроется или останется пустой. Пользователь видит только скачивание файла.

Отличие от обычной ссылки без download

Для сравнения:

<!-- Без download - браузер попробует отобразить PDF в окне -->
<a href="docs/instruction.pdf">Открыть инструкцию</a>

<!-- С download - браузер начнет скачивание PDF -->
<a href="docs/instruction.pdf" download>Скачать инструкцию</a>

Вы можете комбинировать подход:

  • без download — "Открыть онлайн";
  • с download — "Скачать файл".

Пример:

<a href="docs/instruction.pdf" target="_blank">Открыть инструкцию в браузере</a>
<a href="docs/instruction.pdf" download>Скачать инструкцию на компьютер</a>

Ограничения безопасности и кросс-доменные запросы

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

Поведение при скачивании с того же домена

Если ресурс расположен на том же домене (origin), что и страница, атрибут download обычно работает без ограничений:

<!-- origin: https://example.com -->
<a href="/files/report.pdf" download="report-2025.pdf">
  Скачать отчет 2025
</a>

В этом случае:

  • браузер использует имя report-2025.pdf;
  • файл скачивается без лишних предупреждений (если сервер не требует авторизации).

Поведение при скачивании с другого домена

Теперь давайте посмотрим, что происходит, если файл лежит на другом домене:

<!-- Страница на https://mysite.com -->
<a href="https://cdn.othersite.com/files/report.pdf" download="my-report.pdf">
  Скачать отчет
</a>

Многие браузеры в таком случае:

  • игнорируют имя в download (my-report.pdf);
  • используют имя, указанное сервером или взятое из URL;
  • иногда могут вообще игнорировать атрибут download, если политика безопасности ресурса это запрещает.

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

Влияние заголовка Content-Disposition

Сервер может явно указать поведение файла с помощью заголовка Content-Disposition. Например:

  • Content-Disposition: attachment; filename="report.pdf" — сервер говорит: "это вложение, скачай его";
  • Content-Disposition: inline — "попробуй отобразить в браузере".

Если сервер задает Content-Disposition, он может переопределить или усилить поведение, которое вы ожидаете от download.

Общая логика:

  • если сервер говорит attachment, скачивание почти гарантировано, даже без download;
  • если сервер inline, но вы установили download, браузер все равно обычно скачает файл;
  • имя файла из Content-Disposition чаще всего приоритетнее, чем имя в download при кросс-доменных запросах.

Ограничения по протоколам

Атрибут download работает не для всех схем URL.

Как правило, он:

  • работает для http и https;
  • может игнорироваться для data: URL в некоторых браузерах;
  • может не поддерживаться для file:, blob: и других схем в зависимости от реализации.

Смотрите пример с data URL:

<a href="data:text/plain,Hello%20world" download="hello.txt">
  Скачать hello.txt
</a>

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

<!-- 
href - data URL с текстом Hello world 
download="hello.txt" - желаемое имя файла 
Поддержка - не во всех браузерах поведение предсказуемое 
-->
<a href="data:text/plain,Hello%20world" download="hello.txt">
  Скачать hello.txt
</a>

Здесь часть браузеров корректно скачает файл, часть может попытаться открыть его в вкладке.


Атрибут download и JavaScript

Очень часто ссылки с download комбинируют с JavaScript: генерируют содержимое файла на лету, используют Blob-объекты, создают временные ссылки.

Программное создание ссылки с download

Покажу вам, как это реализовано на практике, когда файл генерируется в браузере:

<button id="save">Скачать как файл</button>

<script>
// Находим кнопку
const button = document.getElementById('save');

button.addEventListener('click', () => {
  // Здесь мы создаем текстовое содержимое файла
  const text = 'Пример данных для сохранения\nСтрока номер два';

  // Создаем Blob-объект на основе строки
  const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });

  // Получаем временный URL для Blob-объекта
  const url = URL.createObjectURL(blob);

  // Создаем временную ссылку
  const a = document.createElement('a');
  a.href = url;                 // Указываем ссылку на Blob
  a.download = 'example.txt';   // Имя сохраняемого файла
  a.style.display = 'none';     // Скрываем ссылку от пользователя

  // Добавляем ссылку в документ
  document.body.appendChild(a);

  // Программно кликаем по ссылке, чтобы инициировать скачивание
  a.click();

  // Удаляем ссылку из DOM
  document.body.removeChild(a);

  // Освобождаем URL, чтобы не держать лишнюю память
  URL.revokeObjectURL(url);
});
</script>

Как видите, download здесь используется уже из JavaScript-кода. Это стандартный прием для скачивания данных, созданных на стороне клиента.

Пояснения по шагам:

  1. Создаем Blob из строки.
  2. Получаем временный URL через URL.createObjectURL.
  3. Создаем элемент <a>, задаем href на Blob и атрибут download с именем файла.
  4. Добавляем ссылку в DOM, вызываем click и сразу удаляем.
  5. Освобождаем URL через URL.revokeObjectURL.

Управление именем файла через JS

Вы можете динамически задавать имя файла в зависимости от контекста:

function downloadJson(data, filenamePrefix) {
  // Преобразуем объект в JSON
  const json = JSON.stringify(data, null, 2);

  // Формируем имя файла с префиксом и датой
  const date = new Date().toISOString().slice(0, 10); // Например, 2025-11-25
  const filename = `${filenamePrefix}-${date}.json`;

  // Создаем Blob
  const blob = new Blob([json], { type: 'application/json' });
  const url = URL.createObjectURL(blob);

  // Создаем ссылку
  const a = document.createElement('a');
  a.href = url;
  a.download = filename; // Динамическое имя файла
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

// Пример вызова функции
downloadJson({ user: 'Ivan', age: 30 }, 'user-data');

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

// filenamePrefix - префикс в имени файла, например user-data
// new Date().toISOString().slice(0, 10) - формируем дату в формате YYYY-MM-DD
// filename - итоговое имя файла, например user-data-2025-11-25.json
// a.download = filename - устанавливаем имя сохраняемого файла

Особенности работы с разными типами файлов

Файлы, которые браузер обычно открывает

Многие типы файлов браузеры умеют показывать прямо во вкладке:

  • картинки (jpg, png, gif, webp);
  • PDF;
  • текстовые файлы (txt, json);
  • иногда аудио и видео.

Если вы не используете download, клик по ссылке на такой файл, как правило, откроет его во вкладке.

С download картина меняется:

<!-- Открытие картинки во вкладке -->
<a href="images/photo.jpg">Показать фото</a>

<!-- Принудительное скачивание картинки -->
<a href="images/photo.jpg" download="photo-local.jpg">Скачать фото</a>

Файлы, которые по умолчанию скачиваются

Есть типы файлов, которые почти всегда скачиваются:

  • архивы (zip, rar, 7z);
  • исполняемые файлы (exe, msi);
  • многие бинарные форматы.

Для них download часто не добавляет нового поведения, но он может:

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

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

Загрузка нескольких версий одного ресурса

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

<h3>Скачать руководство пользователя</h3>

<ul>
  <li>
    <!-- PDF-версия -->
    <a href="docs/manual.pdf" download="manual-ru.pdf">
      PDF версия
    </a>
  </li>
  <li>
    <!-- DOCX-версия -->
    <a href="docs/manual.docx" download="manual-ru.docx">
      DOCX версия
    </a>
  </li>
  <li>
    <!-- Архив со всеми файлами -->
    <a href="docs/manual-full.zip" download="manual-ru-full.zip">
      Полный архив
    </a>
  </li>
</ul>

Здесь вы явно задаете имена файлов для каждого формата, чтобы у пользователя не копились файлы с непонятными названиями вроде manual(1).pdf.

Кнопка "Сохранить как CSV" для таблицы

Смотрите, я покажу вам, как это реализовать, когда вам нужно сохранить данные таблицы в CSV прямо из браузера.

<table id="report">
  <tr><th>Месяц</th><th>Доход</th></tr>
  <tr><td>Январь</td><td>1000</td></tr>
  <tr><td>Февраль</td><td>1500</td></tr>
</table>

<button id="download-csv">Скачать CSV</button>

<script>
// Функция преобразования таблицы в CSV
function tableToCsv(table) {
  // Получаем строки таблицы
  const rows = Array.from(table.querySelectorAll('tr'));

  // Преобразуем каждую строку в CSV-формат
  const csvLines = rows.map(row => {
    const cells = Array.from(row.querySelectorAll('th, td'));
    return cells
      .map(cell => {
        const text = cell.textContent.trim();
        // Экранируем запятые и кавычки
        const escaped = text.replace(/"/g, '""');
        return `"${escaped}"`;
      })
      .join(',');
  });

  // Соединяем строки через перевод строки
  return csvLines.join('\n');
}

document.getElementById('download-csv').addEventListener('click', () => {
  const table = document.getElementById('report');

  // Получаем CSV-строку
  const csv = tableToCsv(table);

  // Создаем Blob с типом text/csv
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
  const url = URL.createObjectURL(blob);

  // Создаем ссылку с атрибутом download
  const a = document.createElement('a');
  a.href = url;
  a.download = 'report.csv'; // Имя файла

  // Добавляем, кликаем, удаляем
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);

  // Освобождаем URL
  URL.revokeObjectURL(url);
});
</script>

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

// tableToCsv - превращает DOM-таблицу в CSV-текст
// new Blob([csv], { type: 'text/csv;charset=utf-8' }) - создаем Blob с типом CSV
// a.download = 'report.csv' - задаем имя сохраняемого файла
// a.click() - инициируем скачивание без участия пользователя в DOM

Адаптация под разные браузеры

Поддержка атрибута download

Современные версии основных браузеров (Chrome, Firefox, Edge, Safari, Opera) поддерживают атрибут download, но есть нюансы:

  • старые версии Internet Explorer его не поддерживают;
  • в старых мобильных браузерах поведение может отличаться.

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

  • использовать серверный заголовок Content-Disposition: attachment;
  • дублировать функциональность через JavaScript (Blob, window.location и прочее) там, где это уместно.

Падение обратно на обычное поведение

Хорошая новость: если браузер не понимает download, ссылка просто ведет себя как обычная:

<a href="docs/manual.pdf" download>Скачать руководство</a>

В старом браузере пользователь, скорее всего, увидит PDF во вкладке и сам нажмет "Сохранить как" через интерфейс браузера. То есть деградация функциональности происходит мягко.


Сочетание с серверной логикой

Когда лучше полагаться на сервер

Атрибут download удобен, но он работает только на стороне клиента. В некоторых случаях вам нужно управлять скачиванием с сервера:

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

В таких сценариях обычно:

  1. На клиенте вы по-прежнему используете download, чтобы подсказать браузеру поведение.
  2. На сервере вы настраиваете заголовки и логику выдачи.

Пример HTTP-ответа от сервера (упрощенно, псевдокод):

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="manual-ru.pdf"

<тело PDF-файла>

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

Content-Type - тип содержимого (здесь PDF)
Content-Disposition - attachment - указание браузеру скачать файл как вложение
filename="manual-ru.pdf" - рекомендуемое имя файла

Даже без download браузер скачает такой файл, так как сервер явно требует поведение attachment.

Совмещение Content-Disposition и download

Как правило:

  • для внутренних файлов (на том же домене) вы можете ограничиться атрибутом download;
  • для более строгого контроля лучше дублировать поведение заголовком Content-Disposition.

Пример HTML + серверной настройки:

<a href="/download/manual/ru" download="manual-ru.pdf">
  Скачать руководство на русском
</a>

На сервере по маршруту /download/manual/ru:

  • проверяется авторизация;
  • выбирается нужный файл;
  • отправляется ответ с Content-Disposition: attachment; filename="manual-ru.pdf".

Если какой-то браузер проигнорирует download, заголовок все равно заставит его скачать файл.


Ограничения и подводные камни

Нельзя обойти диалоги безопасности браузера

Атрибут download не может:

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

Пользователь в любом случае контролирует, куда и что сохранять.

Не всегда удается переименовать файл

Даже если вы указали download="myname.ext":

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

Поэтому download — это не гарантия имени файла, а лишь рекомендация.

Не стоит использовать для конфиденциальных файлов без сервера

Если вы генерируете конфиденциальные данные на клиенте и даете их скачивать через download, помните:

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

Для реальной защиты конфиденциальных документов обычно используют:

  • авторизацию;
  • шифрование;
  • ограничение времени действия ссылки.

Атрибут download тут не отвечает за безопасность.


Заключение

Атрибут download в HTML — это простой, но полезный инструмент, который позволяет управлять поведением ссылок при скачивании файлов. Вы можете:

  • явно сказать браузеру "скачать, а не открыть";
  • задать читаемое имя для загружаемого файла;
  • комбинировать атрибут с JavaScript и Blob, чтобы сохранять данные, сгенерированные на стороне клиента.

При этом важно учитывать:

  • ограничения безопасности при кросс-доменных запросах;
  • взаимодействие с заголовком Content-Disposition;
  • возможные различия в поведении браузеров.

Если вы строите систему скачивания файлов, старайтесь сочетать download с корректной серверной конфигурацией и, при необходимости, с JavaScript-логикой. Тогда пользователи получат предсказуемое поведение, а вы — больше контроля над тем, как именно загружаются ваши ресурсы.


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

Как реализовать скачивание файла по POST-запросу, если download работает только с ссылками?

Атрибут download действительно применяется к <a> и работает по GET-запросу. Чтобы инициировать скачивание по POST, используйте один из подходов:

  1. Отправляете POST из формы на сервер, сервер в ответ возвращает файл с заголовком Content-Disposition: attachment. Тогда браузер начнет скачивание сам.
  2. Либо:
    • отправляете POST через fetch;
    • получаете Blob;
    • создаете временный URL и ссылку с download (как в примерах выше);
    • программно кликаете по ссылке.

Мини-инструкция (fetch + Blob):

fetch('/export', {
  method: 'POST',
  body: JSON.stringify({ filter: 'today' }),
  headers: { 'Content-Type': 'application/json' }
})
  .then(res => res.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'export.csv';
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  });

Почему ссылка с download открывает PDF во вкладке, а не скачивает?

Основные причины:

  • сервер явно задает Content-Disposition: inline, и браузер следует ему;
  • браузер или расширение принудительно открывает PDF во встроенном просмотрщике;
  • вы используете кросс-доменный ресурс, и браузер игнорирует download.

Что можно сделать:

  1. На сервере установить Content-Disposition: attachment.
  2. Проверить настройки браузера и отключить автопросмотр PDF (если это допустимо).
  3. Использовать собственный сервер-проксирование, чтобы выдавать PDF с вашего домена с нужными заголовками.

Можно ли принудительно задать расширение файла через download, если у URL его нет?

Да, вы можете задать любое имя, включая расширение, в значении download:

<a href="/api/report" download="report-2025.xlsx">Скачать отчет</a>

Но важно:

  • расширение не меняет фактический формат данных;
  • если сервер вернет не Excel-файл, а, например, PDF, пользователь получит файл с расширением xlsx, который не откроется корректно.

Лучше обеспечивать согласованность: сервер выдает правильный тип, а вы задаете соответствующее расширение.

Как сделать, чтобы файл скачивался только после авторизации, но download при этом работал?

Используйте защиту на стороне сервера:

  1. Ссылка ведет на защищенный URL, например /secure/files/report.pdf.
  2. На сервере маршрут /secure/files/report.pdf проверяет авторизацию пользователя:
    • если пользователь не авторизован — редирект на логин или ошибка 401/403;
    • если авторизован — выдается файл с Content-Disposition: attachment.
  3. На клиенте вы можете добавить download, чтобы подсказать браузеру поведение:
<a href="/secure/files/report.pdf" download="report-2025.pdf">
  Скачать отчет 2025
</a>

Таким образом, доступ контролируется сервером, а download улучшает UX.

Почему download не работает для blob: URL в некоторых старых браузерах?

Поддержка download для blob: URL появилась не сразу и не во всех браузерах одновременно. В старых версиях:

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

Обходной путь:

  • использовать библиотеку, которая учитывает особенности конкретных браузеров (например, старые версии FileSaver.js);
  • проверять поддержку: если атрибут download есть у HTMLAnchorElement.prototype, использовать стандартный путь, если нет — применять альтернативы (например, navigator.msSaveOrOpenBlob в старом Edge/IE).
Стрелочка влевоАтрибут href в HTML - подробное руководство для начинающих и практикующих разработчиковТег ссылки HTML a - полное руководство для начинающих и практикующих разработчиковСтрелочка вправо

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

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