Логово верстальщика
7.97K subscribers
1.17K photos
68 videos
4 files
2.01K links
Логово верстальщиков: HTML, CSS, JavaScript, практики современной верстки, вайбкодинг и использование ИИ в разработке.

Личный блог автора - @just_genych
По вопросам рекламы или разработки: @g_abashkin
Download Telegram
Тест зелёный, фича сломана — в живом проекте на TypeScript и PostgreSQL разобрали семь случаев, когда проверка совпала по неверной причине. Суть проблемы: тест смотрит на форму, а не на эффект. Например, имя поля есть в файле, но в разметку оно так и не попало.

Среди разобранных ситуаций: CSS-фикс сломал прокрутку колесом мыши, а диагностика проверила defaultPrevented вместо самой прокрутки; подстрока совпала с другой подстрокой; комментарий в SQL прочитался как код; метка источника обнулила отчёт, и ноль интерпретировали как «людей нет».

В статье — код, разбор каждой ошибки и результаты мутационного прогона на 13 400 мутантах. Читать далее

👉 Логово Верстальщика
Please open Telegram to view this post
VIEW IN TELEGRAM
⁣CSS-изоляция: почему @scope лучше, чем Shadow DOM и «БЭМ-переусложнение»

Когда речь заходит об изоляции стилей компонента, обычно вспоминают Shadow DOM или жёсткую методологию БЭМ. Но у обоих подходов есть боль: Shadow DOM — это тяжеловесная архитектура и потеря глобальных токенов, а БЭМ часто вырождается в «модификатор на модификаторе» и классы уровня block__element--modifier--state.

В 2023–2024 все стабильные браузеры приняли CSS @scope. Он решает ровно ту задачу, ради которой раньше придумывали сложные обёртки.

Синтаксис:

