Code Ready | Frontend
Авторский канал по Frontend разработке. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3NJCKs
Show more📈 Analytical overview of Telegram channel Code Ready | Frontend
Channel Code Ready | Frontend (@code_ready) in the Russian language segment is an active participant. Currently, the community unites 21 656 subscribers, ranking 5 962 in the Technologies & Applications category and 30 064 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 21 656 subscribers.
According to the latest data from 05 October, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by 34 over the last 30 days and by -9 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 7.40%. Within the first 24 hours after publication, content typically collects 4.51% reactions from the total number of subscribers.
- Post reach: On average, each post receives 1 604 views. Within the first day, a publication typically gains 977 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 20.
- Thematic interests: Content is focused on key topics such as css, браузер, интерфейс, загрузка, api.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3NJCKs”
Thanks to the high frequency of updates (latest data received on 06 October, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
createElement() не всегда удобно: разметка смешивается с логикой и увеличивает объём js. Для таких случаев в HTML существует <template> — элемент для хранения готовой DOM-заготовки без её отображения на странице:
const card = document.createElement('article');
const title = document.createElement('h2');
const button = document.createElement('button');
card.className = 'card';
title.className = 'card__title';
button.className = 'card__button';
card.append(title, button);
Ту же структуру можно описать декларативно непосредственно в HTML:
<template id="card-template">
<article class="card">
<h2 class="card__title"></h2>
<button class="card__button">
Открыть
</button>
</article>
</template>
Браузер парсит содержимое <template> как HTML, но не отображает его и не включает в активное дерево документа:
<template>
<h2>Карточка пользователя</h2>
</template>
Содержимое шаблона доступно через свойство content, которое представляет собой DocumentFragment:
const template = document.querySelector(
'#card-template'
);
console.log(template.content);
// DocumentFragment
Поэтому искать элементы шаблона необходимо внутри content, а не через сам <template>:
template.querySelector('.card');
// null
template.content.querySelector('.card');
// <article class="card">...</article>
Для создания независимого экземпляра содержимое шаблона можно импортировать в текущий документ с глубоким копированием:
const fragment = document.importNode(
template.content,
true
);
document.body.append(fragment);
Аргумент true означает глубокое копирование вместе со всеми вложенными узлами. До вставки экземпляр можно заполнить данными, не изменяя исходный шаблон:
const fragment = document.importNode(
template.content,
true
);
fragment.querySelector('.card__title').textContent =
'JavaScript';
document.body.append(fragment);
Один шаблон можно использовать многократно, каждый раз получая независимую DOM-структуру:
function createCard(title) {
const fragment = document.importNode(
template.content,
true
);
fragment.querySelector('.card__title').textContent =
title;
return fragment;
}
document.body.append(
createCard('JavaScript'),
createCard('TypeScript'),
createCard('Node.js')
);
<template> не следует путать с обычным скрытым контейнером: hidden скрывает элемент визуально, но его содержимое остаётся частью документа:
<div hidden>
<video src="video.mp4" autoplay></video>
</div>
У <template> содержимое хранится отдельно и становится частью активного DOM только после создания и вставки экземпляра:
<template id="video-template">
<video src="video.mp4" autoplay></video>
</template>
Есть важный нюанс с событиями: обработчики, зарегистрированные через addEventListener(), при копировании DOM-структуры не переносятся:
const button =
template.content.querySelector('.card__button');
button.addEventListener('click', handler);
const fragment = document.importNode(
template.content,
true
);
Обработчик необходимо назначить уже созданному экземпляру либо использовать делегирование событий:
const button =
fragment.querySelector('.card__button');
button.addEventListener('click', handler);
На практике <template> подходит для карточек, строк таблицы, элементов списка, уведомлений и других повторяемых частей интерфейса с заранее известной структурой:
function createUser(user) {
const fragment = document.importNode(
template.content,
true
);
fragment.querySelector('.card__title').textContent =
user.name;
return fragment;
}
🔥 <template> позволяет хранить HTML-заготовку вне активного DOM и создавать из неё независимые экземпляры по мере необходимости, оставляя структуру в HTML, а работу с данными и поведением — в js.
📣 Code Ready | #практикаFrontendReady в чат с менеджером, чтобы закрепить за собой скидку и узнать подробности:
👉@cyacademy_support@view-transition позволяет управлять поведением View Transition API при навигации между документами. С его помощью можно включить плавные переходы между страницами без необходимости вручную запускать их через JS.
Основные параметры:
• navigation: auto — включает переходы при навигации между страницами; • types — задаёт типы переходов, которые затем можно использовать для разных анимаций.
@view-transition полезно для многостраничных сайтов: смену страниц можно сделать визуально плавной, а сами анимации настроить через CSS-псевдоэлементы View Transition.
📣 Code Ready | #свойствоoverflow: hidden часто ставят просто для обрезки того, что выходит за границы блока.
.wrapper {
overflow: hidden;
}
Но у него есть побочный эффект: элемент становится контейнером прокрутки, даже если полос прокрутки нет. Это может влиять на поведение position: sticky, программную прокрутку и поиск ближайшего скролл-контейнера.
Если прокрутка вообще не нужна, есть более точное значение.
.wrapper {
overflow: clip;
}
Контент по-прежнему обрезается, но контейнер прокрутки не создаётся. Поэтому sticky внутри такого блока может ориентироваться на внешний скролл-контейнер, а не останавливаться на .wrapper.
Разница особенно заметна в такой структуре.
<div class="wrapper">
<aside class="sidebar">...</aside>
</div>
.wrapper { overflow: clip; }
.sidebar {
position: sticky;
top: 16px;
}
Есть ещё полезная деталь: расстояние, на котором происходит обрезка, можно увеличить отдельно.
.wrapper {
overflow: clip;
overflow-clip-margin: 8px;
}
Это удобно, когда содержимое нужно обрезать, но хочется сохранить несколько пикселей для визуального эффекта вроде тени.
🔥 overflow: clip широко доступен в современных браузерах. Важно только не считать его полной заменой hidden: если элемент действительно должен программно прокручиваться, нужен overflow: hidden или другое прокручиваемое значение.
📣 Code Ready | #советОставляю ссылочку: GitHub 📱📣 Code Ready | #репозиторий
:checked в CSS применяется к отмеченным элементам формы — например, checkbox и radio. Он позволяет менять их оформление в зависимости от текущего состояния.
Примеры использования:
• менять цвет выбранного элемента; • создавать кастомные чекбоксы и радиокнопки; • стилизовать связанные элементы через CSS-селекторы; • создавать простые переключатели без JavaScript.По задумке должен работать и с
<option>, но поскольку выпадающий список сильно отличается от системы к системе и от браузера к браузеру, то пока работает только в браузере Chrome на Windows.
📣 Code Ready | #свойствоОставляю ссылочку: GitHub 📱📣 Code Ready | #репозиторий
z-index не является глобальной системой нумерации слоёв страницы. Браузер строит дерево stacking context, где каждый контекст отрисовывается независимо. Значение z-index сравнивается только внутри текущего контекста и не позволяет дочернему элементу напрямую влиять на соседние контексты.
Например, z-index: 999999 у вложенного элемента не гарантирует, что он окажется выше элемента с меньшим значением z-index, если родительский stacking context находится ниже в порядке отрисовки:
.card {
position: relative;
z-index: 1;
}
.modal {
position: absolute;
z-index: 999999;
}
.header {
position: relative;
z-index: 10;
}
Если .modal находится внутри .card, браузер сначала сравнивает .card и .header в родительском stacking context, а уже затем учитывает внутренние слои .card. Высокий z-index дочернего элемента не может изменить положение родительского контекста.
Stacking context создаётся не только через position и z-index. Многие CSS-свойства меняют модель композиции слоёв и создают отдельный контекст наложения:
.component {
opacity: 0.99;
transform: translateZ(0);
filter: blur(5px);
isolation: isolate;
contain: paint;
}
В реальных проектах чаще всего проблемы возникают у модальных окон, dropdown, popover и tooltip-компонентов, когда один из родителей создаёт собственный stacking context:
.layout {
transform: translate3d(0, 0, 0);
}
.dropdown {
position: absolute;
z-index: 999999;
}
В такой ситуации увеличение z-index не помогает, потому что элемент остаётся внутри ограниченного контекста .layout.
Отдельный случай — position: fixed. Обычно такой элемент привязан к viewport, но некоторые свойства родителей изменяют его containing block:
.page {
transform: translateZ(0);
}
.modal {
position: fixed;
inset: 0;
z-index: 10000;
}
Теперь modal рассчитывает позицию относительно .page, а не viewport. Поэтому проблема решается не изменением z-index, а изменением структуры DOM.
Для глобальных интерфейсных слоёв используют отдельный DOM-слот вне основного дерева приложения. Такой подход лежит в основе portal-механизма современных UI-библиотек:
<body>
<div id="app"></div>
<div id="overlay-root"></div>
</body>
Также необходимо учитывать, что не все проблемы перекрытия связаны со stacking context. Например, overflow: hidden может обрезать дочерний элемент независимо от его z-index:
.container {
overflow: hidden;
}
.dropdown {
position: absolute;
z-index: 1000;
}
При отладке проблем со слоями необходимо проверять всю цепочку родителей: наличие stacking context, ограничения overflow, изменённый containing block и фактическое расположение элементов в DOM.
🔥 z-index — это только один параметр системы композиции браузера. В сложных интерфейсах реальный порядок отображения определяется структурой stacking context.
📣 Code Ready | #практика::file-selector-button — псевдоэлемент, представляющий кнопку внутри поля <input type="file">. Позволяет стилизовать её так же, как любую кнопку интерфейса: менять фон, бордеры, скругления, состояния наведения/фокуса и другие стили.
С его помощью можно настроить:
• background — цвет фона; • color — цвет текста; • border — рамку кнопки; • padding — внутренние отступы; • font — оформление текста.Для лучшей доступности обеспечьте заметные стили фокуса (
outline, outline-offset).
📣 Code Ready | #свойство• Разберётесь, почему Flexbox и Grid не гарантируют визуально идеальное выравнивание;
• Узнаете, как метрики шрифтов и высота строки влияют на положение текста;
• Посмотрите, почему иконки рядом с текстом часто «съезжают» и как это исправлять на практике.
🔊 Продолжай читать на Habr!📣 Code Ready | #статья
main thread блокирует выполнение других задач. Даже обычный цикл может превратиться в длительную задачу, если обработка элементов достаточно тяжёлая:
function processItems(items) {
for (const item of items) {
renderItem(item);
}
}
Классический способ разбить такую работу — планировать продолжение через setTimeout(). В современных браузерах для добровольной передачи управления планировщику есть более специализированный механизм — scheduler.yield():
async function processItems(items) {
for (let i = 0; i < items.length; i++) {
renderItem(items[i]);
if ((i + 1) % 100 === 0) {
await scheduler.yield();
}
}
}
scheduler.yield() приостанавливает текущую async-функцию и планирует её продолжение как отдельную задачу, давая браузеру возможность выполнить другую ожидающую работу на main thread:
await scheduler.yield();
// выполнение продолжится позже
Это принципиально отличается от await Promise.resolve(): resolved Promise продолжает выполнение через microtask queue и не обеспечивает полноценную передачу управления event loop для выполнения следующей задачи:
await Promise.resolve();
// продолжение выполняется как microtask
Делать yield() после каждой итерации не стоит: каждая передача управления создаёт дополнительные накладные расходы. Размер порции работы зависит от стоимости конкретных операций, поэтому 100 или 200 итераций — лишь пример, а не универсальное значение.
if ((i + 1) % CHUNK_SIZE === 0) {
await yieldToMain();
}
Поддержка scheduler.yield() пока не универсальна, поэтому стоит предусмотреть запасной вариант:
function yieldToMain() {
if (globalThis.scheduler?.yield) {
return scheduler.yield();
}
return new Promise(resolve => setTimeout(resolve, 0));
}
🔥 scheduler.yield() полезен для кооперативного планирования длительной работы на main thread: обработки больших наборов данных и постепенного обновления сложного UI. Для тяжёлых вычислений, интенсивно использующих процессор, Worker остаётся предпочтительным решением: yield() не переносит вычисления с main thread, а только разбивает их выполнение во времени.
📣 Code Ready | #практикаРазбираем Reflect API и его основные методы для чтения, изменения, проверки и удаления свойств, вызова функций, создания экземпляров, работы с дескрипторами и получения собственных ключей объекта. Reflect применяется для метапрограммирования, низкоуровневой работы с объектами и реализации Proxy-логики с явным результатом операций.
📣 Code Ready | #шпора:autofill — псевдокласс, который находит поля формы, куда браузер сам подставил сохранённые данные: адрес, телефон, почту. Нужен, чтобы подсвеченные браузером поля не выбивались из дизайна формы.
Как работает автозаполнение:
• срабатывает только по инициативе браузера, через JavaScript вызвать его нельзя; • браузер может заполнить сразу несколько полей формы; • поле остаётся :autofill, пока пользователь не изменит значение; • после ручного редактирования оно больше не считается автозаполненным.Не полагайтесь на
:autofill для валидации: это лишь визуальное состояние, а не факт корректности данных.
📣 Code Ready | #свойство<data> позволяет показать пользователю обычный текст и одновременно связать его с другим значением, которое удобно использовать в скриптах или при обработке данных.
В <data> используются:
• содержимое тега — текст, который видит пользователь; • value — машиночитаемое значение; • JavaScript — при необходимости может получить значение через свойство value.Элемент
<data> стоит использовать, когда вы не хотите выделять элементы на вёрстке, например, при помощи <div> или <span>, но вам нужно связать текст с внутренним ID или значением, который вы будете использовать при обработке запросов пользователя.
📣 Code Ready | #атрибутbutton.disabled = true;
input.disabled = true;
link.tabIndex = -1;
disabled применим не ко всем HTML-элементам, а изменение tabindex решает только задачу фокуса. Для блокировки целой области документа существует глобальный атрибут inert:
<main id="content">
<button>Сохранить</button>
<a href="/profile">Профиль</a>
<input type="text">
</main>
Состоянием можно управлять через HTMLElement.inert, без поиска и изменения каждого интерактивного элемента внутри контейнера:
const content = document.querySelector('#content');
content.inert = true;
После установки inert контейнер и его потомки в плоском дереве (flat tree) не могут получать фокус. Это относится и к программному вызову focus():
content.inert = true;
document.querySelector('#content input').focus();
Пользовательская активация также блокируется: клик пользователя по кнопке внутри inert-области не приводит к click на этой кнопке. Программный element.click() при этом следует рассматривать отдельно:
const button = document.querySelector('#content button');
button.addEventListener('click', () => {
console.log('click');
});
content.inert = true;
В отличие от inert, pointer-events: none влияет на определение элемента под указателем, но сам по себе не исключает элементы из последовательной навигации с клавиатуры:
.content {
pointer-events: none;
}
inert действует шире: элементы не получают фокус, пользовательское взаимодействие блокируется, а содержимое исключается из дерева доступности.
Например, основной интерфейс можно деактивировать при открытии выдвижной панели, расположенной вне inert-контейнера:
<main id="content">
<!-- основной интерфейс -->
</main>
<aside id="drawer" hidden>
<!-- выдвижная панель -->
</aside>
Состояние всего фонового интерфейса переключается одной операцией независимо от количества элементов внутри main:
function openDrawer() {
content.inert = true;
drawer.hidden = false;
}
function closeDrawer() {
content.inert = false;
drawer.hidden = true;
}
Для модальных интерфейсов есть <dialog>. Вызов showModal() помещает диалог в верхний слой (top layer), а остальную часть документа браузер делает inert автоматически:
const dialog = document.querySelector('dialog');
dialog.showModal();
Сам inert не задаёт визуальное состояние заблокированной области. При необходимости оно оформляется отдельно через CSS:
[inert] {
opacity: 0.6;
}
🔥 inert позволяет исключить целую область документа из взаимодействия без ручного управления disabled, tabindex и состоянием каждого вложенного элемента.
📣 Code Ready | #практика