Веб-страница
22.2K subscribers
2.15K photos
559 videos
2 files
4.43K links
Всё по фронтенду, бэкенду и девопсу в одном месте

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Сайт: https://tprg.ru/site

Регистрация в перечне РКН: https://tprg.ru/64ai
Download Telegram
Мобильное меню Starlight работает даже без JavaScript

Если скрипт не загрузился, меню документации всё равно должно позволять перейти на другую страницу. В Starlight 0.42 управление мобильным меню перенесли на Popover API. В браузере с поддержкой API оно открывается и при отключённом JavaScript.

В разборе релиза есть демонстрация и ссылка на реализацию. Для своего меню можно начать с той же проверки: отключить скрипты и пройти основные действия с клавиатуры.

В npm-пакете Starlight при этом стало больше JavaScript: исходные TypeScript-файлы теперь компилируются, а типы поставляются отдельно. Это избавляет пользователей от проверки чужих .ts-файлов со своей конфигурацией tsc.

У этих изменений разные адресаты: Popover API уменьшает зависимость интерфейса от клиентского кода, а формат пакета влияет на работу инструментов разработчика. Объём JavaScript в npm сам по себе не говорит, сколько кода получит браузер.
🔥2
Как найти компонент, который тормозит сборку Astro

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

В Astro 7.4 появился `astro build --timings`. Отчёт показывает этапы сборки, плагины Vite, обработку Markdown, изображения и самые медленные страницы.

В примере команды почти всё время генерации страниц уходило на компоненты. Сначала страница получала комментарии, затем каждый комментарий запрашивал профиль автора. Возникали два последовательных сетевых ожидания.

Запросы собрали в родительском компоненте, где данные получали через Promise.all(), а профили передавали вниз. Генерация страниц в этом примере сократилась с 2,10 до 1,13 секунды.

Отчёт помог выбрать место исправления. Сам по себе новый флаг сборку не ускоряет.
👍2🔥2
Свой чекбокс без переписывания его поведения на JavaScript

У чекбокса нужен особый вид, но переключение с клавиатуры, фокус и участие в форме хочется сохранить. Для этого внутри компонента можно оставить настоящий input.

В примере Энди Белла поле лежит в label, занимает всю площадь своей обёртки и получает appearance: none. Рядом находится SVG-галочка, скрытая от вспомогательных технологий через aria-hidden.

Состояние по-прежнему хранит браузер. Селектор input:checked + svg показывает галочку, а :has(input:checked) меняет фон обёртки. Само поле остаётся доступным для фокуса.

Размеры заданы в em, поэтому компонент масштабируется вместе со шрифтом. Для радиокнопок автор показывает тот же подход с другим индикатором. В статье есть живые примеры и полный CSS.
🔥5
Где именно прокрутка должна запустить анимацию? Теперь это видно в DevTools

Анимация срабатывает раньше нужного, а по нескольким CSS-значениям трудно понять почему. Брамус выпустил Scroll-Triggered Animations Debugger — расширение с отдельной панелью в Elements.

Оно показывает контейнер прокрутки, анимируемый элемент и объект, относительно которого считается триггер. На миникарте видны диапазоны активации; их можно менять прямо в панели. Индикатор показывает, активен ли триггер сейчас.

Есть поддержка scroll(), view() и элементов с position: sticky.

У инструмента есть ограничения: относительные единицы отображаются как вычисленные пиксели, а выбор элемента внутри iframe мешает получить нужные данные. Поэтому для примеров CodePen автор рекомендует отдельный Debug View.
🔥4
GitHub ускорил страницы, отправляя больше готового CSS

При CSS-in-JS часть работы со стилями выполняется во время рендеринга. В большой системе компонентов эта цена повторяется на множестве страниц.

GitHub рассказал о переходе на CSS Modules. Команда переносила стили компонентов и заменяла использование свойства sx отдельными CSS-файлами. Переходные обёртки позволяли продолжать пользоваться компонентами, пока их потребителей обновляли по частям.

Отдельно пришлось отвязать темы от styled-components. Миграцию раскатывали постепенно, с флагами и проверками перед включением.