@scope (.card) {
:scope { border: 1px solid #d0d7de; }
.title { font-weight: 600; }
.button { padding: 8px 12px; }
}


Вся магия: селекторы внутри @scope применяются только к элементам внутри .card. При этом сами классы — обычные, без card__title, без завязки на структуру.

Можно ограничить скоуп ещё точнее — до конкретной вложенности:

@scope (.media) to (.media__content) {
img { border-radius: 8px; }
}


Здесь стили достаются только элементам между .media и .media__content.

Чем это удобно в реальном проекте:

- не нужен Shadow DOM ради изоляции одного карточного блока;
- не нужно на каждый чих придумывать новый БЭМ-элемент;
- CSS остаётся плоским и предсказуемым;
- можно аккуратно расширять стили библиотечного компонента без риска зацепить чужое.

Почему это не «ещё один препроцессор»:

@scope — нативная фича CSS. В отличие от вложенности в SCSS, он создаёт настоящую границу для каскада: селекторы из внешнего мира применяются к внутрям скоупа, но селекторы внутри скоупа не «утекают» наружу. Именно это ломало всю игру ещё вчера.

БЭМ не отменяется полностью — но там, где раньше нужен был блок с корнем-обёрткой, теперь достаточно легкочитаемого @scope. Компонент становится по-настоящему локальным без лишней разметки и без проклятия специфичности.

Важный нюанс: @scope управляет каскадом, но не специфичностью. Если снаружи написан селектор с #id или ультра-специфичный !important, он всё равно перебьёт скоуп — как и любое другое CSS-правило. Поэтому внутрь скоупа лучше не класть слишком сложные селекторы, а на верхнем уровне не злоупотреблять !important.

Кроссбраузерность сегодня — зелёная: все современные Chrome, Firefox, Safari поддерживают @scope без флагов.

Куда копать дальше:
- CSS Scope Specification — https://drafts.csswg.org/css-cascade-6/
- MDN: @scope — https://developer.mozilla.org/en-US/docs/Web/CSS/@scope

Коротко: если вам нужна чистая локальность стилей «здесь и сейчас» — берите @scope. Shadow DOM оставьте для настоящих web components, а БЭМ — для крупных переиспользуемых систем, где скоуп будет лишним уровнем.
👍5🔥2
OpenAI выкатила GPT-6 Astra — нового флагмана, который по первым цифрам делает прошлое поколение похожим на динозавра. Бенчмарки у модели просто огонь:
- Terminal-Bench 4.0: 57,7% (у Fable 5.1 — 55,8%, у GPT-5.6 Sol вообще жалкие 37,3%);
- Terminal-Bench Science: 64,6% против 52,6% у Fable 5.1;
- ARC-AGI-3: 99,9%;
- ExploitBench: 100%.

Цена в API — $10 за миллион входных токенов и $50 за миллион выходных. Fast mode, который шустрит до 2,5 раза быстрее, обойдётся в два раза дороже.

Пока Astra дали пощупать только избранным организациям. Но в ближайшие дни обещают раскатать её и на платных пользователей.

Теперь осталось только дождаться, когда доступ откроют всем, и посмотреть, что покажут честные независимые тесты 🥹
https://openai.com/index/gpt-6-astra/
Будете в Питере - сохраняйте

Атмосферная квартира у метро «Петроградская»: инди-артхаус интерьер, дух старого Петербурга и проектор для уютных вечеров.

Подойдёт для отдыха и удалённой работы.

Посуточная аренда:
https://t.me/FlatErmitage
❤1
💻 Хакер похитил с помощью агента API-ключ и сжег кредитов на $600 000!

Исследователь METR навайбкодил приложение для управления ИИ-агентами. Из-за бага интерфейс на несколько дней оказался открыт всему интернету, хакер нашел его и попросил агента раскрыть API-ключ. Последующие три недели гений просто тратил кредиты на ИИ-модели.

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

✖️ xCode Journal
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣 Должно быть вот так:
«Я создал этот баг, Гендальф
3000 лет назад»


💥 xCode Journal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4
⁣Есть два мощных CSS-механизма, которые позволяют анимировать появление и исчезновение попапов, диалогов и вообще любых элементов с display: none без единой строчки JS. Речь про @starting-style и transition-behavior: allow-discrete.

---

## Проблема
Раньше нельзя было плавно показать попап, который скрыт через display: none (стандарт для popover/dialog в закрытом состоянии). Браузер не мог найти стартовое состояние для перехода. Результат — либо мгновенное появление, либо костыли с JS и реквайрами.

## Решение

**Шаг 1. display и overlay участвуют в transition**

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

transition-behavior: allow-discrete;


Если указать это в transition для display, то браузер «перекидывает» значение с none на block в **начале** анимации появления и в **конце** анимации исчезновения. Элемент для закрывающегося попапа остаётся видимым до конца анимации, а потом получает display: none.

Для попапов важно ещё и overlay — отключает верхний слой (top layer) только после завершения анимации.

**Шаг 2. @starting-style — стили «до старта»**

Когда браузер переключает display с none, у элемента нет предыдущего состояния, от которого можно анимировать. @starting-style задаёт стартовые стили:

.popover {
opacity: 0;
transform: translateY(-10px);
transition:
opacity 0.3s ease,
transform 0.3s ease,
display 0.3s allow-discrete,
overlay 0.3s allow-discrete;
}

.popover:popover-open {
opacity: 1;
transform: translateY(0);
}

@starting-style {
.popover:popover-open {
opacity: 0;
transform: translateY(-10px);
}
}


## Как это работает

- При открытии: @starting-style мгновенно применяет opacity: 0, затем срабатывает переход к opacity: 1.
- При закрытии: обычные стили возвращают попап к opacity: 0, а display: none и уход из top layer (overlay) применяются только в конце transition.

## Важные нюансы

1. Без allow-discrete display переключится мгновенно, анимация исчезновения не будет.
2. overlay нужно указывать именно для элементов в top layer (popover, dialog). Обычные выпадашки могут обойтись без него.
3. Поддержка: все современные браузеры, включая Safari 17.5+ и Chrome 117+. Работает и для <dialog>, и для [popover].

## Минимальный пример

<button popovertarget="tip">Показать</button>
<div popover id="tip">Подсказка</div>


#tip {
opacity: 0;
transform: scale(0.95);
transition:
opacity 0.2s ease,
transform 0.2s ease,
display 0.2s allow-discrete,
overlay 0.2s allow-discrete;
}

