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

Автор: @energy_c

РКН: https://clck.ru/3NJCKs

Реклама на бирже: https://telega.in/c/code_ready
Download Telegram
Как создавать независимые компоненты без конфликтов CSS-переменных?

В больших проектах часто используют глобальные переменные:
:root {
--color: blue;
}


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

CSS позволяет делать локальные токены прямо внутри компонента.
.card {
--color: #222;
color: var(--color);
}


Теперь переменная действует только внутри .card и его потомков.

Можно создавать полностью изолированные темы компонентов.
.dark-card {
--bg: #111;
--text: white;
}


Внутренние элементы автоматически получают эти значения:
.title {
color: var(--text);
}


Без дополнительных классов и дублирования.

Особенно удобно для:
.theme,
.component,
.widget


где каждый блок должен иметь свои настройки.

🔥 Локальные CSS custom properties позволяют строить компонентные дизайн-системы без огромного количества модификаторов и переопределений.

📣 Code Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4🤝3
Intersection Observer — отслеживаем появление элементов в области видимости!

Эффективная альтернатива scroll-событиям. Используется для ленивой загрузки, анимаций и инфинит-скролла.

Инициализируем наблюдатель:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
});


Подключаем наблюдение:
document.querySelectorAll('.anim').forEach((el) => {
observer.observe(el);
});


Стили для появления:
.anim { opacity: 0; transform: translateY(30px); transition: 0.4s ease; }
.visible { opacity: 1; transform: none; }


🔥
Простая и масштабируемая практика, которую используют в продакшене: YouTube, Medium, e-commerce.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥118👍7
This media is not supported in your browser
VIEW IN TELEGRAM
✍️ Frontend Handbook — большая база знаний по frontend-разработке!

Здесь собраны статьи, документация, шпаргалки, инструменты и другие ресурсы по HTML, CSS, JavaScript, TypeScript, React и многим другим технологиям. Особенно удобно, что информация хорошо структурирована, поэтому можно быстро найти нужную тему.

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

📣 Code Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
13🔥7🤝4
👩‍💻 Группируем заголовок и обычный текст!

Тег <hgroup> объединяет основной заголовок страницы или раздела с дополнительным текстом, который его сопровождает — например, подзаголовком или кратким описанием.

Чаще всего внутри <hgroup> размещают:
• один из заголовков <h1>–<h6>;

• дополнительные элементы текста, например <p> с пояснением.


Он помогает логически связать несколько элементов заголовка, сохраняя структуру документа более понятной для браузеров и вспомогательных технологий. Не используйте <hgroup>, если вы хотите показать два независимых заголовка, — лучше оформить это через <section> или <article>

📣 Code Ready | #атрибут
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍6🤝4
Опа, тут бывший сеньор одного из IT-отделов Яндекса Игорь Никитин выкатил целый канал про Python — и это лучшее, что есть в рунете по теме.

Качественные гайды. Советы от известных прогеров. Тематические мемасы. Короче, ничего лишнего.

Хватит душить питона, учись его кодить: https://t.me/+IzIPzvoa7p40ZTUy 🐍
👎8
CSS.escape() — экранирование динамических значений для CSS-селекторов!

При работе с DOM часто приходится искать элементы по динамическим значениям: id, class, значениям атрибутов. И здесь есть один важный момент: querySelector() и querySelectorAll() принимают не просто строки, а полноценные CSS-селекторы.

Поэтому если часть селектора формируется динамически, нужно учитывать правила синтаксиса CSS. Например:
const id = "user:123";

const element = document.querySelector(
`#${id}`
);


После подстановки браузер получает:
#user:123


На первый взгляд кажется, что мы ищем элемент с id="user:123".

Но для CSS символ : имеет специальное значение. Он используется для псевдоклассов:
:hover
:focus
:checked


Поэтому CSS-парсер воспринимает : не как часть значения, а как элемент синтаксиса селектора.

Для таких случаев существует стандартный метод CSS.escape():
const id = "user:123";

const element = document.querySelector(
`#${CSS.escape(id)}`
);


Теперь значение будет преобразовано в корректный CSS-идентификатор:
#user\:123


Браузер понимает, что : является частью значения, а не специальной конструкцией CSS. Такая проблема возникает не только с двоеточием.

CSS имеет множество специальных символов, которые могут изменить смысл селектора:
const id = "product.item#42";

const element = document.querySelector(
`#${CSS.escape(id)}`
);


Без экранирования символы ., # и другие будут интерпретироваться как часть CSS-селектора.

То же самое относится к динамическим классам:
const className = "theme:dark";