На части страниц команда наблюдала сокращение времени серверного рендеринга на 1–22%. Это результаты конкретных этапов переноса, а не обещание одинакового ускорения любому проекту после замены библиотеки.
👍1🔥1
Двойное нажатие на кнопку приближает страницу? Есть точечное исправление

Пользователь быстро переключает станции в веб-плеере, а Safari на iPhone принимает нажатия за жест увеличения. Запрещать масштабирование всей страницы ради одной кнопки не требуется.

Энди Белл показал решение через `touch-action`:

.button {
touch-action: manipulation;
}


Значение разрешает перемещение страницы и увеличение двумя пальцами, но отключает двойное касание для зума на этом элементе.

В отличие от user-scalable=no в метатеге viewport, здесь сохраняется возможность приблизить содержимое. Это пригодится кнопкам, которые часто нажимают подряд: переключателям, счётчикам и игровым контролам.

В статье есть два интерактивных примера для сравнения на телефоне.
❤3🔥3👍2
Переходы из Internet Explorer вернулись через View Transition API

Шахматная сетка, жалюзи, растворение пикселями — в старом IE такие эффекты включали метатегом при входе на страницу или выходе с неё.

Брамус воссоздал все 23 эффекта RevealTrans в библиотеке ie-page-transitions. Она читает прежние Page-Enter и Page-Exit, а небольшой скрипт переводит настройки в типы современных View Transitions.

Дальше работает CSS: снимки старой и новой страницы анимируются через clip-path, маски и зарегистрированные пользовательские свойства. На демосайте можно переключать эффекты и смотреть варианты для SPA и обычного многостраничного сайта.

Поддержку нужно проверять для выбранного режима: переходы между документами требуют Cross-Document View Transitions. Библиотека не добавляет этот API браузерам, где его нет.
❤2
Nuxt вводит собственный серверный API поверх Nitro

Серверный код Nuxt-проекта часто импортирует функции из h3 и nitropack. Когда эти зависимости меняют API, обновление затрагивает и приложение, и модули экосистемы.

В Nuxt 4.6 появился `nuxt/server`. Фреймворк предоставляет свои серверные утилиты и типы: события запроса, правила маршрутов и типизированный $fetch.

Это даёт Nuxt возможность адаптироваться к изменениям нижележащих библиотек за собственным интерфейсом. В статье команда объясняет, как такой слой упрощает дальнейший переход к Nitro 3 и h3 2.

Nitro остаётся серверной реализацией по умолчанию. Альтернатива @nuxt/vite-server пока экспериментальная, и команда по-прежнему рекомендует Nitro большинству проектов.
❤3
Как закончить фон целым узором, даже если высота блока меняется

Повторяющийся фон обрезается снизу, потому что текст задаёт произвольную высоту секции. background-repeat: round убирает обрезку, но меняет размер самих плиток.

Ахмад Шадид предлагает округлять высоту блока. calc-size() получает размер, рассчитанный для auto, а round(up, …) увеличивает его до ближайшего значения, кратного высоте узора.

Так при переносе текста меняется высота секции, а размер рисунка остаётся прежним. В статье разобраны внутренние отступы и разница между округлением вверх и вниз: уменьшение высоты может оставить контенту слишком мало места.

На момент публикации автор отмечает поддержку решения только в Chrome. Для остальных браузеров стоит сохранить обычную автоматическую высоту как базовый вариант.
🔥3
Почему запись глубины в шейдере может заставить GPU делать лишнюю работу

GPU умеет отбрасывать скрытые фрагменты до запуска дорогого фрагментного шейдера. Но если шейдер сам меняет глубину, драйверу трудно понять заранее, останется ли такая оптимизация корректной.

В обзоре WebGPU для Chrome 155–156 показано расширение WGSL fragment_depth. Режимы less и greater позволяют явно описать отношение выходной глубины к интерполированной. Это даёт GPU информацию для сохранения ранней проверки глубины.

Наличие расширения проверяется через navigator.gpu.wgslLanguageFeatures. В коде шейдера автор рекомендует явно указать requires fragment_depth;.

Это возможность для конкретного графического алгоритма. Перед использованием нужны проверка поддержки и замеры на целевых устройствах.
🔥2
Как Next.js разобрал полторы тысячи старых issues

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

