.anchor--one { anchor-name: --a1; }
.anchor--two { anchor-name: --a2; }
.route--one {
position: absolute;
left: anchor(--a1 right);
right: anchor(--a2 left);
top: anchor(--a1 center);
bottom: anchor(--a2 center);
}
В фон кладём SVG с диагональю и background-size: 100% 100%. В самом SVG нужен preserveAspectRatio="none", иначе линия не растянется по обеим осям.
👉 @seniorFrontSenior Front - канал для front-end программистов, здесь есть много всего про CSS3, Javascript, Html5, Angular, React, видео / статьи / курсы Админ - @antshater, Реклама - @seniorFrontPromo
23 800подписчиков сейчас
Публикации всего: 67
🔗 Линия между двумя блоками без JavaScript
Линия между двумя карточками сама тянется за ними, когда они двигаются. Скрипт для расчёта координат не нужен.
Это CSS Anchor Positioning: элемент с anchor-name становится якорем, а блок с position: absolute привязывает к нему свои стороны через anchor(), даже при разных родителях.
Главный трюк: привязать противоположные стороны блока к двум разным якорям, и он растянется между ними:
🔍 Почему overflow: hidden не удерживает размытие
Свойство backdrop-filter: blur() размывает всё, что видно сквозь полупрозрачный элемент. Так делают эффект матового стекла. Снимок фона браузер берёт из готовой GPU-текстуры (compositing layer), а не из DOM. Кто чей родитель, ему неважно.
В статье есть живой пример. Карточки с blur(70px) лежат в scroll-контейнере с overflow: hidden, а снаружи стоит яркая кнопка PLAY. Карточка подъезжает к кнопке ближе чем на 70px и начинает светиться её цветом.
Дело в том, что overflow: hidden обрезает на этапе paint, а размытие работает позже, на этапе composite. Помогает
clip-path: inset(0) на контейнере: автор называет его единственным надёжным способом.
Только помните, что clip-path обрежет всё содержимое контейнера, включая дочерние элементы, которые выходят за его край.
В статье ещё три бага в Safari и на iPhone и разбор, почему большой радиус blur так дорого обходится GPU.
👉 @seniorFront🔑 Обработчик postMessage без проверок слушается кого угодно
Виджет в iframe (комментарии, форма оплаты) не может сам растянуться на странице. Поэтому он шлёт родителю сообщение через postMessage, а родитель в обработчике message выставляет iframe новую высоту.
Подвох в том, что браузер доставит сообщение от любого окна, у которого есть ссылка на ваше. Чужая страница одной строкой пришлёт
{ type: 'resize', height: 1 }, и виджет схлопнется до одного пикселя.
Спасает строгое сравнение event.origin с ожидаемым адресом. Это поле заполняет сам браузер, и отправитель не может его подделать.
if (event.origin !== WIDGET_ORIGIN) return;Но origin говорит, с какого сайта пришло сообщение, а не из какого окна. Два iframe с одного домена пройдут проверку оба, и сообщение от одного изменит размер другого. Как это закрыть через
event.source и что ещё проверить в самих данных (вроде height: 1e9), автор показывает на живых демо с тремя атаками.
👉 @seniorFront📐 Как заменить CSS progress(), пока его поддерживают не везде
Функция progress() показывает, где значение лежит между двумя границами, и возвращает число от 0 до 1. Формула простая: (значение - начало) / (конец - начало).
Но поделить 180px на 880px и получить просто число умеют не все браузеры: Firefox, например, пока нет. Выручает tan(atan2()). Функция atan2() по сути сама делит первый аргумент на второй, а tan() отдаёт обычное число без единиц.
--progress: tan(atan2(500px - 320px, 1200px - 320px));Так мы узнаём, где 500px между 320px и 1200px. Чтобы результат не выходил за пределы от 0 до 1, как у progress(), оберните его в clamp(). С разными единицами, например vw и px, трюк кроссбраузерно не сработает. Зарегистрируйте ширину экрана через @property как <length>, и браузер сам переведёт её в пиксели. Как быть, если границы заданы в rem, и какой вариант выбрать под ваши единицы, автор разбирает в статье. 👉 @seniorFront
📜 Страница скроллится, а window.scrollY показывает 0
У каждой страницы есть главный контейнер прокрутки, root scroller. Только он получает восстановление позиции при возврате «назад», прокрутку пробелом и стрелками, сворачивание адресной строки на телефоне.
Потерять его легко. Вот частая комбинация:
html,
body {
height: 100%;
overflow-x: hidden;
}
Из-за overflow-x: hidden по вертикали у body получается auto. А height: 100% делает body ровно в высоту экрана. Теперь прокручивается body, а не страница. Внешне всё как раньше, ошибок нет.
Проверить просто: прокрутите вниз и выполните в консоли window.scrollY. Ноль значит, что скроллится что-то другое.
Вложенные контейнеры прокрутки сами по себе нормальны, например для сайдбара или чата. Проблема, только когда такой контейнер занимает весь экран.
В статье разобрано, как сделать липкую шапку, футер внизу и блокировку прокрутки под модалкой, не теряя root scroller.
👉 @seniorFront✨ Одна и та же CSS-переменная может дать 1, а может 2
Кастомные свойства вроде --index по умолчанию хранятся как кусок текста. Вычисляется он там, где переменную подставили через var(), а не там, где объявили.
Пример Джейка Арчибальда. У второго div задано --index: sibling-index() (номер элемента среди соседей, с единицы). Его первый ребёнок, абзац, получает scale: var(--index). Масштаб будет 1: функция считается уже для абзаца.
Теперь зарегистрируем свойство с типом:
@property --index { syntax: '<number>'; inherits: true; initial-value: 0;}
Значение вычислится прямо на div и станет числом 2, абзац увеличится вдвое. С em, lh и единицами контейнерных запросов то же правило.
Но var() внутри значения подставляется сразу при любом типе. Если в --index есть var(--multiplier), переопределять --multiplier у ребёнка бесполезно.
А что при этом происходит с URL из разных таблиц стилей, разобрано в статье.
👉 @seniorFront🎉 iframe, который сам подстраивается под содержимое
Обычно у <iframe> фиксированный размер. Встроенная форма или виджет комментариев выросли, и появляется полоса прокрутки.
В Chrome 154 фрейм умеет брать размер из встроенного документа. Нужно согласие обеих сторон. Внешняя страница задаёт фрейму свойство frame-sizing:
/* In styles.css for index.html */
iframe {
frame-sizing: content-height;
width: 100%;
}
А документ внутри фрейма кладёт в head мета-тег responsive-embedded-sizing. Его параметр allow-origins ограничивает, каким сайтам можно сообщать размер.
Размер передаётся после загрузки. Если содержимое изменилось, документ вызывает window.requestResize().
Пока это есть только в Chrome 154, в Firefox и Safari поддержки нет.
В статье есть демо: многошаговая форма во фрейме, которая меняет размер на каждом шаге без единой полосы прокрутки.
👉 @seniorFront
❤ 3 🔥 1
Перейти к публикации →
⚽ Одна обёртка, две стороны сетки: турнирная таблица на subgrid
Турнирную сетку плей-офф рисуют симметрично: часть пар раунда слева, часть справа. На сайте FIFA каждая такая половина свёрстана отдельным div, и разметка просто повторяет картинку.
Есть вариант чище. Раунд остаётся одним элементом с детьми .start и .end. Он растягивается на всю общую сетку .rounds и через subgrid получает её колонки и строки:
.round-of-8 {
grid-column: 1 / -1;
grid-row: 1 / -1;
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
Теперь .start встаёт в первую колонку, а .end в последнюю, хотя в DOM они соседи.
Подвох в выравнивании: align-items: center не ставит матчи соседних раундов друг напротив друга. Помогает flex: 1 у каждого матча внутри flex-колонок .start и .end, чтобы матчи делили высоту поровну.
А в статье видно, как та же разметка на узком экране перестраивается так, что каждый раунд занимает одну колонку.
👉 @seniorFront3 дня бесплатного обучения во Frontend-разработке!
Вместо лекций пройди симуляцию настоящего первого заказа. Скучных уроков не будет. Их заменяет сюжет, где ты уже начинающий Frontend-разработчик и у тебя есть первый клиент.
За 3 дня ты:
- Получишь первую задачу от «клиента» стоимостью 10 000 руб. и соберёшь структуру сайта на HTML;
- Оформишь внешний вид сайта по пожеланиям клиента с помощью CSS;
- Добавишь на страницу интерактивность с JavaScript — нажал → сработало;
- Внесёшь финальную правку и сдашь готовый проект;
- Заберёшь сайт себе. Можно оформить как кейс в портфолио.
С нас — задача, подсказки на каждом шаге и разбор, если что-то не получается.
С тебя — 20–30 минут в день.
👉 Начать бесплатно
К концу третьего дня у тебя будет не абстрактное «прошёл курс», а готовый проект и понимание, как зарабатываются деньги на удалёнке в IT.
✨ Как не оставить один пункт меню одного на новой строке
Когда во флексбоксе включён перенос (flex-wrap: wrap), элементы уходят на следующую строку, как только перестают помещаться. Бывает, что там оказывается ровно один: пять пунктов меню сверху и одинокий «Speaking» снизу.
Обычно это чинят медиазапросом, но он легко ломается, стоит поменять текст. Новое значение flex-wrap: balance делает иначе: браузер сам раскладывает элементы по строкам ровнее, без расчётов ширины.
.channels {
display: flex;
flex-wrap: balance;
justify-content: center;
gap: 1rem;
}
Для сравнения: тот же ряд иконок соцсетей без balance приходится выравнивать обходными путями, от контейнерных запросов до display: contents. Все четыре варианта из разбора заметно длиннее.
Оговорка: на момент публикации это работает только в Chrome, начиная со 150-й версии.
Рядом появилось ещё свойство flex-line-count, которое задаёт минимальное число строк, и на нём получается даже экспериментальная masonry-раскладка.
👉 @seniorFrontИстория названий канала
14.08.2026
название
SeniorFront - javascript, html, css
→
Senior Frontend - javascript, html, css
Дата — момент, когда изменение заметил наш обход.