#tip:popover-open {
opacity: 1;
transform: scale(1);
}

@starting-style {
#tip:popover-open {
opacity: 0;
transform: scale(0.95);
}
}


Теперь никакого JS для анимации попапов — только чистый CSS. Удобно, когда нужно скрыть логику анимации из бандла и убрать хрупкие кодушки с анимациями через классы.
⁣Сегодня покажу, как выкинуть JS из связки «скролл + эффекты». Речь про CSS scroll-driven animations — это уже не polyfill, а нативный API в Chrome/Edge/Safari 26+. Два главных героя: scroll() и view(). Поехали.

**Основы**

scroll() привязывает анимацию к прогрессу прокрутки контейнера. Элемент просто крутится/двигается/закрашивается в зависимости от того, сколько пикселей мы проскроллили.

view() привязывает анимацию к появлению элемента во вьюпорте. Элемент «оживает», когда вползает в кадр, и «умирает», когда выходит. И это идеально для параллакса или плавного появления карточек.

Оба механизма работают через animation-timeline, а за точками старта и конца управляет animation-range.

**Прогресс-бар без единой строчки JS**

Классика: полоска сверху показывает, сколько прочитано. Раньше — слушатель скролла и requestAnimationFrame. Теперь — 5 строк CSS:

.progress {
position: fixed;
top: 0; left: 0;
width: 100%; height: 4px;
background: #ff4d00;
transform-origin: left;
animation: scale linear;
animation-timeline: scroll();
}

@keyframes scale {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}


Всё. scroll() без аргументов = отслеживаем скролл ближайшего предка (или корня, если предка-скроллера нет). Анимация идёт ровно от верха страницы до низа.

**Параллакс через view()**

Берём картинку, которая должна двигаться с другой скоростью, пока она на экране. Вместо scroll-слушателя и пересчёта позиций:

.parallax-image {
animation: drift linear;
animation-timeline: view();
animation-range: entry 0% cover 40%;
}

@keyframes drift {
from { transform: translateY(15%); }
to { transform: translateY(-15%); }
}


Поясню значения entry, cover, exit. Палитра простая:
- entry — элемент выезжает снизу/сверху в кадр
- cover — полностью на экране
- exit — покидает вьюпорт

entry 0% cover 40% значит: анимация начинается в момент появления и заканчивается, когда элемент прошёл 40% высоты экрана. За счёт этого картинка «сдвигается» независимо от скорости скролла.

**Важный нюанс: animation-range**

Если у вас контейнер высотой 200%, а анимация должна идти только на середине скролла — играйтесь именно через range. scroll(root) + range: 0% 50% даст эффект, заканчивающийся на половине страницы. Это заменяет кучу логики «если y > X».

**Бонус-фича: animation-timeline: view(block)**

По умолчанию отслеживается ось блока (вертикаль) или инлайна (горизонталь). Можно явно указать view(inline) для горизонтальных слайдеров-каруселей с прокруткой по X. Тоже без JS.

**Что под капотом и поддержка**

Работает только с ключевыми кадрами — CSS-переходы так не умеют. animation-timeline можно комбинировать с обычной animation-duration, но при наличии timeline длительность игнорируется: прогрессом правит скролл.

Поддержка в 2025-м: Chrome 115+, Edge 115+, Safari 26+ (с префиксом -webkit- в iOS 26). Firefox — за флагом, но уже в активной разработке. Для отстающих браузеров это деградирует безболезненно: без поддержки просто не будет анимации.

**Моя рекомендация**

Не пишите свой параллакс через JS, если это обычный маркетинговый лендинг. Нативный scroll-driven API считается на стороне compositor, поэтому дёрганий и микролагов на слабых устройствах меньше, чем при ручном обновлении свойств из JS.

Вывод: добавьте scroll() на прогресс-бар, view() на карточки — почувствуете разницу в скорости вёрстки сразу.
🔥1
Чек-лист: как пробить компанию до собеседования (7 шагов)

