Атрибут
required добавляется обязательным полям формы. Если поле с таким атрибутом не заполнено, то при отправке формы браузер покажет предупреждение и отменит отправку.Атрибут required можно использовать для <select>, <textarea>, а также для <input> со следующими типами:
• text,
• search,
• url,
• tel,
• email,
• password,
• date,
• month,
• week,
• time,
• datetime-local,
• number,
• checkbox,
• radio,
• file.
Важно: этот атрибут проверяется только на стороне браузера. Для защиты данных всегда нужна дополнительная проверка на сервере, так как HTML-валидацию можно обойти.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥9🤝7❤2
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь собраны полезные ресурсы по HTML, CSS, Flexbox, Grid, JavaScript, React, Git и Computer Science: учебники, статьи, интерактивные курсы, игры и задачи. Отдельные разделы посвящены JavaScript-проектам и подготовке к собеседованиям. Удобная подборка для начинающих.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥6🤝6❤2
Передавай простые значения из HTML прямо в CSS!
Раньше
Например, прогресс можно хранить прямо в разметке:
А ширину вычислить без
То же самое работает с типизированными значениями. Например, компонент может получить цвет из
Это удобно для серверного рендера и компонентов, где данные уже находятся в DOM, тк не нужно дублировать их в
Но пока расширенный
🔥 По сути,
📣 Code Ready | #совет
Раньше
attr() практически ассоциировался только с content. Расширенный синтаксис умеет читать атрибут как конкретный CSS-тип и использовать результат в обычных свойствах.Например, прогресс можно хранить прямо в разметке:
<div class="progress" data-value="72"></div>
А ширину вычислить без
style="width: 72% и без JS:.progress {
width: calc(attr(data-value type(<number>)) * 1%);
}То же самое работает с типизированными значениями. Например, компонент может получить цвет из
data-*:.badge {
background: attr(data-color type(<color>), gray);
}Это удобно для серверного рендера и компонентов, где данные уже находятся в DOM, тк не нужно дублировать их в
inline-style или генерировать отдельные классы.Но пока расширенный
attr() для произвольных свойств и type() ещё имеет неполную поддержку браузерами.data-* теперь может быть небольшим типизированным API между разметкой и CSS.Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥7❤6
В этой статье:
• Узнаете, как сделать аналог fixed-элемента внутри прокручиваемого контейнера;• Разберёте необычный способ передачи параметров в SVG через CSS;• Посмотрите, как scroll-driven animations помогают решить сложную задачу с автоматическим размером элементов.🔊 Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍6🔥4🤝2
Разбираем insertAdjacentHTML() — вставляем HTML без повторного парсинга существующего содержимого!
Для добавления разметки в элемент иногда используют
Но это не точечная вставка. Браузер получает текущее содержимое как строку, добавляет новую разметку и снова устанавливает
В результате существующие дочерние DOM-узлы могут быть заменены новыми:
Для вставки HTML без повторного парсинга существующего содержимого есть
Метод принимает позицию вставки и HTML-строку:
Например, вставка первым дочерним элементом:
А
Что важно:
🔥 В отличие от
📣 Code Ready | #практика
Для добавления разметки в элемент иногда используют
innerHTML +=:list.innerHTML += '<li>Новый элемент</li>';
Но это не точечная вставка. Браузер получает текущее содержимое как строку, добавляет новую разметку и снова устанавливает
innerHTML.В результате существующие дочерние DOM-узлы могут быть заменены новыми:
const button = list.querySelector('button');
list.innerHTML += '<li>Новый</li>';
console.log(
list.querySelector('button') === button
);
// falseДля вставки HTML без повторного парсинга существующего содержимого есть
insertAdjacentHTML():const button = list.querySelector('button');
list.insertAdjacentHTML(
'beforeend',
'<li>Новый</li>'
);
console.log(
list.querySelector('button') === button
);
// trueМетод принимает позицию вставки и HTML-строку:
beforebegin
afterbegin
beforeend
afterend
Например, вставка первым дочерним элементом:
list.insertAdjacentHTML(
'afterbegin',
'<li>Первый</li>'
);
А
afterend вставляет разметку после самого элемента:list.insertAdjacentHTML(
'afterend',
'<p>После списка</p>'
);
beforebegin и afterend работают относительно родительского элемента, поэтому целевой элемент должен иметь родителя.Что важно:
insertAdjacentHTML() передает строку HTML-парсеру и не выполняет санитизацию. Передача недоверенного HTML создает риск XSS. Для обычного текста используйте textContent или insertAdjacentText(), а недоверенный HTML необходимо корректно санитизировать.innerHTML +=, insertAdjacentHTML() позволяет вставить новый HTML-фрагмент в нужную позицию, не заменяя уже существующие DOM-узлы.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤7🔥5
Почему change не всегда подходит для отслеживания изменений в input!
При работе с формами часто пытаются отслеживать ввод через событие
Но для текстовых полей это не всегда правильный вариант.
Если интерфейс должен реагировать непосредственно во время ввода, используется событие
Теперь обработчик вызывается при каждом изменении значения:
При этом
Например, динамический поиск обычно строят так:
Частая ошибка — использовать
Но эти события решают разные задачи.
У события
Например, можно определить, было ли действие вставкой текста, удалением символа или вставкой из буфера обмена.
Если обработчик
При этом у
Важный нюанс: программное изменение
Браузер отличает изменение через код от реального пользовательского ввода. Если приложению нужно уведомить другие части системы, событие можно вызвать отдельно:
Но такое событие будет синтетическим (
В сложных редакторах также учитывают IME-ввод, например при работе с китайской, японской или корейской раскладкой. Во время композиции можно проверить:
🔥 Главное правило простое: если нужно реагировать на процесс редактирования в реальном времени — используйте
📣 Code Ready | #практика
При работе с формами часто пытаются отслеживать ввод через событие
change:input.addEventListener('change', event => {
console.log(event.target.value);
});Но для текстовых полей это не всегда правильный вариант.
change срабатывает не при каждом изменении текста, а после того, как пользователь изменил значение и завершил редактирование, например покинул поле.Если интерфейс должен реагировать непосредственно во время ввода, используется событие
input:input.addEventListener('input', event => {
console.log(event.target.value);
});Теперь обработчик вызывается при каждом изменении значения:
J
Ja
Jav
Java
При этом
input — это не просто реакция на нажатие клавиш. Событие возникает и при других действиях пользователя, например при вставке текста, удалении, вставке через контекстное меню или перемещении текста через drag & drop.Например, динамический поиск обычно строят так:
search.addEventListener('input', event => {
const query = event.target.value.trim();
filterItems(query);
});Частая ошибка — использовать
keyup как замену input:input.addEventListener('keyup', handler);Но эти события решают разные задачи.
keyup реагирует только на отпускание клавиши, поэтому он не поймает вставку мышью, автозаполнение браузера и другие изменения значения без клавиатуры.У события
input есть дополнительная информация через InputEvent:input.addEventListener('input', event => {
console.log(event.inputType);
});Например, можно определить, было ли действие вставкой текста, удалением символа или вставкой из буфера обмена.
Если обработчик
input запускает тяжёлую операцию или запрос к API, обычно используют debounce, чтобы не выполнять действие после каждого символа:search.addEventListener(
'input',
debounce(event => {
fetchResults(event.target.value);
}, 300)
);
При этом у
change остаются свои правильные сценарии. Например, для <select> он хорошо подходит, потому что важен момент выбора нового значения:select.addEventListener('change', event => {
updateLanguage(event.target.value);
});Важный нюанс: программное изменение
value само по себе не создаёт событие input:input.value = 'JavaScript';
Браузер отличает изменение через код от реального пользовательского ввода. Если приложению нужно уведомить другие части системы, событие можно вызвать отдельно:
input.value = 'JavaScript';
input.dispatchEvent(
new Event('input', { bubbles: true })
);
Но такое событие будет синтетическим (
isTrusted === false), а не настоящим действием пользователя.В сложных редакторах также учитывают IME-ввод, например при работе с китайской, японской или корейской раскладкой. Во время композиции можно проверить:
input.addEventListener('input', event => {
if (event.isComposing) {
return;
}
processValue(event.target.value);
});input. Если нужно получить факт завершённого изменения значения — подходит change. Если нужно отслеживать только действия клавиатуры — используйте keyup, понимая его ограничения.Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🤝10👍7🔥1
Разбираем AbortController и AbortSignal, с помощью которых можно отменять fetch-запросы и другие поддерживаемые операции, проверять состояние и причину отмены, прерывать собственную асинхронную логику, задавать таймауты и объединять несколько сигналов отмены. Используется для управления жизненным циклом операций, предотвращения лишней работы и корректной очистки ресурсов.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍9🤝3❤2
В контейнер
<nav> помещаются основные ссылки, по которым пользователь сможет быстро перейти на нужный раздел сайта.В <nav> обычно размещают:
• главное меню сайта;
• навигацию по разделам;
• оглавление статьи или документа;
• ссылки для перехода между связанными страницами.
При этом не каждую группу ссылок стоит помещать в
<nav>. Тег предназначен прежде всего для основных навигационных блоков, а обычный набор вспомогательных ссылок может оставаться без него.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤9🤝4🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
В репозитории собраны полезные ресурсы по веб-разработке: HTML, CSS, JavaScript, React, Node.js, Webpack, Git, тестирование и архитектура frontend-приложений. Есть статьи, курсы, видео, книги, разборы задач и практические материалы по асинхронности, ООП, алгоритмам, паттернам проектирования и созданию реальных проектов.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9🤝7👍4❤1
Прокачать навыки вёрстки и фронтенда можно в телеграм!
В этом канале опытный верстальщик делится структурированными уроками и различными материалами по HTML, CSS, JS, а также советами по заработку на фрилансе.
Канал будет полезен:
1. начинающим и опытным верстальщикам
2. программистам
3. веб-дизайнерам
Научиться и зарабатывать на верстке:
@free_html_lessons
В этом канале опытный верстальщик делится структурированными уроками и различными материалами по HTML, CSS, JS, а также советами по заработку на фрилансе.
Канал будет полезен:
1. начинающим и опытным верстальщикам
2. программистам
3. веб-дизайнерам
Научиться и зарабатывать на верстке:
@free_html_lessons
Не давай стилям компонента протекать во вложенные компоненты!
Частая проблема большого UI: стилизуем весь контент внутри компонента, а потом эти правила неожиданно задевают другой компонент, вложенный внутрь.
Обычный селектор по вложенности затронет оба
С
Первый
Это особенно удобно для CMS-контента,
И не приходится усложнять селекторы:
Вместо описания всей структуры мы задаём архитектурную границу:
🔥
📣 Code Ready | #совет
Частая проблема большого UI: стилизуем весь контент внутри компонента, а потом эти правила неожиданно задевают другой компонент, вложенный внутрь.
<article class="article">
<p>Текст статьи</p>
<div class="widget"><p>Текст виджета</p></div>
</article>
Обычный селектор по вложенности затронет оба
<p>:.article p {
margin-block: 1em;
}С
@scope можно задать не только начало области, но и место, перед которым действие правил заканчивается.@scope (.article) to (.widget) {
p { margin-block: 1em; }
}Первый
<p> получит стиль, а <p> внутри .widget — уже нет. .widget здесь является нижней границей scope, поэтому элементы внутри неё исключаются из этой области.Это особенно удобно для CMS-контента,
markdown, rich-text и дизайн-систем, где внутрь одного компонента могут попадать другие независимые компоненты.И не приходится усложнять селекторы:
.article > p,
.article > section > p {
/* попытка описать структуру DOM */
}
Вместо описания всей структуры мы задаём архитектурную границу:
@scope (.content) to (.component) {
a { text-decoration: underline; }
}@scope специально предназначен для ограничения селекторов конкретным DOM-поддеревом без наращивания специфичности и жёсткой привязки CSS к структуре разметки.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤6🤝4👍2
Тег
<picture> позволяет браузеру выбирать подходящую версию изображения в зависимости от размера экрана, поддерживаемого формата или других условий.Внутри <picture> обычно размещают:
• <source> — задаёт альтернативные версии изображения;
• srcset — указывает файл изображения;
• media — определяет условие выбора, например ширину экрана;
• type — указывает MIME-тип формата, например image/avif;
• <img> — служит основным или резервным вариантом изображения.
Браузер анализирует каждый тег
<source> по порядку, останавливается на первом подходящем под текущие условия и отображает картинку из атрибута srcset. Другие теги не анализируются. Если тег <picture> не поддерживается браузером или ни один из тегов <source> не подходит под условия, то отображается картинка из тега <img>.Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🤝4🔥1
Ищем новичков во frontend-разработке и вёрстке сайтов.
Айтилогия запускает бесплатное обучение, где будет:
1. Практика на реальном заказе ценой до 10 000₽.
2. Разбор работ куратором.
3. Задачи от Fullstack-разработчика с 12-летним опытом.
4. Именной сертификат.
И главное — ты почувствуешь уверенность.
Потому что увидишь, что выполнить заказ на frontend-проект тебе по силам.
👉 Приходи на бесплатное обучение и зови с собой друзей
🔥 С 2019 Айтилогия стабильно помогает с обучением, практикой, зарабатывать на фрилансе и проходить собеседования.
Айтилогия запускает бесплатное обучение, где будет:
1. Практика на реальном заказе ценой до 10 000₽.
2. Разбор работ куратором.
3. Задачи от Fullstack-разработчика с 12-летним опытом.
4. Именной сертификат.
И главное — ты почувствуешь уверенность.
Потому что увидишь, что выполнить заказ на frontend-проект тебе по силам.
👉 Приходи на бесплатное обучение и зови с собой друзей
🔥 С 2019 Айтилогия стабильно помогает с обучением, практикой, зарабатывать на фрилансе и проходить собеседования.
😁1
Element.scrollIntoView() — управление прокруткой без ручной работы с координатами.
По умолчанию метод пытается сделать элемент видимым во всех подходящих прокручиваемых предках — включая вложенные scroll-контейнеры и viewport, если это необходимо.
В новых реализациях браузеров появился параметр
Это особенно полезно для компонентов с вложенной прокруткой: списков, панелей, модальных окон и навигационных меню.
А также важно не путать два разных
Во многих случаях для управления расстоянием до края viewport или scroll-контейнера не требуется вручную считать координаты через
Теперь браузер учитывает заданные CSS-правила при вычислении конечной позиции.
🔥 В результате
📣 Code Ready | #практика
scrollIntoView() в основном используют как простой переход к элементу, но в сложных интерфейсах важно понимать, какие scroll-контейнеры браузер будет изменять и как управлять областью воздействия.По умолчанию метод пытается сделать элемент видимым во всех подходящих прокручиваемых предках — включая вложенные scroll-контейнеры и viewport, если это необходимо.
element.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});В новых реализациях браузеров появился параметр
container, который позволяет ограничить область прокрутки.element.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
container: 'nearest'
});container: 'nearest' ограничивает область прокрутки ближайшим scroll-контейнером вместо изменения всех доступных областей прокрутки.Это особенно полезно для компонентов с вложенной прокруткой: списков, панелей, модальных окон и навигационных меню.
container — относительно новый параметр с ограниченной поддержкой браузерами. Перед использованием в продакшн стоит проверить поддержку. В браузерах без поддержки параметр может быть проигнорирован.А также важно не путать два разных
nearest: container: 'nearest' отвечает за какая область прокрутки может изменяться.block: 'nearest' отвечает за как элемент будет позиционироваться внутри видимой области.activeItem.scrollIntoView({
block: 'nearest',
inline: 'nearest'
});block: 'nearest' использует стратегию минимального смещения. В отличие от start или center, браузер не пытается принудительно установить элемент в определённую позицию, а выполняет только необходимую прокрутку, чтобы элемент стал видимым. block обычно управляет вертикальной осью, а inline — горизонтальной.Во многих случаях для управления расстоянием до края viewport или scroll-контейнера не требуется вручную считать координаты через
getBoundingClientRect(). Эти правила можно описать через CSS:.item {
scroll-margin-block: 16px;
}
.list {
overflow-y: auto;
scroll-padding-block: 16px;
}scroll-margin задаёт внешний отступ для самого элемента при прокрутке.scroll-padding определяет внутреннюю область видимости scroll-контейнера, внутри которого выполняется прокрутка. Это позволяет учитывать фиксированные панели, sticky-header и другие элементы интерфейса декларативно. Пример:section.scrollIntoView({
behavior: 'smooth',
block: 'start'
});Теперь браузер учитывает заданные CSS-правила при вычислении конечной позиции.
scrollIntoView() становится инструментом не только для простых якорных переходов, а для построения сложной навигации внутри интерфейсов с большим количеством вложенных scroll-областей.Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🔥5
🔴 Тестовый собес на Frontend-разработчика со старшим разработчиком ex. Сбер в этот четверг!
[+ разбор 50 сложных вопросов в подарок ]
17 сентября (в этот четверг!) в 19:00 по мск приходи онлайн, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика!
Собеседование проведёт Даниил Дмитриев - старший разработчик в R-Vision, ex. Сбер,
Как это будет:
📂 Даниил задаст разработчику вопросы и задачи, которые могут спросить на реальном собесе
📂 После каждого ответа респондента ты услышишь подробный комментарий от ментора и поймёшь, чего на самом деле ожидает собеседующий на интервью
📂 В конце сможешь задать любой вопрос Даниилу и получить на него развёрнутый ответ
Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы
И ты можешь посмотреть его бесплатно 🔥
Только завтра, в прямом эфире!
🎁 Подарок для всех, кто зарегается на веб — файл с ОТВЕТАМИ НА 50 СЛОЖНЫХ ВОПРОСОВ с Frontend-собеседований 🔥
Переходи в бот, чтобы попасть на эфир и забрать подарок 👉 @shortcut_front_bot
Реклама.
О рекламодателе.
[+ разбор 50 сложных вопросов в подарок ]
17 сентября (в этот четверг!) в 19:00 по мск приходи онлайн, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика!
Собеседование проведёт Даниил Дмитриев - старший разработчик в R-Vision, ex. Сбер,
Как это будет:
📂 Даниил задаст разработчику вопросы и задачи, которые могут спросить на реальном собесе
📂 После каждого ответа респондента ты услышишь подробный комментарий от ментора и поймёшь, чего на самом деле ожидает собеседующий на интервью
📂 В конце сможешь задать любой вопрос Даниилу и получить на него развёрнутый ответ
Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы
И ты можешь посмотреть его бесплатно 🔥
Только завтра, в прямом эфире!
🎁 Подарок для всех, кто зарегается на веб — файл с ОТВЕТАМИ НА 50 СЛОЖНЫХ ВОПРОСОВ с Frontend-собеседований 🔥
Переходи в бот, чтобы попасть на эфир и забрать подарок 👉 @shortcut_front_bot
Реклама.
О рекламодателе.
requestSubmit() — программная отправка формы с сохранением нативного поведения!
В HTML-формах существует два разных подхода к программному запуску отправки. Метод
Если форма содержит обработчик
Для случаев, когда отправка инициируется js, но должна сохранить стандартную модель поведения HTML-форм, используется метод
Рассмотрим форму с обязательным email-полем. Если значение отсутствует или не проходит проверку типа
После регистрации обработчика отправку можно инициировать программно, сохранив обычное поведение формы.
В отличие от
Переданная кнопка должна быть submit-элементом, связанным с этой формой. В этом случае учитываются такие параметры кнопки, как
В реальном приложении выбор конкретной submit-кнопки позволяет управлять поведением одной формы из разных сценариев отправки, сохраняя стандартную обработку браузера.
На практике
🔥
📣 Code Ready | #практика
В HTML-формах существует два разных подхода к программному запуску отправки. Метод
submit() выполняет непосредственную отправку формы, но отличается от пользовательского сценария: он не запускает constraint validation и не генерирует событие submit.const form = document.querySelector('form');
form.submit();Если форма содержит обработчик
submit, вызванный через submit(), он не будет выполнен. Это принципиальное отличие от реального действия пользователя через submit-кнопку.const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
event.preventDefault();
console.log('Form submitted');
});
form.submit();Для случаев, когда отправка инициируется js, но должна сохранить стандартную модель поведения HTML-форм, используется метод
requestSubmit().form.requestSubmit();
requestSubmit() запускает стандартный алгоритм отправки формы: браузер выполняет встроенную constraint validation, а после успешной проверки генерирует событие submit.Рассмотрим форму с обязательным email-полем. Если значение отсутствует или не проходит проверку типа
email, обработчик submit вызван не будет, поскольку браузер остановит процесс на этапе валидации.<form id="profile">
<input
name="email"
type="email"
required
>
<button type="submit">
Save
</button>
</form>
После регистрации обработчика отправку можно инициировать программно, сохранив обычное поведение формы.
const form = document.querySelector('#profile');
form.addEventListener('submit', (event) => {
event.preventDefault();
const data = new FormData(form);
console.log(Object.fromEntries(data));
});
form.requestSubmit();В отличие от
submit(), метод requestSubmit() также позволяет передать конкретную submit-кнопку. Это важно для форм, где разные кнопки отправки имеют собственные параметры или меняют поведение отправки.const saveButton = form.querySelector('.save');
form.requestSubmit(saveButton);Переданная кнопка должна быть submit-элементом, связанным с этой формой. В этом случае учитываются такие параметры кнопки, как
name, value, formaction, formenctype, formmethod и другие submit-настройки.<form id="actions">
<input name="title" value="Example">
<button
class="save"
type="submit"
name="action"
value="save"
>
Save
</button>
</form>
В реальном приложении выбор конкретной submit-кнопки позволяет управлять поведением одной формы из разных сценариев отправки, сохраняя стандартную обработку браузера.
const form = document.querySelector('#actions');
const saveButton = form.querySelector('.save');
form.requestSubmit(saveButton);На практике
requestSubmit() применяется, когда действие пользователя необходимо инициировать из js, но при этом требуется сохранить полный жизненный цикл HTML-формы: валидацию браузера, событие submit и стандартную обработку submit-кнопки.form.submit() и form.requestSubmit() решают разные задачи. Первый вариант выполняет прямую отправку без validation и события submit, второй запускает полноценный процесс отправки, максимально близкий к пользовательскому взаимодействию с формой. Если программная отправка должна работать так же, как обычное нажатие submit-кнопки, используйте requestSubmit().Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤6🔥5