Команда Next.js создала исследовательского агента `closability`. В отдельной песочнице он читает обсуждение, ищет связанные изменения и при необходимости запускает воспроизведение на разных версиях фреймворка.

На выходе — заключение со ссылками на доказательства. Агент не может сам комментировать, закрывать issues или отправлять код; результаты проверяют мейнтейнеры.

За описанный период в репозитории закрыли 1462 отчёта, включая часть вне этого разбора. Среди причин были уже внесённые исправления, дубликаты и ожидаемое поведение. Это уборка и проверка backlog, а не 1462 новых исправления ошибок.
❤3
Как назвать компонент, чтобы команда понимала одно и то же

Box почти ничего не говорит о назначении. Название по цвету или месту на экране быстро устаревает, когда компонент переносят или меняют тему.

В подборке Виталия Фридмана собраны подходы и справочники для названий компонентов, классов, цветов и дизайн-токенов.

Для интерфейсных элементов есть Component Gallery: примеры из реальных дизайн-систем и альтернативные названия одного компонента. Для классов и функций — Classnames со словами, сгруппированными по поведению, порядку и связям.

Общая рекомендация к именам: понятная структура, конкретный смысл и знакомый команде словарь. Для названий пользовательских функций автор советует сначала узнать, какими словами люди сами описывают задачу и ожидаемый результат.
🔥5❤1
Горячие клавиши для демо можно показывать прямо во вкладке

Системная утилита выводит нажатия поверх рабочего стола. Но при демонстрации только одной вкладки зрители могут не увидеть этот слой.

Брамус сделал веб-компонент `<show-keystrokes>`. Он рисует сочетания клавиш внутри самой страницы, по умолчанию показывая горячие клавиши и навигационные кнопки, без обычного набора текста.

Всплывающий слой использует Popover API, поэтому не прячется за соседними элементами. CSS Anchor Positioning размещает его в углу или рядом с курсором и помогает переворачивать расположение у края окна.

Есть настройки оформления, режим всех нажатий, bookmarklet и расширение для подключения на чужих сайтах. При записи демонстрации полезно проверить, какой режим включён, прежде чем вводить данные.
🔥2
Как отправить форму из JavaScript с проверкой полей

Если вызвать form.submit(), форма уйдёт без обычной проверки полей и события submit. Это легко пропустить, когда отправка запускается из отдельной кнопки или после другого действия в интерфейсе.

form.requestSubmit() запускает сценарий отправки через submit-кнопку: браузер проверяет ограничения полей и при успешной проверке вызывает submit. Можно передать конкретную кнопку. Она должна принадлежать форме, а её form*-атрибуты могут переопределить параметры отправки.

Есть оговорка: novalidate у формы и formnovalidate у кнопки меняют поведение проверки. И клиентская валидация всё равно не заменяет серверную. 📎 Разница между двумя методами в MDN.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍1
scrollbar-gutter убирает сдвиг при появлении скроллбара

Список получил ещё несколько строк, появилась полоса прокрутки, и контент немного уехал в сторону. С классическим скроллбаром это происходит потому, что он занимает часть ширины контейнера.

scrollbar-gutter: stable резервирует для него место заранее, даже когда переполнения ещё нет. Это работает при overflow: auto, scroll или hidden. Если нужна симметрия, stable both-edges добавляет такой же отступ у противоположного края по строчной оси.

Свойство управляет местом, а не оформлением полосы. При overlay-скроллбарах, которые лежат поверх контента, резерв не создаётся. Поэтому на разных ОС результат будет отличаться, а старые браузеры стоит проверить отдельно. 📎 Примеры обоих режимов в MDN.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Forwarded from Нейроканал
Две критические уязвимости в PHP, обновляйтесь срочно. Специально собранными HTTP-запросами без логина можно выполнить на сервере любой код с правами PHP-воркера. Рабочий взлом уже показали на WordPress, Drupal, Joomla, Laravel, Symfony, Nextcloud, Magento и phpMyAdmin.

Исправления вышли в PHP 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Для 8.1 и старше релизов не будет: есть минимальные патчи к исходникам 7.4, 8.0 и 8.1 и пакеты от дистрибутивов и LTS-поставщиков. Уязвимые пути тянутся с PHP 5.4, сильнее всего под ударом Apache с mod_php, но FPM тоже уязвим.

