Code Ready | Frontend
Авторский канал по Frontend разработке. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3NJCKs
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Code Ready | Frontend
تُعد قناة Code Ready | Frontend (@code_ready) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 21 657 مشتركاً، محتلاً المرتبة 5 964 في فئة التكنولوجيات والتطبيقات والمرتبة 30 059 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 21 657 مشتركاً.
بحسب آخر البيانات بتاريخ 06 أكتوبر, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار 35، وفي آخر 24 ساعة بمقدار -6، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 7.57%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 4.51% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 1 640 مشاهدة. وخلال اليوم الأول يجمع عادةً 977 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 20.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل css, браузер, интерфейс, загрузка, api.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3NJCKs”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 07 أكتوبر, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
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 | #практика