Frontend Interview - собеседования по Javascript / Html / Css
10.3K subscribers
2.08K photos
117 videos
320 files
493 links
Канал для подготовки к собеседованиям по фронтенду

Админ, сотрудничество, реклама: @seniorFrontPromo, @maria_seniorfront

Купить рекламу: https://telega.in/c/frontendinterview

Канал в реестре РКН:
https://rknn.link/su
Download Telegram
🧮 Поле ввода, в которое можно вписать формулу

Часто число для формы сначала надо посчитать. С обычным <input> приходится бегать в калькулятор и обратно. А позже в поле виден только итог, и непонятно, откуда он взялся.

Bramus сделал для этого веб-компонент <calc-input>. Пишешь (2 + 3) * 4, уходишь из поля, и там появляется 20. Возвращаешь фокус, и снова видна формула, её можно проверить или поправить.

Считает компонент своим парсером, без eval(). Он понимает обычные операторы, скобки и функции вроде sqrt, round, min, max. Внутри лежат обычные <input>, поэтому отправка формы и валидация работают как есть. С недописанной формулой вроде 2 + форма не отправится.

Учтите, что по умолчанию в поле с вашим name уходит сама формула «2 + 3», а не 5. Чтобы сервер получил число, нужен атрибут submit="result".

Как устроены три поля внутри и почему стили на самом теге сразу применяются к ним, Bramus показывает в статье.

👉 @seniorFront
❤1
✨ CSS может заметить, что элементы вот-вот столкнутся

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

Между декором и секцией через anchor positioning растягивается невидимый элемент .measure. Внутри у него псевдоэлемент шириной 20px и overflow-x: auto. Когда зазор меньше 20px, .measure переполняется.

Само переполнение запускает scroll-driven анимацию, прокручивать ничего не нужно. Анимация лишь ставит --touching: 1, а style container query прячет декор:

.decor {
@container style(--touching: 1) {
opacity: 0;
}
}


Работает только в браузерах, где есть и scroll-driven анимации, и anchor positioning, так что это улучшение поверх обычной вёрстки.

В статье есть интерактивные демо, где можно потянуть границу и поймать момент срабатывания.

👉 @seniorFront
❤1
✨ Скроллбар, который следит за прокруткой без JavaScript

Свой скроллбар обычно рисуют так: нативный прячут, а размер и положение ползунка считают в JS на каждое событие scroll. Это дорого: scroll летит много раз в секунду, а чтение scrollHeight может вызвать reflow.

Разработчик библиотеки Taiga UI отдал эту работу CSS через scroll-driven animations. Их прогресс зависит не от времени, а от прокрутки контейнера.

Хитрее всего с высотой ползунка. Анимации его краёв растягивают на высоту контейнера (100cqb) за конец прокрутки, и в крайней точке они замирают ровно там, где нужно:

.bar {
animation-range: 0% calc(100% + 100cqb), calc(0% - 100cqb) 100%;
animation-fill-mode: both;
}


JS остаётся только для перетаскивания ползунка мышью.

Учтите, что на момент статьи Firefox умел это лишь в Nightly, поэтому в Taiga UI новая схема включается только там, где браузер её поддерживает.

Отдельно красиво решено, как прибить ползунки к краю контейнера: через anchor positioning.

👉 @seniorFront
🧩 Как сделать, чтобы фоновый узор не обрезался снизу

У секции повторяющийся фоновый узор, плитка 52×44px. Высота блока зависит от текста, поэтому нижний ряд плиток часто обрезается на середине.

Можно поставить background-repeat: round. Но тогда браузер сжимает или растягивает саму плитку, чтобы она уместилась целиком.

Решение аккуратнее: взять автоматическую высоту через calc-size() и округлить её функцией round() до кратного высоте плитки. Высота плитки лежит в переменной --tile-height.

.section {
height: calc-size(auto, round(up, size, var(--tile-height)));
}


Выглядит как фиксированная высота, но работает скорее как min-height. Блок по-прежнему подстраивается под контент, просто его высота всегда кратна высоте плитки, и узор не режется.

Оговорка: на момент написания статьи это работает только в Chrome.

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

👉 @seniorFront
❤1
✨ Рамка, которая рисует себя сама, на чистом CSS

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

Это обходится так: регистрируем свою переменную через @property и указываем её тип. Такую переменную браузер уже плавно меняет:

@property --p {
syntax: "<percentage>";
initial-value: 0%;
inherits: false;
}


Дальше она встаёт в градиент рамки: linear-gradient(-45deg, red var(--p), transparent 0%). Пока --p равна 0%, рамка прозрачная. При наведении --p становится 100%, красный заполняет рамку, и кажется, что её рисуют на глазах.

Есть подвох: border-image не изгибается по форме элемента, так что скруглённые углы он не повторит.

В статье тот же приём крутят дальше: conic-gradient, анимация border-image-slice и ещё куча вариаций.

👍 - если было полезно

👉 @frontendInterview
❤1👍1
🚀 Предзагрузка, которая грузит не те данные

В TanStack Router у маршрута есть loader: он запускает запрос ещё до рендера, а компонент забирает готовые данные из кеша TanStack Query. Но параметры запроса тогда описаны дважды, и если они разойдутся, ошибки никто не покажет.