Если обновиться прямо сейчас нельзя, команда PHP советует задать session.upload_progress.enabled=0 в php.ini или конфиге пула, на 8.5 ещё fatal_error_backtraces=0, и перезапустить все воркеры. Против второй ошибки снизить post_max_size и ограничить на прокси размер и число частей запроса, включая запросы без Content-Length. Это только снижает риск.

Детали утекли за день до релиза, и атаки уже идут: Cloudflare видит попытки эксплуатации и включила правила WAF даже на бесплатном тарифе. Wiz советует искать в логах необычные multipart-запросы, после которых идут ошибки лимита памяти или серии ответов 500. И проверьте бэкапы.

Нашли уязвимости с помощью ИИ: Calif в программе OpenAI Patch the Planet с GPT-5.6 Sol и независимо Wiz с Gemini 4 Argon и GPT-5.6 Sol. Подробности и инструкции на официальном сайте PHP.

@neuro_channel
🔥6❤2
Knip ищет код, который больше никто не использует

Удалили экран, а его зависимости и вспомогательные файлы остались в проекте. Найти их поиском по одному имени трудно: экспорт может ссылаться на другой экспорт, а точка входа находиться в конфигурации инструмента.

Knip проверяет JavaScript- и TypeScript-проект целиком и ищет неиспользуемые файлы, экспорты и зависимости. Анализ начинается с точек входа. Плагины помогают учитывать устройство проекта и то, как файлы подключают фреймворки, сборщики и тестовые инструменты.

Отчёт стоит использовать как список кандидатов на уборку. Перед удалением проверьте точки входа и неявное использование, которое анализатор мог не учесть. Само попадание в список ещё не доказывает, что файл можно безопасно стереть. 📎 Репозиторий Knip и документация.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
Откуда берётся цикл в ResizeObserver

ResizeObserver следит за размерами элемента, а не только окна. Если в его callback увеличить ширину того же элемента, изменение может вызвать следующее уведомление. Получается цикл, который сам не закончится.

Браузер переносит часть уведомлений на следующий кадр и сообщает ResizeObserver loop completed with undelivered notifications. Это защита от зависания браузера, а не исправление логики. Правило «при каждом уведомлении добавить ещё 10 пикселей» продолжит увеличивать элемент.

Проверьте, есть ли у изменения конечное состояние. Например, можно хранить ожидаемый размер и не задавать его повторно, когда элемент уже до него дошёл. Один requestAnimationFrame() лишь переносит работу и не устраняет бесконечное изменение. 📎 Разбор ошибок наблюдения в MDN.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Почему многоточие не спасает длинное имя во flex-строке

У имени уже стоят white-space: nowrap, overflow: hidden и text-overflow: ellipsis, но строка всё равно растягивается и выталкивает соседнюю кнопку. Проверять нужно не только сам текст.

В примере Ахмада Шадида заголовок лежит внутри .user__meta, а flex-элементом является именно эта обёртка. Её автоматическая минимальная ширина мешает сжатию. Автор задаёт min-width: 0 на .user__meta, оставляя свойства обрезки на заголовке.

Так контейнеру разрешают уменьшиться, а тексту задают способ показать нехватку места. Это разные задачи. Если полное имя важно для выбора пользователя, вместо обрезки может понадобиться перенос. 📎 Разбор с HTML и CSS показывает именно этот случай.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2❤1
Что проверять перед обработкой postMessage от iframe

Сообщение от встроенного виджета не становится доверенным только потому, что пришло через postMessage(). Страница должна проверить, кто его прислал и что именно предлагается сделать.

На отправке задайте точный targetOrigin, если адрес получателя известен: со схемой, хостом и нужным портом. На приёме сравните event.origin с ожидаемым origin. Если важен конкретный iframe, проверьте и event.source. Это помогает отличить нужное окно от других отправителей.

После этого проверьте структуру и допустимые значения event.data. Правильный origin не гарантирует корректность содержимого. И сохранённая ссылка на окно не гарантирует, что оно всё ещё открыто на прежнем адресе. 📎 Правила безопасного обмена в MDN.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2