Code Ready | Frontend
21.6K subscribers
1.22K photos
519 videos
17 files
926 links
Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Автор: @energy_c

РКН: https://clck.ru/3NJCKs

Реклама на бирже: https://telega.in/c/code_ready
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
🤔 Awesome CSS — большая подборка ресурсов по CSS!

Здесь собраны качественные статьи, инструменты, библиотеки и другие полезные ресурсы для работы со стилями. Особенно полезен тем, кто хочет лучше разобраться в современных возможностях CSS, быстрее находить решения для вёрстки и держать под рукой материалы. Хорошая база как для обучения, так и для повседневной разработки.

Оставляю ссылочку: GitHub 📱


📣 Code Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍8🤝5
Как убрать лишние классы для пустых блоков?

Часто в компонентах есть контейнеры для описания, ошибки, подсказки или дополнительного контента.

Если данных нет — элемент остаётся пустым, но продолжает занимать место.

Обычно это решают через JS или условный рендеринг.
.error {
display: none;
}


А потом отдельно добавляют класс при появлении контента.

Но CSS умеет определять пустые элементы самостоятельно.
.error:empty {
display: none;
}


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

Можно делать и обратную логику.
.card:not(:empty) {
padding: 16px;
}


Отступы появятся только тогда, когда внутри действительно есть контент.

Особенно удобно для:
error,
hint,
description,
badge


Где содержимое может появляться динамически.

🔥 :empty позволяет убрать лишние классы и часть условной логики прямо средствами CSS.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👍7🤝4
📂 Напоминалка для работы с Query Parameters!

Например, get() позволяет получить значение параметра, set() обновить существующий параметр, append() добавить новый, а delete() удалить ключ вместе со всеми значениями.

На картинке — основные методы URLSearchParams, примеры работы с параметрами запроса и базовые сценарии использования в современной web-разработке.

Сохрани, чтобы не потерять!

📣 Code Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍64
👩‍💻 Добавляем подсказки в поля формы с помощью атрибута placeholder!

Атрибут, который подсказывает пользователю, что именно нужно ввести в поле ввода (обычно это пример слова или фразы). А ещё значение атрибута исчезает, как только пользователь начинает вводить текст.

Чаще всего используется с:
• <input> — для текстовых полей, поиска, email, телефона и других типов ввода;
• <textarea> — для подсказок в многострочных полях.


Часто из-за дизайнерских решений placeholder используется для замены более семантического элемента метки. Однако это не означает, что текст-заполнитель может заменить <label>, поскольку это создаёт неудобства для пользователей с особыми потребностями.

📣 Code Ready | #атрибут
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥137👍7
Проверяем интернет-скорость!

Хочешь узнать, насколько быстрый у тебя интернет? Для этого есть готовый пакет speedtest-net, который позволяет получить скорость загрузки, отдачи и пинга.

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

Шаг 1 — импортируем:
const speedTest = require('speedtest-net');


Шаг 2 — запускаем тест:
(async () => {
const res = await speedTest({ acceptLicense: true });
})();


Шаг 3 — форматируем и выводим результаты:
// Загрузка
console.log(`Download: ${(res.download.bandwidth / 125000).toFixed(2)} Mbps`);

// Выгрузка
console.log(`Upload: ${(res.upload.bandwidth / 125000).toFixed(2)} Mbps`);

// Пинг
console.log(`Ping: ${res.ping.latency} ms`);


🔥 Теперь у тебя свой speedtest прямо в коде. Можно запускать вручную или добавить в cron для регулярного замера.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍127🔥6
Крутая статья попалась на Хабре: «HTML Sanitizer API: конец эпохи DOMPurify и XSS-страданий»!

В этой статье:
• Разбирается, почему привычные способы защиты от XSS становятся сложнее и какие проблемы есть у старых подходов вроде DOMPurify;
• Показывается новый HTML Sanitizer API, который позволяет безопаснее работать с пользовательским HTML прямо на уровне браузера;
• Объясняется, как современные веб-разработчики могут упростить код и повысить безопасность приложений.