«Сначала проверь работодателя, а потом уже вкладывай в него своё время» — так автор выражает главный принцип. Только вот многие, как стадо, валят на интервью без разведки — и в итоге ловят либо разбитые ожидания, либо испорченную трудовую.

Автор собрал чек-лист проверки конторы перед собеседованием. Внутри два блока: база — проверка по открытым интернет-ресурсам, и дополнительно — прогон через реестры и базы. По его мнению, такая разведка — не паранойя, а нормальный способ сэкономить время и нервы.

Читать далее

👉 Логово Верстальщика
Please open Telegram to view this post
VIEW IN TELEGRAM
Казахский ИП-разработчик обходится на 22% дороже. Готовься к такому раскладу

Нашли мидла на бэкенд в Казахстане, обсудили зарплату, всё чинно. Но тут бухгалтер задаёт сакральный вопрос: «ИП или физлицо?» И вот это меняет всё — проект может подорожать на 22%. Разбираемся, откуда ноги растут у этих процентов, почему НДФЛ с казахстанца платить не требуется, а вот агентом по налогам ты остаёшься, и какая фраза в договоре способна превратить сэкономленные деньги в доначисление.

Не воспринимай это как готовый шаблон. Конкретный проект нужно согласовывать с юристом. Исходник: разработчик постоянно живёт в Казахстане, работает там же, в Россию не заезжает.

Читать далее

👉 Логово Верстальщика
Please open Telegram to view this post
VIEW IN TELEGRAM
⁣Зачем нужен overflow: clip, если есть overflow: hidden? 🎯

Когда верстаешь карточку со скруглёнными углами, а дочерний элемент «вылезает» за границы — тень, glow, бегущая строка, фокус-кольцо — первое желание: зарезать лишнее через overflow: hidden.

Но у hidden есть неочевидный побочный эффект: он делает элемент скролл-контейнером.

Это значит:
— содержимое можно программно проскроллить (scrollTop, scrollIntoView);
— браузер резервирует ресурсы на скролл-механику;
— при навигации с клавиатуры скрытый контент может стать «достижимым» скроллом — UX ломается.

Когда тебе нужно лишь обрезать **декоративный** выплеск, а не сделать полноценный скролл-регион — hidden избыточен и вреден.

Решение — overflow: clip.

Он делает ровно одну вещь: жёстко обрезает всё, что выходит за границы бокса, и **не создаёт скролл-контейнер**. Никакого программного скролла, никаких сюрпризов с фокусом.

.card {
overflow: clip;
}


А теперь самое интересное — overflow-clip-margin.

По умолчанию обрезка идёт по padding-краю. Но что, если хочется скруглить контент внутри, а снаружи оставить видимой аккуратную тень? Раньше приходилось делать костыли с врапперами. Теперь можно расширить область видимости:

.card {
overflow: clip;
overflow-clip-margin: 8px;
}


Эти 8px — пространство за пределами бокса, в котором контент продолжает отображаться, а всё, что дальше — обрезается. По сути, визуальная «зона безопасности» для декоративных элементов.

Где реально спасает:
— тени и drop-shadow, которые чуть-чуть выходят за карточку;
— focus ring у кнопок внутри контейнера с обрезкой;
— всплывающие подсказки внутри карточки;
— трансформированные бейджи, наклонённые заголовки, кастомные ленты.

Ещё один нюанс, который часто упускают: при паре overflow-x: visible; overflow-y: hidden браузер молча превращает visible в auto — получаем скролл-контейнер там, где не ждали. С clip такого нет: visible остаётся visible, потому что clip не создаёт scroll container. Это позволяет безопасно комбинировать:

.card {
overflow-x: clip;
overflow-y: visible;
}


Поддержка: все современные браузеры — Chrome 90+, Firefox 81+, Safari 16+. Можно смело использовать, а с фолбэком на hidden для старых — тем более.

Итого: если hidden «на всякий случай» режет всё и создаёт скрытый скролл — clip решает точечно и без побочных эффектов. А overflow-clip-margin даёт тонкую настройку: сколько именно декоративного выплеска оставить на виду.