const element = document.querySelector(
`.${CSS.escape(className)}`
);


CSS.escape() работает согласно правилам CSS-идентификаторов и возвращает строку, которую можно использовать внутри селектора:
CSS.escape("hello world");
// "hello\ world"

CSS.escape("item.value");
// "item\.value"

CSS.escape("a:b");
// "a\:b"


До появления этого метода часто использовали ручное экранирование:
value.replace(/:/g, "\\:");


Но такой подход быстро становится неудобным. CSS имеет много специальных случаев: разные символы, пробелы, цифры в начале идентификаторов и другие правила. CSS.escape() переносит эту логику на стандартный API браузера.

Использовать его стоит в местах, где динамическое значение становится частью CSS-селектора:
document.querySelector()

document.querySelectorAll()

element.matches()

element.closest()


Важный момент: CSS.escape() не является механизмом защиты данных.

Он решает только задачу корректного экранирования значения для CSS-селектора. Например:
element.innerHTML = value;


— это уже другая область: HTML и потенциальные XSS-риски. Там используются другие механизмы защиты. Если вы работаете с динамическими id, классами или значениями, которые приходят извне (например, из API), CSS.escape() помогает избежать ошибок парсинга и сохранить ожидаемое поведение DOM API.

🔥 CSS.escape() — хороший способ подготовить динамические значения перед использованием внутри CSS-селекторов.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6🤝42
👩‍💻 Можно ли стилизовать текст, к которому пользователь перешёл по ссылке?

::target-text — псевдоэлемент, который применяется к тексту, найденному через текстовый фрагмент в URL вида #:~:text=.... Он позволяет задать стили выделения, которые браузер покажет после перехода по такой ссылке.

Примеры использования:
• изменить фон выделенного текста;

• добавить собственный цвет текста;

• настроить контрастное выделение вместо стандартного.


Стандартные якоря #id подсвечивают целевой элемент. Текстовые фрагменты #:~:text=... указывают на конкретную строку текста. ::target-text позволяет настраивать стиль этого автоматического выделения (обычно это жёлтая подсветка от браузера), чтобы он соответствовал дизайну.

📣 Code Ready | #свойство
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥54
🔥 Глобальное обновление программ CyberYozh Academy
3 новых уровня для вашей карьеры


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

⚡️Выбирайте свой трек:
🟢 УРОВЕНЬ 1: Новичкам - Инженер по информационной безопасности
Трек для тех, кто готов освоить одну из самых высокооплачиваемых и востребованных профессий в IT с полного нуля, без воды и иллюзий.
Длительность: 11 месяцев
Итог: Диплом установленного образца + помощь с трудоустройством
Стоимость: от 5 015 ₽/мес


🟡УРОВЕНЬ 2: Специализация - Специалист по OSINT
Полное погружение в конкретную специальность. Идеально для студентов, у которых уже есть базовые знания в ИБ, и которым нужно стать профи в узкой нише.
Длительность: 9 месяцев
Итог: Удостоверение + помощь с трудоустройством
Стоимость: от 4 763 ₽/мес


🟥УРОВЕНЬ 3: Повышение квалификации - Пентест внутренней инфраструктуры: Active Directory
Курсы для действующих специалистов в сфере ИБ, которым необходимо расширить свой боевой арсенал и пробить карьерный потолок.
Длительность: 6 месяцев
Итог: Удостоверение + подготовка к сертификации
Стоимость: от 5 821 ₽/мес


Неважно, делаете ли вы первые шаги или уже давно работаете - у нас есть инструменты, чтобы кратно усилить ваши скиллы.

👉 Подобрать программу и записаться на курс: @cyacademy_support 🦔
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Intl.ListFormat: форматируем списки с учётом языка пользователя!

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

Самый простой вариант — использовать join():
const users = [
'Alex',
'Maria',
'John'
];

users.join(', ');


Такой подход работает только для простого разделения элементов. Но он не знает правил конкретного языка. В английском между последними элементами используется and, в русском — и, а в других локалях могут быть свои правила форматирования.

Если приложение поддерживает несколько языков, обычно появляются ручные проверки:
if (locale === 'en') {
// добавить and
}

if (locale === 'ru') {
// добавить и
}


Поддерживать такую логику сложно, поэтому для подобных задач в JavaScript существует стандартный API Intl.ListFormat.

Создаём форматтер и передаём нужную локаль:
const formatter =
new Intl.ListFormat('ru');

formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);


Результат: JavaScript, TypeScript и Python.

При изменении локали правила форматирования изменятся автоматически:
const formatter =
new Intl.ListFormat('en');

formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);


Результат: JavaScript, TypeScript, and Python.

Intl.ListFormat использует встроенные правила локализации JavaScript, поэтому не нужно самостоятельно реализовывать союзы, разделители и особенности разных языков.

Кроме обычного перечисления можно форматировать варианты выбора. Например, когда пользователь выбирает один из способов оплаты:
const formatter =
new Intl.ListFormat(
'ru',
{
type: 'disjunction'
}
);

formatter.format([
'Карта',
'PayPal',
'Перевод'
]);


Результат: Карта, PayPal или Перевод.

По умолчанию используется conjunction — обычное перечисление через союз "и". Значение disjunction используется для альтернатив через "или".

Также важно понимать, что Intl.ListFormat не изменяет исходные данные. Он только создаёт новую строку:
const tags = [
'Frontend',
'Backend',
'DevOps'
];

const text =
new Intl.ListFormat('ru')
.format(tags);


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

🔥 Intl.ListFormat позволяет использовать стандартные правила локализации JavaScript вместо ручной сборки строк через join() и множества условий для разных языков.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍7🔥6
Наткнулся на необычную и очень интересную статью на Хабре: «PowerHTML»!

В этой статье:
• Показывается, как создать интерактивные презентации, которые работают полностью офлайн в одном HTML-файле без установки программ и регистрации;
• Разбираются возможности редактора: встроенные видео, анимации, таймеры, интерактивные элементы и др;
• Объясняется, как с помощью AI был создан полноценный инструмент, ориентированный на преподавателей, спикеров и всех, кто проводит презентации.

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

📣 Code Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥65
На Stepik запустили курс по вайбкодингу c Claude Code

Первым делом вы освоите базу Claude Code и научитесь проектировать полноценные приложения.

После этого перейдёте к более продвинутым инструментам и автоматизации:

➡️Разработаете собственные MCP-серверы и Claude Skills
➡️Автоматизируете разработку с помощью Agent Loops и хуков
➡️Освоите Claude Design, Cowork и Connectors
➡️Построите личную систему знаний на базе Obsidian + Claude Cowork
➡️Научитесь работать с таблицами при помощи Cowork
➡️Перестанете постоянно упираться в лимиты Claude

А в финале получите готовую дорожную карту, полезные лайфхаки и 7 практических способов обхода блокировок Claude Code в России.

🔥 В течении 48 часов действует скидка 25%
Please open Telegram to view this post
VIEW IN TELEGRAM
2👎1
Element.animate() — управление композицией анимаций в браузере!

CSS-анимации удобны, пока элемент имеет одно состояние. Но когда несколько эффектов должны управляться из JavaScript, Web Animations API даёт больше контроля.

Например, несколько анимаций одного элемента могут существовать одновременно:
const fade = element.animate(
[
{ opacity: 0 },
{ opacity: 1 }
],
{
duration: 300
}
);

const move = element.animate(
[
{ transform: 'translateY(20px)' },
{ transform: 'translateY(0)' }
],
{
duration: 300
}
);


Браузер создаёт отдельные Animation-объекты и объединяет их эффекты при расчёте итогового стиля элемента.

У каждой анимации есть собственное состояние:
console.log(fade.playState);

console.log(move.currentTime);


currentTime позволяет управлять прогрессом вручную:
fade.currentTime = 150;


Анимация сразу перейдёт примерно к середине выполнения. Это полезно для синхронизации анимаций с внешним состоянием, например с прогрессом загрузки:
animation.currentTime =
progress * animation.effect.getTiming().duration;


Также Web Animations API позволяет изменять параметры уже созданного эффекта:
animation.effect.updateTiming({
duration: 1000
});


При этом не нужно пересоздавать анимацию. Отдельно стоит учитывать композицию свойств. Если два эффекта изменяют один и тот же параметр:
element.animate(
[
{ transform: 'translateX(100px)' }
],
{
duration: 1000
}
);

element.animate(
[
{ transform: 'scale(1.2)' }
],
{
duration: 1000
}
);


Оба эффекта работают с одним CSS-свойством transform. Итоговое поведение зависит от правил композиции анимаций, поэтому параллельное изменение одного свойства может дать неожиданный результат.

Для сложных случаев можно управлять композицией через composite:
element.animate(
[
{
transform: 'translateX(100px)'
}
],
{
duration: 500,
composite: 'add'
}
);


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

🔥 Element.animate() — это не просто замена CSS keyframes. Web Animations API предоставляет полноценную модель управления анимациями: состояние, время выполнения, изменение параметров и правила композиции эффектов.

📣 Code Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥54