Code Ready | Frontend
21.5K subscribers
1.35K photos
545 videos
17 files
1.06K links
Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!

Cотрудничество: @energy_c

Реклама на бирже: https://telega.in/channels/code_ready/card

РКН: https://clck.ru/3NJCKs
Download Telegram
📱 CSS-селекторы — специфичность, состояния и структурная выборка элементов!

Шпаргалка по CSS-селекторам: группировка через :is() и :where(), выбор связанных элементов с :has(), исключение через :not(), управление состояниями фокуса с :focus-visible и :focus-within(), определение пустых элементов через :empty и позиционная выборка с :nth-child(). Примеры охватывают специфичность, структуру DOM и стилизацию элементов в зависимости от их состояния.

📣 Code Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15🔥7🤝5👍1
overflow-anchor — управляем сохранением позиции прокрутки при изменении контента!

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

Браузеры используют механизм scroll anchoring, который помогает сохранять видимую позицию при таких изменениях. Но иногда автоматическая компенсация прокрутки мешает логике интерфейса.

Рассмотрим контейнер с сообщениями:
<div class="chat">
<div class="messages">
<!-- сообщения -->
</div>
</div>


Зададим ему ограниченную высоту и вертикальную прокрутку:
.chat {
height: 400px;
overflow-y: auto;
}


Если содержимое выше видимой области изменит размер, браузер может скорректировать scrollTop, чтобы сохранить положение опорного элемента.

Для управления этим механизмом существует CSS-свойство overflow-anchor:
.chat {
overflow-anchor: none;
}


Значение none исключает контейнер и его потомков из выбора опорного элемента для scroll anchoring. При этом прокрутка продолжает работать, а размеры содержимого могут изменяться как обычно.

По умолчанию используется auto:
.chat {
overflow-anchor: auto;
}


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

Чат, в котором новые сообщения добавляются в конец списка:
const chat = document.querySelector('.chat');
const messages = document.querySelector('.messages');

function appendMessage(text) {
const message = document.createElement('div');
message.textContent = text;

messages.append(message);
}


Если требуется самостоятельно управлять прокруткой, можно отключить scroll anchoring:
.chat {
height: 400px;
overflow-y: auto;
overflow-anchor: none;
}


Например, после добавления сообщения можно прокрутить контейнер вниз:
chat.scrollTop = chat.scrollHeight;


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

Поэтому лучше проверять положение до добавления сообщения:
function appendMessage(text) {
const distanceToBottom =
chat.scrollHeight -
chat.scrollTop -
chat.clientHeight;

const shouldScroll = distanceToBottom <= 20;

const message = document.createElement('div');
message.textContent = text;

messages.append(message);

if (shouldScroll) {
chat.scrollTop = chat.scrollHeight;
}
}


Теперь контейнер прокручивается вниз только тогда, когда пользователь уже находился рядом с нижней границей. Здесь overflow-anchor: none отключает автоматическую компенсацию, а js управляет необходимой позицией.

Если у родителя установлено overflow-anchor: none, потомки не могут повторно включить scroll anchoring:
.container {
overflow-anchor: none;
}

.container .item {
overflow-anchor: auto;
}


В данном случае .item всё равно остаётся внутри исключённой области.

Также scroll anchoring не гарантирует компенсацию любых изменений. А поддержка overflow-anchor в Safari ограничена, поэтому для строго определённого поведения лучше использовать js.

🔥 overflow-anchor позволяет управлять участием элементов в scroll anchoring. Свойство полезно для чатов, лент и динамических списков, где положение прокрутки контролируется логикой приложения.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤8🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ frontend-interview-notes — большая подборка материалов для разработчиков!

В репозитории собраны заметки по ключевым темам веб-разработки, которые помогают систематизировать знания и разобраться в вопросах, встречающихся на технических интервью. Удобно использовать для повторения теории, самопроверки и подготовки к собеседованию.

Оставляю ссылочку: GitHub 📱


📣 Code Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥6❤5🤝1
👩‍💻 Умная валидация формы без JS!

Обычный :invalid подсвечивает ошибки даже в пустой форме, когда пользователь ещё ничего не вводил. Из-за этого приходится добавлять обработчики событий и отслеживать, какие поля уже были затронуты.
Но у CSS есть более точный инструмент — :user-invalid.

Как работает:
• :user-invalid выбирает поле, которое не прошло проверку после взаимодействия пользователя;

• : неhas() позволяет родительскому контейнеру реагировать на состояние вложенного поля;

• :not(:placeholder-shown) здесь не нужен — браузер сам учитывает момент взаимодействия;

• :user-valid позволяет аналогично оформить корректно заполненные поля.


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

📣 Code Ready | #фишка
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤6🔥6
Как убрать скачки меню при наведении без фиксированной ширины?

В навигации при наведении текст становится жирным, его ширина увеличивается, а соседние пункты сдвигаются.
.nav-link:hover {
font-weight: 700;
}

Часто это исправляют фиксированной шириной пунктов меню. Но такой подход плохо работает с переводами, динамическими названиями и адаптивной вёрсткой.

Есть более гибкий приём: заранее зарезервировать место под жирную версию текста.
<a class="nav-link" data-text="Каталог">
Каталог
</a>

.nav-link::before {
content: attr(data-text);
font-weight: 700;
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}

Псевдоэлемент создаёт невидимую копию надписи с нужной толщиной шрифта. Несмотря на нулевую высоту, его ширина участвует в расчёте размера элемента.

Поэтому ссылка заранее занимает достаточно места для жирного текста. Остаётся добавить само состояние наведения.
.nav-link:is(:hover, :focus-visible) {
font-weight: 700;
}


Теперь изменение толщины шрифта не должно сдвигать соседние элементы, если жирная версия действительно шире обычной.

Важный нюанс: значение data-text нужно поддерживать в соответствии с видимым текстом. Для многострочных подписей и сложной типографики приём стоит проверять отдельно.

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

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍10❤7🤝2
❤️ Крайне интересная статья на Хабре: «WASM vs JavaScript 2026 — проверка на Flutter Web»!

В этой статье:
• Узнаете, действительно ли переход с JavaScript на WebAssembly ускоряет Flutter-приложения;
• Разберёте результаты 46 тестов производительности: от вычислений и работы с памятью до обработки данных и графики;
• Посмотрите, в каких задачах выигрывает WASM, где быстрее JavaScript и как это влияет на плавность интерфейса.

🔊 Продолжай читать на Habr!


📣 Code Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤5🤝5👎1🔥1
Как избежать потери изменений при обновлении данных через API?

При редактировании данных пользователь может отправить несколько запросов подряд. Если сервер обрабатывает их независимо, более старый запрос иногда завершается позже нового и перезаписывает актуальное состояние.

Например, два запроса изменяют название документа:
fetch('/api/document/1', {
method: 'PATCH',
body: JSON.stringify({ title: 'Draft' })
});

fetch('/api/document/1', {
method: 'PATCH',
body: JSON.stringify({ title: 'Final' })
});


Порядок отправки запросов не гарантирует порядок их применения на сервере. Поэтому итоговое название может оказаться Draft, хотя пользователь последним указал Final.

Один из способов предотвратить перезапись изменений устаревшими данными — оптимистическая блокировка через версионирование данных. Сервер возвращает документ вместе с его версией:
{
"id": 1,
"title": "Draft",
"version": 5
}


При обновлении клиент передаёт версию, на основе которой редактировал документ:
const response = await fetch('/api/document/1', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Final',
version: 5
})
});


На бэкенд обновление выполняется только при совпадении версии. Например, в sql:
UPDATE documents
SET title = 'Final',
version = version + 1
WHERE id = 1
AND version = 5;


Если запись уже была изменена другим запросом, условие version = 5 не выполнится и количество обновлённых строк будет равно нулю. Такой же результат возможен, если документ не существует.

В таком случае бэкенд проверяет количество обновлённых строк и может вернуть 409 Conflict при несовпадении версии или 404 Not Found, если документ отсутствует. Фронтенд при конфликте может предложить пользователю обновить данные или разрешить конфликт:
if (response.status === 409) {
throw new Error(
'Документ был изменён. Обновите данные.'
);
}


🔥 Главное преимущество подхода — атомарная проверка версии и обновление записи в базе данных. Это предотвращает незаметную перезапись изменений, но не гарантирует применение последнего отправленного запроса.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥8❤7
This media is not supported in your browser
VIEW IN TELEGRAM
😎 FrontEnd_rus — полноценный русскоязычный курс по HTML, CSS и JavaScript!