Источники:
— MDN: overflow — https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
— MDN: overflow-clip-margin — https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-clip-margin
— CSS Overflow Module Level 3 — https://drafts.csswg.org/css-overflow-3/
👍4❤1🔥1
Как мы шторы закрывать учили: стажёрская кухня глазами наставников

Здарова, Хабр! Прошлым летом семеро энтузиастов вкатились на трёхмесячную стажировку в Учебный центр НТЦ «Вулкан». Звучало всё просто, как угол: сделать пульт для управления рулонными шторами в офисном опенспейсе.

Наставники решили не молчать и расказали, как была устроена движуха и как они воевали со стажёрами. А в конце — мешок выводов. Кому надо — сэкономит себе нервы и время, если решит повторить этот трюк или просто впервые сунется в аппаратный проект.

Читать далее

👉 Логово Верстальщика
Please open Telegram to view this post
VIEW IN TELEGRAM
⁣**CSS field-sizing: content — авторазмер полей форм без единого скрипта**

Всё ещё тянете высоту textarea через scrollHeight, строчите обёртки со скрытыми дивами и ResizeObserver? Выкидывайте. В CSS завезли нативное решение для авторазмера элементов форм.

**Как это работает**

Свойство field-sizing говорит браузеру: подгони размер поля под его контент. Значение по умолчанию — fixed (все привычно), нас интересует content.

textarea {
field-sizing: content;

/* без этого textarea схлопнется в точку,
а с длинным текстом улетит в бесконечность */
min-height: 4em;
max-height: 20em;

resize: none; /* ресайз мышью теперь не нужен */
}


Поле растёт при вводе и уменьшается, когда строк стало меньше. Без анимаций layout-сдвигов и обработчиков на каждый keyup.

**Это работает не только с textarea**

Свойство определено для всех элементов форм и подстраивает размер по контенту:

input,
select {
field-sizing: content;
}


- input[type="text"] — ширина подстраивается под введённый текст;
- select — размер подгоняется под выбранную опцию, а не под самую длинную;
- input[type="file"], input[type="number"] — тоже подхватывают.

**Подводные камни**

1. Всегда задавайте min-height или стартовые размеры. Сломанный (или пустой) элемент схлопнется до нуля.
2. Для input по умолчанию задан size, и если не сбросить CSS-ширину, рост незаметен. Элементу нужно «дышать»: никаких width: 100%, если ждёте автоширину.
3. Это свойство — не фича, которая ломает интерфейс, если браузер не поддерживает. Оно просто проигнорируется, и поле останется со стандартным rows, cols и size. Идеально для прогрессивного улучшения.

**Поддержка**

- Chrome / Edge — с 123 версии;
- Firefox — долго был за флагом, проверяйте актуальный статус на caniuse;
- Safari — нет.

Среднестатистический пользователь Chrome уже живёт с этим. Можно смело применять на проектах, где не нужно поддерживать древний Safari.

**Зачем это фронту**

- минус JS-костыли: ни scrollHeight, ни скрытых дублей контента, ни обсерверов;
- скорость: ростом поля управляет браузерный layout, а не перезапись DOM;
- доступность и простота: «коробка» всегда соответствует контенту, в том числе при вставке текста мышью и автозаполнении (на чём часто падают самописные решения).

Берите в работу и потихоньку вычищайте старые наколенки. Ссылку на спецификацию не даю — она и так гуглится за секунду.

#css #forms
👍2
Месяц вайбкодинга с незнакомцами — в КОРУСе подвели итоги ИИ-лаборатории, где студенты месяц разрабатывали реальный продукт для заказчика из бизнес-единицы.

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

Как это было — рассказывают HR, Корпоративный университет, бизнес-единицы и сами стажёры. Читать далее

👉 Логово Верстальщика
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣 Наконец-то батя покажет, как он в детстве ходил в школу за 100 верст

💥 xCode Journal
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩 Нашли репу с десятками практических проектов для прокачки навыков и резюме

Внутри 54 проекта разной сложности по Terraform, Kubernetes, Docker, CI/CD, DevSecOps, AWS, Azure, безопасности и мониторингу.

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

✖️ xCode Journal
Please open Telegram to view this post
VIEW IN TELEGRAM