Code Ready | Frontend
Авторский канал по Frontend разработке. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3NJCKs
Показати більше📈 Аналітичний огляд Telegram-каналу Code Ready | Frontend
Канал Code Ready | Frontend (@code_ready) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 21 538 підписників, посідаючи 6 162 місце в категорії Технології та додатки та 30 489 місце у регіоні Росія.
📊 Показники аудиторії та динаміка
З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 21 538 підписників.
За останніми даними від 27 жовтня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на -51, а за останні 24 години на -12, загальне охоплення залишається високим.
- Статус верифікації: Не верифікований
- Рівень залученості (ER): Середній показник залученості аудиторії становить 6.40%. Протягом перших 24 годин після публікації контент зазвичай збирає 4.29% реакцій від загальної кількості підписників.
- Охоплення публікацій: В середньому кожен допис отримує 1 379 переглядів. Протягом першої доби публікація в середньому набирає 925 переглядів.
- Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 23.
- Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як css, браузер, интерфейс, загрузка, api.
📝 Опис та контентна політика
Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
“Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3NJCKs”
Завдяки високій частоті оновлень (останні дані отримано 28 жовтня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.
3 новых уровня для вашей карьерыРынок кибербезопасности меняется каждый месяц, и мы меняемся вместе с ним. Теперь наши флагманские программы выстроены в четкую систему из 3 уровней, которые идеально подойдут для специалиста на любом этапе карьеры. ⚡️Выбирайте свой трек: 🟢 УРОВЕНЬ 1: Новичкам - Инженер по информационной безопасности
Трек для тех, кто готов освоить одну из самых высокооплачиваемых и востребованных профессий в IT с полного нуля, без воды и иллюзий. Длительность: 11 месяцев Итог: Диплом установленного образца + помощь с трудоустройством Стоимость: от 5 015 ₽/мес🟡УРОВЕНЬ 2: Специализация - Специалист по OSINT
Полное погружение в конкретную специальность. Идеально для студентов, у которых уже есть базовые знания в ИБ, и которым нужно стать профи в узкой нише. Длительность: 9 месяцев Итог: Удостоверение + помощь с трудоустройством Стоимость: от 4 763 ₽/мес🟥УРОВЕНЬ 3: Повышение квалификации - Пентест внутренней инфраструктуры: Active Directory
Курсы для действующих специалистов в сфере ИБ, которым необходимо расширить свой боевой арсенал и пробить карьерный потолок. Длительность: 6 месяцев Итог: Удостоверение + подготовка к сертификации Стоимость: от 5 821 ₽/месНеважно, делаете ли вы первые шаги или уже давно работаете - у нас есть инструменты, чтобы кратно усилить ваши скиллы. 👉 Подобрать программу и записаться на курс: @cyacademy_support 🦔
::target-text — псевдоэлемент, который применяется к тексту, найденному через текстовый фрагмент в URL вида #:~:text=.... Он позволяет задать стили выделения, которые браузер покажет после перехода по такой ссылке.
Примеры использования:
• изменить фон выделенного текста;
• добавить собственный цвет текста;
• настроить контрастное выделение вместо стандартного.Стандартные якоря
#id подсвечивают целевой элемент. Текстовые фрагменты #:~:text=... указывают на конкретную строку текста. ::target-text позволяет настраивать стиль этого автоматического выделения (обычно это жёлтая подсветка от браузера), чтобы он соответствовал дизайну.
📣 Code Ready | #свойство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 | #практика<hgroup> объединяет основной заголовок страницы или раздела с дополнительным текстом, который его сопровождает — например, подзаголовком или кратким описанием.
Чаще всего внутри <hgroup> размещают:
• один из заголовков <h1>–<h6>;
• дополнительные элементы текста, например <p> с пояснением.Он помогает логически связать несколько элементов заголовка, сохраняя структуру документа более понятной для браузеров и вспомогательных технологий. Не используйте
<hgroup>, если вы хотите показать два независимых заголовка, — лучше оформить это через <section> или <article>
📣 Code Ready | #атрибут
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 | #практика: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 | #совет🥇место – 1 000 000 рублей 🥈место – 700 000 рублей 🥉место – 500 000 рублей Награда за 4-8 места - 100 000 рублейПройди заочный онлайн-этап и получи путевку на очный этап турнира в Республику Татарстан! Перелет, питание, проживание - за счет организаторов. 🇷🇺 Подать заявку и узнать подробности 🇷🇺
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 | #практика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 | #совет<math> используется для встраивания математических выражений на веб-страницу с помощью языка MathML. Он позволяет отображать дроби, степени, корни, индексы, матрицы и другие математические конструкции без изображений.
Кроме глобальных атрибутов, <math> поддерживает:
• display="inline" — формула отображается внутри строки (по умолчанию). • display="block" — формула выводится отдельным блочным элементом. • alttext — альтернативное текстовое описание формулы.Все теги MathML чувствительны к регистру: используйте строго строчные (
<msup>, а не <MSUP>). Для лучшего внешнего вида можно подключать стили к формуле, но аккуратно, некоторые свойства не работают
📣 Code Ready | #атрибут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 | #практика• Разбирается, почему привычные способы защиты от XSS становятся сложнее и какие проблемы есть у старых подходов вроде DOMPurify;
• Показывается новый HTML Sanitizer API, который позволяет безопаснее работать с пользовательским HTML прямо на уровне браузера;
• Объясняется, как современные веб-разработчики могут упростить код и повысить безопасность приложений.
🔊 Продолжай читать на Habr!📣 Code Ready | #статья
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 | #практика