В репозитории собраны учебные материалы, примеры кода и практические задания: от создания адаптивных страниц и работы со стилями до асинхронных запросов и взаимодействия с API. Обучение построено вокруг практики — по итогам модулей можно создать многостраничный сайт и интерактивное веб-приложение. Дополнительно есть руководства по Git, Linux, настройке VS Code и рабочего окружения.

Оставляю ссылочку: GitHub 📱


📣 Code Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍8🔥7🤝1
CSS @container style() — проверяй состояние компонента без дополнительных классов!

Обычные контейнерные запросы проверяют размер контейнера. Но CSS умеет проверять и значения его свойств — через style().

Это полезно, когда оформление вложенных элементов зависит от настройки родительского компонента.
Например, карточка может иметь два варианта оформления.
<article class="card" style="--variant: compact">
<h3 class="card__title">Название</h3>
<p class="card__description">Описание</p>
</article>


Задаём значение по умолчанию через CSS-переменную.
.card {
--variant: default;
}


А теперь меняем оформление вложенных элементов в зависимости от её значения.
@container style(--variant: compact) {
.card__description {
display: none;
}

.card__title {
font-size: 14px;
}
}


Здесь не нужен container-type: для проверки CSS-переменной достаточно обычного родительского элемента.

Можно комбинировать несколько условий.
@container style(--variant: compact) {
.card__title {
line-height: 1.2;
}
}


Запрос проверяет стили предка, а не самого элемента, к которому применяется правило; также поддержка style() для произвольных CSS-свойств пока отличается от поддержки проверки CSS-переменных.

🔥 @container style() позволяет передавать состояние оформления вложенным элементам через CSS-переменные, не создавая отдельные классы для каждого варианта компонента.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍8🤝4🔥2
👩‍💻 Адаптивная карточка без media queries и JS!

Обычно для адаптивной вёрстки приходится прописывать брейкпоинты и вручную управлять количеством колонок. Но CSS Grid умеет самостоятельно перестраивать элементы в зависимости от доступного пространства — буквально одной строкой.

Как работает:
• repeat(auto-fit, ...) автоматически подбирает количество колонок, которые помещаются в контейнере;

• minmax() задаёт минимальную и максимальную ширину каждой колонки;

• min(100%, 260px) не даёт колонке выйти за пределы узкого контейнера;

• 1fr распределяет оставшееся пространство между колонками.


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

📣 Code Ready | #фишка
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤7🔥7
📱 HTML Constraint Validation API: валидация форм!

В этом посте собраны основные методы и свойства HTML Constraint Validation API для проверки корректности данных в формах. Рассмотрены программная проверка полей, отображение ошибок, установка пользовательских сообщений, контроль обязательных значений, проверка формата и шаблонов, а также ограничений диапазона и шага.

📣 Code Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍8❤6🤝1
display: contents — убираем обёртку из CSS-раскладки!

Представим каталог, в котором карточки разбиты на группы. Обёртки нужны для структуры компонентов, но все товары должны находиться в одной сетке.
<div class="product-list">
<div class="product-group">
<article>Товар 1</article>
<article>Товар 2</article>
</div>

<div class="product-group">
<article>Товар 3</article>
</div>
</div>


Если применить Grid к .product-list, элементами сетки станут две группы, а не три карточки.
.product-list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}


Чтобы карточки участвовали в общей сетке, необязательно менять HTML. Достаточно убрать коробку обёртки из CSS-раскладки.
.product-group {
display: contents;
}


Теперь карточки становятся элементами сетки .product-list, хотя их родительские обёртки по-прежнему существуют в DOM.

Тот же приём работает и с Flexbox.
.toolbar {
display: flex;
gap: 12px;
}

.toolbar-group {
display: contents;
}


Важно: элемент с display: contents теряет собственную коробку, поэтому его фон, границы и отступы не отображаются как у обычного блока; для семантически важных обёрток также стоит проверять доступность.

🔥 display: contents позволяет сохранить структуру компонентов и при этом не усложнять CSS-раскладку лишними контейнерами.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14🔥8👍5
📱 HTML-атрибуты — получение, изменение, удаление и проверка атрибутов элементов!

Шпаргалка по работе с HTML-атрибутами через JavaScript: чтение значений с getAttribute(), добавление и обновление через setAttribute(), удаление с removeAttribute(), проверка наличия через hasAttribute() и переключение с toggleAttribute(). Также рассмотрены получение списка атрибутов через getAttributeNames(), работа с data-атрибутами через dataset и доступ к коллекции attributes.

📣 Code Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍8❤7