Пример из статьи. В дашборд добавили ?asOf=дата, но только в компоненте. По ссылке loader грузит данные «на сегодня», а компонент потом запрашивает снимок заново. Лишний запрос и лишнее ожидание.

Автор предлагает класть queryOptions в контекст маршрута. Их создаёт одна функция context, а loader и компонент через useRouteContext() берут один и тот же объект. Разойтись им просто негде.

Учтите, что функция context на момент статьи была новой и не описанной в документации.

В статье ещё о том, как контекст наследуют дочерние маршруты и почему лишних ререндеров не будет.

👍 - если было полезно

👉 @frontendInterview
🧩 Один инпут в Angular для строки, функции, шаблона или компонента

Когда компонент принимает кастомный контент, приходится заранее решать: хватит строки или нужен TemplateRef? Потом тип проверяют через @if и ветвят шаблон.

Библиотека Polymorpheus от команды Taiga UI убирает этот выбор. Директива *polymorpheusOutlet одинаково отрисует любой из четырёх вариантов в переданном контексте:

<ng-container *polymorpheusOutlet="content as primitive; context: { $implicit: user }">
{{ primitive }}
</ng-container>


Строка или результат функции попадает в primitive.

Пример с тултипом: обычно в нём просто текст. Когда понадобится ссылка или кнопка, пользователь передаст шаблон, и API тултипа переделывать не придётся.

Оговорка: функцию от конструктора компонента не отличить, поэтому компонент оборачивают в PolymorpheusComponent.

А в статье ещё и трюк, как сделать иконку, которую можно задать просто по имени или целым шаблоном.

👍 - если было полезно

👉 @frontendInterview
❤2
✨ Любой кусок страницы в окне поверх всех окон

Обычный Picture-in-Picture выносит в плавающее окошко только видео. Оно остаётся на экране, даже если переключиться на другую вкладку или программу.

Document Picture-in-Picture API делает то же самое с любым HTML: тикер акций, чат, список дел. По сути, получается веб-виджет.

Окно создаёт requestWindow(), и внутри у него свой пустой document. В статье туда клонируют тикер:

/* Select the component */
const stock = document.querySelector("#stock");

/* Clone the component and append it to the DPIP <body> */
DPIP.document.body.append(stock.cloneNode(true));


Стили сами не переедут, их копируют в head окна отдельно. А поправить вид только внутри окна поможет @media (display-mode: picture-in-picture).

Учтите, что API работает только на десктопе, а Safari на момент статьи его не поддерживал.

В статье есть полный код кнопки и разбор опций окна.

👍 - если было полезно

👉 @frontendInterview
👍1
🎯 Тултип, который сам перепрыгивает вниз, без JavaScript

Подсказка над кнопкой проста, пока кнопка не окажется у верхнего края экрана: подсказку обрезает. Обычно это чинили на JavaScript, и код выходил запутанным.

В CSS для этого есть Anchor Positioning API. Кнопке даём имя через anchor-name: --example-anchor, а подсказка привязывается к ней:

.target {
position: fixed;
position-anchor: --example-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}


position-area: top ставит подсказку над кнопкой. Если там не хватает места, flip-block переворачивает её на другую сторону, вниз.

Подвох: с position: absolute переворот не сработает. Браузер ловит выход за содержащий блок, а у absolute он обычно прокручивается вместе с элементом. У fixed этот блок равен окну, поэтому край замечается.

Дальше в статье: как развернуть стрелочку тултипа и чем подстраховать старые браузеры.

👍 - если было полезно

👉 @frontendInterview
🌗 Переключателю тёмной темы хватит двух положений

Обычно на сайтах три варианта: «Системная», «Светлая», «Тёмная». Но системная тема в итоге всё равно светлая или тёмная. Поэтому один из трёх вариантов ничего видимого не делает: страница остаётся прежней.

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

Зак Лезерман поставил такой тумблер в подвал своего сайта. Режим, совпадающий с системным, подписан (auto):
Dark (auto) [Toggle] Light

Есть оговорка. Bramus в критике подхода указал на особый случай: пользователей, у которых системная тема переключается сама. Зак и сам из них, но считает простоту важнее. Это его личная оценка.

А ещё Зак уже выложил тумблер отдельным веб-компонентом Solar Eclipse Toggle.

👍 - если было полезно

👉 @frontendInterview
👍1
🎨 Перекрасить SVG-иконку внутри <img> прямо из CSS

SVG-иконку в <img> браузер кеширует, у неё есть alt и loading="lazy". Но поменять fill отдельной фигуры внутри неё из CSS нельзя. Поэтому иконки чаще вставляют инлайном и раздувают DOM.

Экспериментальная возможность CSS под названием Linked Parameters предлагает другой путь. В SVG-файле цвет берётся из переменной: fill="env(--color, #c1f07c)". А страница передаёт значение снаружи:

img {
link-parameters: param(--color, #ff8052);
}


Браузер без поддержки просто возьмёт запасной #c1f07c, и иконка не сломается.

Оговорка: пока это работает только за флагами в Firefox Nightly и Safari Technology Preview. Когда появится во всех браузерах, неизвестно.

Если дойдёт, иконки можно будет держать отдельными кешируемыми файлами и красить их из CSS одной строкой.

👍 - если было полезно

👉 @frontendInterview
👍2