🔊 Продолжай читать на Habr!


📣 Code Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍5🤝3
Node.replaceWith() — замена DOM-элемента без пересборки HTML!

Когда нужно заменить элемент на странице, часто используют innerHTML, outerHTML или удаляют старый узел, а потом создают новый. В небольших интерфейсах разницы почти не видно, но внутри браузера это разные операции.

Если вы работаете с динамическими интерфейсами, где есть состояние элементов и обработчики событий, такие детали становятся важными. Например:
const oldElement = document.querySelector('.message');

oldElement.outerHTML = `
<div class="success">
Saved
</div>
`;


Выглядит просто: старый элемент заменили новым. Но браузер получает строку HTML, разбирает её и создаёт новый DOM-узел. Старый элемент исчезает из DOM, а на его месте появляется другой объект.

Если где-то была сохранена ссылка на старый элемент или на нём были обработчики событий, они не перейдут автоматически. Для браузера это уже другой DOM-объект.

Для замены конкретного узла есть более подходящий метод:
const oldElement = document.querySelector('.message');

const newElement = document.createElement('div');

newElement.textContent = 'Saved';

oldElement.replaceWith(newElement);


replaceWith() работает непосредственно с DOM-узлами. Браузеру не нужно заново парсить HTML-строку — он получает готовый элемент и заменяет только нужное место в DOM-дереве.

Это удобно, когда вокруг элемента есть другая разметка, которую не нужно трогать. Например:
const button = document.querySelector('.button');

const loader = document.createElement('span');

loader.textContent = 'Loading...';

button.replaceWith(loader);


Меняется только button. Родительский элемент, соседние узлы и остальная структура страницы остаются без изменений.

Разница хорошо заметна, если сравнить с innerHTML. Например:
const container = document.querySelector('.container');

container.innerHTML = `
<div class="card">
New content
</div>
`;


Здесь браузер заново создаёт содержимое контейнера из строки. Даже если часть элементов выглядит так же, это могут быть уже новые DOM-объекты. Например:
const input = document.querySelector('.search');

input.value = 'frontend';

container.innerHTML += `
<div>
New block
</div>
`;


Если input находится внутри container, старый элемент будет пересоздан вместе с содержимым. Можно потерять значение поля, обработчики событий и ссылки на старые DOM-объекты.

Именно поэтому innerHTML += часто становится причиной багов. replaceWith() такого поведения не создаёт, потому что меняет только указанный узел. Например:
const title = document.querySelector('.title');

const newTitle = document.createElement('h2');

newTitle.textContent = 'New title';

title.replaceWith(newTitle);


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

Но важно учитывать: новый элемент не наследует обработчики старого. Например:
const button = document.querySelector('.button');

button.addEventListener('click', handleClick);

const newButton = document.createElement('button');

button.replaceWith(newButton);


После замены новый button будет другим объектом, поэтому старый обработчик к нему не относится.

Если нужно сохранить поведение, обработчик нужно добавить заново:
newButton.addEventListener('click', handleClick);


Также replaceWith() может принимать несколько узлов:
element.replaceWith(title, text, button);


Браузер удалит старый элемент и вставит переданные узлы на его место. Причём это могут быть не только элементы, но и текстовые узлы:
element.replaceWith('Hello');


🔥 Подведем итог: replaceWith() удобен для точечной замены DOM-элементов без повторного парсинга HTML и пересоздания всей окружающей структуры. В отличие от innerHTML, он работает напрямую с узлами и даёт больше контроля над изменениями DOM.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍10🔥7
👩‍💻 Отображаем математические формулы с помощью тега <math>!

Тег <math> используется для встраивания математических выражений на веб-страницу с помощью языка MathML. Он позволяет отображать дроби, степени, корни, индексы, матрицы и другие математические конструкции без изображений.

Кроме глобальных атрибутов, <math> поддерживает:
• display="inline" — формула отображается внутри строки (по умолчанию).
• display="block" — формула выводится отдельным блочным элементом.
• alttext — альтернативное текстовое описание формулы.


