tgindex
Frontend Matrix

Frontend Matrix

Статистика
@frontendmatrixрусский

Ссылка: https://t.me/+jKZx768Kfrk1ZjIy По всем вопросам: @Shustov_d

Последний пост
5 авг.
Последнее чтение
13 авг.
Постов за неделю
0
Всего постов
20
Тип
открытый
Язык
русский
В каталоге с
13 авг.
Подписчики
2 311
−2 за 3 дн.
Сутки
−1
−0,04%
Неделя
 
Месяц
 
Просмотров на пост
252
20 постов
Вовлечённость
10,9%
к подписчикам
Постов в день
0,0
всего 20
Упоминаний
0
каналов
Охват размещения
оценка
1/24сутки в ленте
170
1/48двое суток
194
1/72трое суток
210

Оценка по просмотрам недавних постов: пост набирает почти всё за первые сутки.

Посты

  • @starting-style: Анимации при первом рендере без JS Раньше, чтобы плавно анимировать появление элемента, который только что добавили в DOM, приходилось изворачиваться через requestAnimationFrame, setTimeout или тяжелые JS-библиотеки. Теперь во всех современных браузерах работает нативный метод @starting-style /* Исходное состояние элемента в DOM */ .dialog { opacity: 1; transform: scale(1); transition: opacity 0.3s, transform 0.3s; } /* Свойства, из которых НАЧИНАЕТСЯ анимация при монтировании */ @starting-style { .dialog { opacity: 0; transform: scale(0.9); } }

  • 💡 JS: Удобная группировка массивов без сторонних библиотек Забудь про громоздкие .reduce() или подключение lodash.groupBy только ради одной операции. В современном JS группировка уже встроена const products = [ { name: "MacBook", category: "electronics" }, { name: "T-Shirt", category: "clothes" }, { name: "iPhone", category: "electronics" } ]; // Группируем по ключу category: const grouped = Object.groupBy(products, product => product.category); console.log(grouped); /* { electronics: [{ name: "MacBook", ... }, { name: "iPhone", ... }], clothes: [{ name: "T-Shirt", ... }] } */ Чистый, читаемый код без внешних зависимостей.

  • 🛠 JS / API: AbortController — отмена запросов при размонтировании компонента Если пользователь переключает табы или быстро вводит текст в инпут, старые фетч-запросы продолжают лететь по сети и могут затереть актуальные данные let currentController = null; async function searchData(query) { // Отменяем предыдущий запрос, если он еще выполняется if (currentController) { currentController.abort(); } currentController = new AbortController(); try { const res = await fetch(`/api/search?q=${query}`, { signal: currentController.signal // Передаем сигнал отмены }); const data = await res.json(); renderResults(data); } catch (err) { if (err.name === 'AbortError') { console.log('Запрос отменен, все в порядке'); } } }

  • 🎯 TypeScript: Забудь про as — используй Type Guards для безопасной типизации Использование as SomeType (Type Assertion) отключает проверку типов и приводит к багам в рантайме. Пиши кастомные предикаты типов interface User { id: number; name: str; } interface Guest { isGuest: true; } type Account = User | Guest; # ❌ Опасно (компилятор поверит на слово, а в рантайме может быть undefined): function getNameUnsafe(account: Account) { return (account as User).name; } # ✅ Безопасно через Type Guard (возвращаемый тип `account is User`): function isUser(account: Account): account is User { return 'name' in account; } function getNameSafe(account: Account) { if (isUser(account)) { return account.name; // TS автодополнением видит, что это User } return "Гость"; }

  • ⚡️ CSS: Забудь про JavaScript для отслеживания размера элементов Раньше для адаптива компонентов в зависимости от размера их контейнера приходилось подключать ResizeObserver на JS. Теперь это чистое CSS-решение. /* 1. Объявляем контейнер */ .card-wrapper { container-type: inline-size; } /* 2. Верстаем внутри карточки с привязкой к ее ширине */ .card-title { /* 5cqw = 5% от ширины КОНТЕЙНЕРА, а не экрана */ font-size: clamp(1rem, 5cqw, 2rem); } /* Адаптируем сетку карточки по ее собственному размеру */ @container (min-width: 400px) { .card { display: grid; grid-template-columns: 1fr 2fr; } } Виджет/карточка будет идеально выглядеть и в узкой боковой колонке, и во всю ширину экрана без единой строчки JS-кода.

  • 🚀 Прекратите использовать Array.includes() внутри циклов Типичная ошибка при работе с большими массивами на фронтенде — поиск элементов через .includes() или .find() внутри фильтрации. const blockedUserIds = [102, 405, 981, ...10000_items]; const allUsers = [...50000_items]; // ❌ ПЛОХО: O(N * M) — массив фильтруется очень долго const activeUsers = allUsers.filter(user => !blockedUserIds.includes(user.id) ); // ✅ БЫСТРО: O(N) — переводим список в Set const blockedSet = new Set(blockedUserIds); const activeUsers = allUsers.filter(user => !blockedSet.has(user.id) // Хеш-таблица: поиск за O(1) ); Замена массива на Set с операцией .has() ускоряет фильтрацию больших списков в десятки раз за счет константного времени поиска $O(1)$

  • ⚡️ Как ускорить рендеринг длинных страниц одной строчкой CSS Если у вас на странице много контента (лента постов, длинные таблицы, каталоги товаров), браузер тратит кучу ресурсов на расчет макета и отрисовку даже тех элементов, которые находятся глубоко за пределами экрана. Свойство content-visibility: auto указывает браузеру пропустить рендеринг элементов до тех пор, пока они не окажутся близко к области видимости. .card-item { /* Браузер не рендерит содержимое карточки, пока она вне экрана */ content-visibility: auto; /* Задаем примерную высоту, чтобы скроллбар не прыгал */ contain-intrinsic-size: 0 300px; }

  • 🧬 Хватит использовать JSON.parse(JSON.stringify()) для глубокого клонирования Когда нужно сделать полную копию сложного объекта (со всеми вложенностями), старый трюк с JSON часто ломает данные: он не умеет копировать даты (Date), регулярные выражения (RegExp), карты (Map/Set) и циклические ссылки. В современном JS есть встроенный инструмент, который делает это правильно и быстро — structuredClone. const user = { name: "Alex", joined: new Date(), skills: new Set(["JS", "React"]), }; // ❌ Старый костыльный метод (дата превратится в строку, Set просто исчезнет) const badCopy = JSON.parse(JSON.stringify(user)); // ✅ Современный нативный метод (все типы данных сохраняются!) const goodCopy = structuredClone(user); console.log(goodCopy.joined instanceof Date); // true console.log(goodCopy.skills); // Set(2) {"JS", "React"}

  • ⚡️ Как победить «прыгающий» скроллбар в CSS? Бывало такое: переходишь между страницами, на одной контента мало (скроллбара нет), на другой много (скроллбар появляется), и весь интерфейс неприятно дергается в сторону? html { /* Резервирует место под скроллбар заранее, предотвращая сдвиг контента */ scrollbar-gutter: stable; } Браузер сразу оставляет пустой трек под полосу прокрутки. Когда она появляется, контент никуда не смещается.

  • Куда ты вставляешь тег <script>? Если до сих пор по старинке бросаешь его в самый низ тега <body>, пора это менять. Современный стандарт — подключать скрипты в <head>, но с правильными атрибутами. 💡 Коротко разница: 1️⃣ Обычный <script src="..."> Блокирует чтение HTML. Браузер видит скрипт, останавливает загрузку страницы, скачивает его, выполняет, и только потом строит сайт дальше. Привет, тормоза. 2️⃣ <script async src="..."> Загружается параллельно с HTML. Как только скачался — HTML замирает, и скрипт выполняется. Отлично подходит для независимых вещей: метрики, аналитика, пиксели соцсетей. 3️⃣ <script defer src="..."> Загружается в фоновом режиме, вообще не мешая HTML. Выполняется строго после того, как вся страница полностью загрузилась. Идеально для основного кода твоего приложения. ⚡ Как делать правильно: <head> <!-- Основная логика сайта: загрузится в фоне, выполнится вовремя --> <script defer src="app.js"></script> <!-- Яндекс.Метрика или Google Analytics: не ждет никого --> <script async src="analytics.js"></script> </head>

  • 🖼️ Адаптивные картинки без CSS-медиазапросов Загружать огромную десктопную картинку на мобильном телефоне — грех против оптимизации и скорости загрузки. Вместо кучи классов в CSS, используй правильный HTML-тег <picture>. ⚡ Идеальное решение для адаптивности: <picture> <!-- Если экран смартфона (до 768px), грузим легкую вертикальную фотку --> <source media="(max-width: 768px)" srcset="mobile-hero.webp"> <!-- Для больших экранов — полноценный баннер --> <source media="(min-width: 769px)" srcset="desktop-hero.webp"> <!-- Запасной вариант для старых браузеров --> <img src="desktop-hero.jpg" alt="Главный баннер" loading="lazy"> </picture> Браузер скачает только один нужный файл, экономя трафик пользователя. А формат .webp уменьшит вес картинки ещё в пару раз.

  • 🔥 CSS-киллер: Забудь про JavaScript там, где он больше не нужен Раньше, чтобы изменить стиль родительского элемента при клике или наведении на дочерний, нам приходилось подключать JS и навешивать классы вроде .is-active. Теперь CSS умеет делать это сам благодаря псевдоклассу :has(). JS const input = document.querySelector('.input-field'); input.addEventListener('focus', () => { input.parentElement.classList.add('highlight'); }); CSS /* Выбираем карточку (.card), ТОЛЬКО если внутри неё есть фокус на инпуте */ .card:has(.input-field:focus) { border-color: #007bff; box-shadow: 0 0 10px rgba(0, 123, 255, 0.5); }

  • ⚖️ JS: В чем разница между || и ??? До появления оператора (??) все использовали логическое ИЛИ для задания дефолтных значений. Но у ИЛИ есть скрытая проблема: он считает ложными числа 0 и пустые строки: const config = { volume: 0 // Пользователь выкрутил звук в ноль }; const currentVolume = config.volume || 50; console.log(currentVolume); // Выведет 50! Ноль проигнорировался. Оператор (??) заменяет значение только в том случае, если слева стоит null или undefined. const currentVolume = config.volume ?? 50; console.log(currentVolume); // Выведет 0. Всё работает корректно! Используйте (||) для строк или булевых значений, а (??) — когда работаете с числами, где ноль имеет значение.

  • ​🔍 Как поймать исчезающий :hover Вы хотите настроить стили для всплывающей подсказки или меню, которое появляется только при наведении мыши. Но стоит увести курсор в панель разработчика, как элемент исчезает ​Как зафиксировать это состояние в Chrome/Firefox: 1.​Откройте DevTools (F12) и выберите нужный элемент в инспекторе. 2.​В правой панели со стилями найдите маленькую кнопку :hov (Toggle Element State). 3.​Поставьте галочку напротив :hover, :focus или :active. ​Теперь элемент намертво застынет в этом состоянии

  • 🧹 Удаляем дубликаты из массива в одну строчку ​Забудьте про циклы for или сложные конструкции с .filter(), если вам нужно просто очистить массив от повторяющихся значений. Для этого есть встроенный объект Set, который хранит только уникальные элементы. ​🛠 Код: const numbers = [1, 2, 2, 3, 4, 4, 4, 5]; // Используем Set и спред-оператор (...) const uniqueNumbers = [...new Set(numbers)]; console.log(uniqueNumbers); // Вывод: [1, 2, 3, 4, 5] Работает максимально быстро и выглядит очень лаконично.

  • ​💡 Как правильно использовать useActionState в React 19 ​Новый хук useActionState — лучший способ обрабатывать отправку форм без ручного контроля. // React 19+ const [state, formAction, isPending] = useActionState( async (prevState, formData) => { const result = await updateProfile(formData.get("name")); return result; // Новый state }, { success: null } // Дефолтный state ); return ( <form action={formAction}> <input name="name" /> <button disabled={isPending}> {isPending ? 'Сохранение...' : 'Обновить'} </button> </form> ); Минимум бойлерплейта, максимум производительности.

  • ​🔥 CSS Anchor Positioning: Забудьте про тяжелые JS-библиотеки для поповеров и дропдаунов ​Раньше для создания всплывающих подсказок, дропдаунов или контекстных меню, которые привязаны к определенной кнопке и не ломаются при скролле, приходилось тащить тяжелые JS-библиотеки вроде Popper.js или Floating UI. ​Теперь CSS Anchor Positioning полностью поддерживается всеми современными браузерами и позволяет делать это нативно /* 1. Элемент-источник (кнопка) */ .anchor-button { anchor-name: --my-anchor; } /* 2. Всплывающее меню */ .dropdown-menu { position: absolute; /* Привязываем топ меню к низу кнопки */ top: anchor(--my-anchor bottom); /* Выравниваем по левому краю кнопки */ left: anchor(--my-anchor left); }

  • ​💡 CSS-магия: Свойство field-sizing для адаптивных инпутов ​Раньше, чтобы текстовое поле автоматически растягивалось по высоте или ширине в зависимости от введенного пользователем текста, приходилось писать костыли на JavaScript. ​Теперь в CSS появилось нативное решение — field-sizing: content;! textarea { field-sizing: content; min-height: 40px; max-height: 200px; } Поле изначально имеет минимальную высоту, но как только пользователь начинает печатать и текст не помещается, инпут автоматически растет вниз, пока не упрется в max-height. Без единой строчки JS

  • Облегченные JS-фреймворки ​Пока React 19 и Next.js усложняют архитектуру, набирает обороты ренессанс легковесных инструментов (Arrow.js, Kasper). Их главная фишка — отсутствие этапа сборки, простая реактивность на прокси/сигналах и файлы llms.txt в корне. Разработчики этих фреймворков прямо заявляют: архитектура спроектирована так, чтобы ИИ-ассистенты (вроде Cursor или Copilot) могли писать код без галлюцинаций.

  • Tailwind v4.0⚡️ Четвертая версия Tailwind окончательно захватила продакшен, и если вы еще не обновились — самое время. Главная фишка релиза — тотальный уход от JavaScript в сторону нативного CSS. Больше никаких портянок на JS. Движок Oxide на Rust: Скорость сборки выросла в 10 раз. Стили компилируются буквально за миллисекунды. Tailwind теперь сам умеет в вендорные префиксы и нативную вложенность.

Frontend Matrix — tgindex