Все теги MathML чувствительны к регистру: используйте строго строчные (<msup>, а не <MSUP>). Для лучшего внешнего вида можно подключать стили к формуле, но аккуратно, некоторые свойства не работают

📣 Code Ready | #атрибут
Please open Telegram to view this post
VIEW IN TELEGRAM
👍129🔥6
CSS-вычисления теперь работают с auto и max-content!

Многие знают calc(), но он не умеет вычислять auto, max-content, fit-content и min-content.

Например, так написать нельзя:
.panel {
width: calc(max-content + 2rem);
}


Такое значение считается невалидным.

Для этого появился calc-size().
.panel {
width: calc-size(max-content, size + 2rem);
}


Теперь браузер сначала вычисляет max-content, а затем прибавляет к нему 2rem.

Это работает и с другими размерами, зависящими от содержимого.
.panel {
height: calc-size(auto, size + 1rem);
}


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

🔥 calc-size() позволяет выполнять вычисления с auto, max-content и fit-content — то, чего обычный calc() делать не умеет.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
19🔥6👍5
This media is not supported in your browser
VIEW IN TELEGRAM
🤔 HTML5Book — большой учебник по HTML, CSS и JavaScript!

На сайте собрана большая база материалов по веб-разработке: подробные уроки по HTML5, CSS3, JavaScript и jQuery, а также удобные справочники по HTML- и CSS-свойствам. Здесь можно найти разбор тегов, форм, анимаций, Flexbox, Grid, DOM и других ключевых технологий фронтенда. Большое количество практических примеров, готовых решений и UI-эффектов для интерфейсов.

📌 Оставляю ссылочку: html5book.ru

📣 Code Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍5🔥3
Date.parse() и неочевидные проблемы при работе с датами!

При работе с датами в JavaScript часто используют Date.parse() или new Date(), чтобы преобразовать строковое значение в дату или получить timestamp. При этом важно понимать, какое значение хранится в системе: календарная дата, локальное время или конкретный момент времени.

Ошибки обычно появляются, когда эти разные сценарии начинают обрабатываться одинаково. Например:
const timestamp = Date.parse(
'2024-01-15T10:30:00Z'
);

console.log(timestamp);


JavaScript возвращает количество миллисекунд от 1 января 1970 года UTC.
Проблемы возникают, когда в Date.parse() передают даты в произвольном формате:
Date.parse('01/15/2024');

Date.parse('15.01.2024');

Date.parse('2024/01/15');


Такие форматы не являются надёжным контрактом между системами. Их обработка может отличаться в зависимости от окружения и реализации JavaScript. Например:
Date.parse('01/02/2024');


Такая запись неоднозначна. Без явного формата невозможно гарантировать одинаковый результат во всех окружениях.

Поэтому при обмене датами между backend и frontend обычно используют ISO 8601 с явным указанием времени и часового пояса:
new Date(
'2024-01-15T10:30:00Z'
);


Здесь описан конкретный момент времени. Указаны дата, время и часовой пояс (UTC), поэтому значение будет одинаково интерпретироваться независимо от локального времени пользователя.

Отдельная проблема возникает при работе с датами без времени. Например:
const date = new Date(
'2024-01-15'
);

console.log(date);


Строка 2024-01-15 в JavaScript интерпретируется как UTC-дата:
2024-01-15T00:00:00.000Z


После этого значение преобразуется в локальный часовой пояс пользователя. В часовом поясе UTC+3 пользователь увидит:
15.01.2024 03:00


А в UTC-5:
14.01.2024 19:00


Само значение времени остаётся одинаковым, но календарная дата при отображении может измениться. Именно здесь часто возникает ошибка в модели данных.

Например, сервер возвращает дату рождения пользователя:
{
"birthday": "2000-01-15"
}


На frontend создаётся объект Date:
const birthday = new Date(
user.birthday
);

birthday.toLocaleDateString('ru-RU');


Разработчик ожидает получить: 15.01.2000. Но пользователь в другом часовом поясе может увидеть: 14.01.2000. Причина в том, что дата рождения — это календарное значение. Она не зависит от часов, минут и часового пояса.

Объект Date в JavaScript используется для работы с конкретным моментом времени, поэтому при преобразовании строк учитывается часовой пояс. Для временных событий лучше использовать полный ISO-формат:
const createdAt = new Date(
'2024-01-15T14:30:00Z'
);


Дата создания сообщения, время оплаты или момент отправки уведомления являются событиями во времени. Для них важно передавать полное значение с часовым поясом.

А вот календарные значения, например дату рождения или дату окончания периода, не всегда стоит преобразовывать в Date. В таких случаях безопаснее работать с исходным значением:
const [year, month, day] =
'2000-01-15'.split('-');

const formattedDate =
`${day}.${month}.${year}`;


Так значение останется календарной датой и не будет изменено из-за часового пояса.

Также стоит учитывать, что Date.parse() не выбрасывает исключение при невозможности распознать дату:
const result = Date.parse(
'invalid-date'
);

console.log(result);


Результат: NaN. Поэтому такие значения необходимо проверять:
const timestamp = Date.parse(value);

if (Number.isNaN(timestamp)) {
throw new Error(
'Invalid date'
);
}


Основная проблема при работе с датами в JavaScript связана не с самим Date.parse(). Проблемы появляются, когда смешиваются разные типы данных: календарные даты, локальное время и конкретные моменты времени.

🔥 Перед использованием Date важно определить, что именно хранится в данных: дата, время события или значение, которое зависит от часового пояса. Только после этого стоит выбирать способ представления и обработки.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
14👍7🔥6
Как создавать независимые компоненты без конфликтов CSS-переменных?

В больших проектах часто используют глобальные переменные:
:root {
--color: blue;
}


Но потом один компонент случайно меняет значение, и стили начинают влиять друг на друга.

CSS позволяет делать локальные токены прямо внутри компонента.
.card {
--color: #222;
color: var(--color);
}


Теперь переменная действует только внутри .card и его потомков.

Можно создавать полностью изолированные темы компонентов.
.dark-card {
--bg: #111;
--text: white;
}


Внутренние элементы автоматически получают эти значения:
.title {
color: var(--text);
}


Без дополнительных классов и дублирования.

Особенно удобно для:
.theme,
.component,
.widget


где каждый блок должен иметь свои настройки.

🔥 Локальные CSS custom properties позволяют строить компонентные дизайн-системы без огромного количества модификаторов и переопределений.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4🤝3
Intersection Observer — отслеживаем появление элементов в области видимости!

Эффективная альтернатива scroll-событиям. Используется для ленивой загрузки, анимаций и инфинит-скролла.

Инициализируем наблюдатель:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
});


Подключаем наблюдение:
document.querySelectorAll('.anim').forEach((el) => {
observer.observe(el);
});


Стили для появления:
.anim { opacity: 0; transform: translateY(30px); transition: 0.4s ease; }
.visible { opacity: 1; transform: none; }


🔥
Простая и масштабируемая практика, которую используют в продакшене: YouTube, Medium, e-commerce.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥108👍7
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ Frontend Handbook — большая база знаний по frontend-разработке!

Здесь собраны статьи, документация, шпаргалки, инструменты и другие ресурсы по HTML, CSS, JavaScript, TypeScript, React и многим другим технологиям. Особенно удобно, что информация хорошо структурирована, поэтому можно быстро найти нужную тему.

Оставляю ссылочку: GitHub 📱

📣 Code Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
12🔥7🤝4
👩‍💻 Группируем заголовок и обычный текст!

Тег <hgroup> объединяет основной заголовок страницы или раздела с дополнительным текстом, который его сопровождает — например, подзаголовком или кратким описанием.

Чаще всего внутри <hgroup> размещают:
• один из заголовков <h1>–<h6>;

• дополнительные элементы текста, например <p> с пояснением.


Он помогает логически связать несколько элементов заголовка, сохраняя структуру документа более понятной для браузеров и вспомогательных технологий. Не используйте <hgroup>, если вы хотите показать два независимых заголовка, — лучше оформить это через <section> или <article>

📣 Code Ready | #атрибут
Please open Telegram to view this post
VIEW IN TELEGRAM
16👍6🤝4
Опа, тут бывший сеньор одного из IT-отделов Яндекса Игорь Никитин выкатил целый канал про Python — и это лучшее, что есть в рунете по теме.

Качественные гайды. Советы от известных прогеров. Тематические мемасы. Короче, ничего лишнего.

Хватит душить питона, учись его кодить: https://t.me/+IzIPzvoa7p40ZTUy 🐍
👎8
CSS.escape() — экранирование динамических значений для CSS-селекторов!

При работе с DOM часто приходится искать элементы по динамическим значениям: id, class, значениям атрибутов. И здесь есть один важный момент: querySelector() и querySelectorAll() принимают не просто строки, а полноценные CSS-селекторы.

Поэтому если часть селектора формируется динамически, нужно учитывать правила синтаксиса CSS. Например:
const id = "user:123";

const element = document.querySelector(
`#${id}`
);


После подстановки браузер получает:
#user:123


На первый взгляд кажется, что мы ищем элемент с id="user:123".

Но для CSS символ : имеет специальное значение. Он используется для псевдоклассов:
:hover
:focus
:checked


Поэтому CSS-парсер воспринимает : не как часть значения, а как элемент синтаксиса селектора.

Для таких случаев существует стандартный метод CSS.escape():
const id = "user:123";

const element = document.querySelector(
`#${CSS.escape(id)}`
);


Теперь значение будет преобразовано в корректный CSS-идентификатор:
#user\:123


Браузер понимает, что : является частью значения, а не специальной конструкцией CSS. Такая проблема возникает не только с двоеточием.

CSS имеет множество специальных символов, которые могут изменить смысл селектора:
const id = "product.item#42";

const element = document.querySelector(
`#${CSS.escape(id)}`
);


Без экранирования символы ., # и другие будут интерпретироваться как часть CSS-селектора.

То же самое относится к динамическим классам:
const className = "theme:dark";

const element = document.querySelector(
`.${CSS.escape(className)}`
);


CSS.escape() работает согласно правилам CSS-идентификаторов и возвращает строку, которую можно использовать внутри селектора:
CSS.escape("hello world");
// "hello\ world"

CSS.escape("item.value");
// "item\.value"

CSS.escape("a:b");
// "a\:b"


До появления этого метода часто использовали ручное экранирование:
value.replace(/:/g, "\\:");


Но такой подход быстро становится неудобным. CSS имеет много специальных случаев: разные символы, пробелы, цифры в начале идентификаторов и другие правила. CSS.escape() переносит эту логику на стандартный API браузера.

Использовать его стоит в местах, где динамическое значение становится частью CSS-селектора:
document.querySelector()

document.querySelectorAll()

element.matches()

element.closest()


Важный момент: CSS.escape() не является механизмом защиты данных.

Он решает только задачу корректного экранирования значения для CSS-селектора. Например:
element.innerHTML = value;


— это уже другая область: HTML и потенциальные XSS-риски. Там используются другие механизмы защиты. Если вы работаете с динамическими id, классами или значениями, которые приходят извне (например, из API), CSS.escape() помогает избежать ошибок парсинга и сохранить ожидаемое поведение DOM API.

🔥 CSS.escape() — хороший способ подготовить динамические значения перед использованием внутри CSS-селекторов.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍6🤝42
👩‍💻 Можно ли стилизовать текст, к которому пользователь перешёл по ссылке?

::target-text — псевдоэлемент, который применяется к тексту, найденному через текстовый фрагмент в URL вида #:~:text=.... Он позволяет задать стили выделения, которые браузер покажет после перехода по такой ссылке.

Примеры использования:
• изменить фон выделенного текста;

• добавить собственный цвет текста;

• настроить контрастное выделение вместо стандартного.


Стандартные якоря #id подсвечивают целевой элемент. Текстовые фрагменты #:~:text=... указывают на конкретную строку текста. ::target-text позволяет настраивать стиль этого автоматического выделения (обычно это жёлтая подсветка от браузера), чтобы он соответствовал дизайну.

📣 Code Ready | #свойство
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥54
🔥 Глобальное обновление программ CyberYozh Academy
3 новых уровня для вашей карьеры


Рынок кибербезопасности меняется каждый месяц, и мы меняемся вместе с ним. Теперь наши флагманские программы выстроены в четкую систему из 3 уровней, которые идеально подойдут для специалиста на любом этапе карьеры.

⚡️Выбирайте свой трек:
🟢 УРОВЕНЬ 1: Новичкам - Инженер по информационной безопасности
Трек для тех, кто готов освоить одну из самых высокооплачиваемых и востребованных профессий в IT с полного нуля, без воды и иллюзий.
Длительность: 11 месяцев
Итог: Диплом установленного образца + помощь с трудоустройством
Стоимость: от 5 015 ₽/мес


🟡УРОВЕНЬ 2: Специализация - Специалист по OSINT
Полное погружение в конкретную специальность. Идеально для студентов, у которых уже есть базовые знания в ИБ, и которым нужно стать профи в узкой нише.
Длительность: 9 месяцев
Итог: Удостоверение + помощь с трудоустройством
Стоимость: от 4 763 ₽/мес


🟥УРОВЕНЬ 3: Повышение квалификации - Пентест внутренней инфраструктуры: Active Directory
Курсы для действующих специалистов в сфере ИБ, которым необходимо расширить свой боевой арсенал и пробить карьерный потолок.
Длительность: 6 месяцев
Итог: Удостоверение + подготовка к сертификации
Стоимость: от 5 821 ₽/мес


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

👉 Подобрать программу и записаться на курс: @cyacademy_support 🦔
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Intl.ListFormat: форматируем списки с учётом языка пользователя!

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

Самый простой вариант — использовать join():
const users = [
'Alex',
'Maria',
'John'
];

users.join(', ');


Такой подход работает только для простого разделения элементов. Но он не знает правил конкретного языка. В английском между последними элементами используется and, в русском — и, а в других локалях могут быть свои правила форматирования.

Если приложение поддерживает несколько языков, обычно появляются ручные проверки:
if (locale === 'en') {
// добавить and
}

if (locale === 'ru') {
// добавить и
}


Поддерживать такую логику сложно, поэтому для подобных задач в JavaScript существует стандартный API Intl.ListFormat.

Создаём форматтер и передаём нужную локаль:
const formatter =
new Intl.ListFormat('ru');

formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);


Результат: JavaScript, TypeScript и Python.

При изменении локали правила форматирования изменятся автоматически:
const formatter =
new Intl.ListFormat('en');

formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);


Результат: JavaScript, TypeScript, and Python.

Intl.ListFormat использует встроенные правила локализации JavaScript, поэтому не нужно самостоятельно реализовывать союзы, разделители и особенности разных языков.

Кроме обычного перечисления можно форматировать варианты выбора. Например, когда пользователь выбирает один из способов оплаты:
const formatter =
new Intl.ListFormat(
'ru',
{
type: 'disjunction'
}
);

formatter.format([
'Карта',
'PayPal',
'Перевод'
]);


Результат: Карта, PayPal или Перевод.

По умолчанию используется conjunction — обычное перечисление через союз "и". Значение disjunction используется для альтернатив через "или".

Также важно понимать, что Intl.ListFormat не изменяет исходные данные. Он только создаёт новую строку:
const tags = [
'Frontend',
'Backend',
'DevOps'
];

const text =
new Intl.ListFormat('ru')
.format(tags);


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

🔥 Intl.ListFormat позволяет использовать стандартные правила локализации JavaScript вместо ручной сборки строк через join() и множества условий для разных языков.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍5🔥4