Псевдоклассы
:valid и :invalid в CSS позволяют стилизовать поля формы в зависимости от результата встроенной HTML-валидации. Они работают с ограничениями вроде required, pattern, min, max, type="email" и другими.Как это используется:
• :valid — поле заполнено корректно;
• :invalid — значение не прошло проверку;
• можно менять цвет рамки, фона или отображать состояние поля.
Это простой способ сделать форму более понятной для пользователя, не прибегая к JS.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍6🔥5🤝2
Passive Event Listeners: оптимизация обработки touch- и wheel-событий!
При обработке некоторых событий ввода браузеру необходимо понимать, может ли JavaScript-обработчик отменить стандартное поведение события.
Например, при взаимодействии с экраном пользователь ожидает мгновенной прокрутки страницы. Однако обработчик
В этом случае браузер должен учитывать, что обработчик потенциально может вызвать
Чтобы явно указать, что обработчик не будет отменять стандартное поведение, используется параметр
Теперь браузер знает, что обработчик не вызовет
Следует учитывать, что современные браузеры в некоторых случаях автоматически используют пассивный режим для обработчиков
Событие
В данном примере при каждом вызове обработчика выполняется поиск элемента в DOM и изменяется его стиль. При высокой частоте событий это создаёт дополнительную нагрузку на основной поток.
В подобных случаях эффективнее заранее сохранить ссылку на элемент, сократить объём выполняемой работы и при необходимости использовать
Также важно учитывать, что
Внутри пассивного обработчика не остановит стандартное поведение браузера и обычно приведёт к предупреждению в консоли.
🔥 Passive Event Listeners уменьшают задержки при обработке touch- и wheel-событий, поскольку браузеру не требуется ожидать возможного вызова
📣 Code Ready | #практика
При обработке некоторых событий ввода браузеру необходимо понимать, может ли JavaScript-обработчик отменить стандартное поведение события.
Например, при взаимодействии с экраном пользователь ожидает мгновенной прокрутки страницы. Однако обработчик
touchmove может вызвать event.preventDefault() и заблокировать стандартный жест браузера. Если обработчик считается непассивным, браузеру может потребоваться дождаться завершения его выполнения, прежде чем начать или продолжить прокрутку. Обычный обработчик события:window.addEventListener(
'touchmove',
event => {
const touch = event.touches[0];
console.log(
touch.clientX,
touch.clientY
);
},
{
passive: false
}
);
В этом случае браузер должен учитывать, что обработчик потенциально может вызвать
preventDefault(). Поэтому прокрутка может быть отложена до завершения выполнения JavaScript-кода.Чтобы явно указать, что обработчик не будет отменять стандартное поведение, используется параметр
passive.window.addEventListener(
'touchmove',
event => {
const touch = event.touches[0];
console.log(
touch.clientX,
touch.clientY
);
},
{
passive: true
}
);
Теперь браузер знает, что обработчик не вызовет
preventDefault(), и может обрабатывать прокрутку без ожидания завершения JavaScript-кода.Следует учитывать, что современные браузеры в некоторых случаях автоматически используют пассивный режим для обработчиков
touchstart, touchmove, wheel и mousewheel, зарегистрированных на window, document или body. Конкретное поведение зависит от браузера, события и целевого элемента. Поэтому, если обработчик должен гарантированно вызывать preventDefault(), лучше явно указать:{
passive: false
}Событие
scroll отличается тем, что возникает после изменения позиции прокрутки и не может быть отменено через preventDefault(). Поэтому использование passive для scroll не даёт преимуществ производительности. Например:window.addEventListener(
'scroll',
() => {
const position = window.scrollY;
document.querySelector(
'.header'
).style.opacity = Math.min(
position / 500,
1
);
}
);
В данном примере при каждом вызове обработчика выполняется поиск элемента в DOM и изменяется его стиль. При высокой частоте событий это создаёт дополнительную нагрузку на основной поток.
В подобных случаях эффективнее заранее сохранить ссылку на элемент, сократить объём выполняемой работы и при необходимости использовать
requestAnimationFrame или throttling.const header = document.querySelector('.header');
let scheduled = false;
window.addEventListener('scroll', () => {
if (scheduled) {
return;
}
scheduled = true;
requestAnimationFrame(() => {
header.style.opacity = Math.min(
window.scrollY / 500,
1
);
scheduled = false;
});
});debounce обычно применяют для действий, которые должны выполняться после завершения прокрутки, например для отправки аналитики или сохранения состояния интерфейса.Также важно учитывать, что
passive: true запрещает отмену стандартного поведения события. Вызов:event.preventDefault();
Внутри пассивного обработчика не остановит стандартное поведение браузера и обычно приведёт к предупреждению в консоли.
window.addEventListener(
'touchmove',
event => {
event.preventDefault();
},
{
passive: true
}
);
passive: true целесообразно использовать, если обработчик только анализирует событие или обновляет интерфейс и ему не требуется вызывать preventDefault(). Если обработчик должен отменять стандартное поведение браузера, его нельзя делать пассивным.preventDefault(). При этом они не устраняют проблемы, связанные с тяжёлыми JavaScript-обработчиками.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤5🔥4🤝3
Атрибут
novalidate используется у тега <form> и отключает стандартную валидацию полей браузером при отправке формы.По умолчанию браузер сам проверяет такие ограничения, как:
• обязательные поля (required);
• корректность email (type="email");
• формат данных (pattern);
• минимальные и максимальные значения (min, max).
После добавления
novalidate эта проверка не выполняется, и отправка формы передаётся полностью под контроль JS или серверной логики. Важно: novalidate не отключает атрибуты в HTML, а только запрещает браузеру автоматически проверять их при отправке.Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🤝9❤6🔥2
Symbol: как добавлять внутренние свойства объектов без конфликтов!
В JavaScript объекты часто используются разными частями приложения, библиотеками и компонентами одновременно. Иногда требуется добавить к существующему объекту дополнительные данные: состояние компонента, метаданные, кэш или внутренние флаги.
Добавление обычных свойств может привести к конфликтам. Если такое имя уже используется другим кодом, одно значение может случайно заменить другое.
Если свойство
Для решения этой задачи существует
Теперь внутренние данные хранятся по уникальному ключу. Объект можно расширять дополнительным состоянием, не изменяя его публичную структуру.
Даже если другой код добавит свойство с похожим названием, конфликт не возникнет:
Symbol-свойства имеют ещё одну особенность: они не отображаются в большинстве стандартных способов перебора объектов. Например,
Это позволяет хранить дополнительные данные внутри объекта, не добавляя их в обычное представление объекта и его публичный API. При необходимости получить символьные свойства можно явно:
Такой подход часто используется в библиотеках и компонентах, которым необходимо хранить внутренние данные, связанные с объектом. Например, можно добавить метаданные компонента:
После этого объект получает внутреннюю информацию, но его внешний интерфейс остаётся неизменным:
Кроме пользовательских символов, JavaScript содержит встроенные
Например,
Важно понимать:
Основная задача
🔥
📣 Code Ready | #практика
В JavaScript объекты часто используются разными частями приложения, библиотеками и компонентами одновременно. Иногда требуется добавить к существующему объекту дополнительные данные: состояние компонента, метаданные, кэш или внутренние флаги.
Добавление обычных свойств может привести к конфликтам. Если такое имя уже используется другим кодом, одно значение может случайно заменить другое.
const element = {
value: "button"
};
element.state = {
mounted: true
};
Если свойство
state уже существует в объекте, новое значение перезапишет старое. В больших приложениях такие ситуации могут быть сложными для поиска, особенно когда объект расширяется несколькими независимыми модулями.Для решения этой задачи существует
Symbol — это примитивный тип данных, который создаёт уникальные ключи свойств объектов. Каждый созданный символ является уникальным, поэтому он не может случайно совпасть с обычным строковым свойством или другим символом.const internalState = Symbol("internalState");
const component = {
value: "button",
[internalState]: {
mounted: true
}
};
console.log(component[internalState]);
// { mounted: true }
Теперь внутренние данные хранятся по уникальному ключу. Объект можно расширять дополнительным состоянием, не изменяя его публичную структуру.
Даже если другой код добавит свойство с похожим названием, конфликт не возникнет:
component.internalState = false;
console.log(component[internalState]);
// { mounted: true }
Symbol-свойства имеют ещё одну особенность: они не отображаются в большинстве стандартных способов перебора объектов. Например,
Object.keys() возвращает только строковые ключи:Object.keys(component);
// ["value"]
Это позволяет хранить дополнительные данные внутри объекта, не добавляя их в обычное представление объекта и его публичный API. При необходимости получить символьные свойства можно явно:
Object.getOwnPropertySymbols(component);
Такой подход часто используется в библиотеках и компонентах, которым необходимо хранить внутренние данные, связанные с объектом. Например, можно добавить метаданные компонента:
const meta = Symbol("meta");
function initComponent(component) {
component[meta] = {
id: crypto.randomUUID(),
createdAt: Date.now()
};
}
После этого объект получает внутреннюю информацию, но его внешний интерфейс остаётся неизменным:
component.id;
// undefined
component[meta].id;
// UUID
Кроме пользовательских символов, JavaScript содержит встроенные
Symbol, которые позволяют изменять стандартное поведение объектов:Symbol.iterator
Symbol.asyncIterator
Symbol.toPrimitive
Например,
Symbol.iterator позволяет объекту поддерживать цикл for...of:const collection = {
items: ["a", "b"],
[Symbol.iterator]() {
return this.items[Symbol.iterator]();
}
};
for (const item of collection) {
console.log(item);
}
Важно понимать:
Symbol не является механизмом настоящей приватности. Символьные свойства можно найти через:Object.getOwnPropertySymbols();
Reflect.ownKeys();
Основная задача
Symbol — создавать уникальные ключи и безопасно расширять объекты без риска конфликтов имён. Для настоящей приватности в классах JavaScript используются #private fields.Symbol — практический инструмент для создания библиотек, компонентов и больших frontend-систем, где требуется добавлять внутренние данные, сохраняя чистый публичный API объекта.Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤8🔥6
Добавляем дополнительную информацию с помощью тега <small>!
Тег
Для чего <small> подойдёт идеально:
• пояснения;
• комментарии;
• дисклеймеры;
• предостережения;
• копирайт;
• информация о лицензии;
• прочая правовая информация.
Важно:
📣 Code Ready | #атрибут
Тег
<small> используется для отображения второстепенного текста, который имеет меньшее значение по сравнению с основным содержимым. Он подходит для информации, которая полезна пользователю, но не является частью основного сообщения.Для чего <small> подойдёт идеально:
• пояснения;
• комментарии;
• дисклеймеры;
• предостережения;
• копирайт;
• информация о лицензии;
• прочая правовая информация.
Важно:
<small> имеет семантическое значение, а не просто уменьшает размер текста. Для изменения визуального размера обычного текста лучше использовать CSS.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10🤝5❤4👍2😁1
HTMLImageElement.decode() — подготовка изображения до появления в DOM!
При динамической подстановке изображений часто возникает ситуация, когда элемент уже добавлен в DOM, но браузер ещё не завершил декодирование изображения. В результате пользователь может увидеть пустую область, задержку появления контента или заметное изменение содержимого после завершения подготовки картинки.
Для таких случаев существует метод
После установки
После успешного выполнения
В таком случае браузеру не требуется выполнять декодирование в момент первого отображения элемента, что помогает избежать визуальных скачков при динамическом обновлении интерфейса.
Метод особенно полезен при динамической замене изображений:
Новая картинка будет установлена только после подготовки браузером, поэтому замена происходит без промежуточного состояния, связанного с декодированием изображения.
Важно учитывать разницу между загрузкой и декодированием. Событие
Эти механизмы решают разные задачи и могут использоваться вместе в зависимости от требований интерфейса.
При ошибке загрузки или невозможности декодировать изображение
Важно учитывать, что
🔥
📣 Code Ready | #практика
При динамической подстановке изображений часто возникает ситуация, когда элемент уже добавлен в DOM, но браузер ещё не завершил декодирование изображения. В результате пользователь может увидеть пустую область, задержку появления контента или заметное изменение содержимого после завершения подготовки картинки.
Для таких случаев существует метод
decode(), который позволяет дождаться момента, когда изображение будет декодировано браузером и готово к безопасному отображению. Создадим объект изображения:const image = new Image();
image.src = '/images/photo.jpg';
await image.decode();
После установки
src браузер начинает загрузку ресурса. Метод decode() не является механизмом загрузки изображения — он ожидает завершения загрузки и последующего декодирования, чтобы браузер не выполнял эту работу непосредственно в момент первого отображения.После успешного выполнения
Promise изображение можно добавлять в DOM:const image = new Image();
image.src = '/images/photo.jpg';
await image.decode();
document.body.append(image);
В таком случае браузеру не требуется выполнять декодирование в момент первого отображения элемента, что помогает избежать визуальных скачков при динамическом обновлении интерфейса.
Метод особенно полезен при динамической замене изображений:
const preview = document.querySelector('.preview');
const nextImage = new Image();
nextImage.src = '/images/next.jpg';
await nextImage.decode();
preview.replaceWith(nextImage);Новая картинка будет установлена только после подготовки браузером, поэтому замена происходит без промежуточного состояния, связанного с декодированием изображения.
Важно учитывать разницу между загрузкой и декодированием. Событие
load сообщает о завершении загрузки ресурса, а decode() отвечает за готовность изображения к отображению без дополнительной подготовки в момент рендера. Например:image.onload = () => {
console.log('Изображение загружено');
};
await image.decode();Эти механизмы решают разные задачи и могут использоваться вместе в зависимости от требований интерфейса.
При ошибке загрузки или невозможности декодировать изображение
Promise будет отклонён:try {
await image.decode();
} catch (error) {
console.error('Не удалось подготовить изображение', error);
}Важно учитывать, что
decode() не решает проблему layout shift (CLS), если размеры изображения заранее неизвестны. Для предотвращения скачков интерфейса рекомендуется задавать размеры через width / height или использовать aspect-ratio. Например:<img src="/images/photo.jpg" width="800" height="600">
decode() широко применяется в современных веб-интерфейсах: галереях, слайдерах, редакторах изображений и компонентах с динамическим обновлением контента, где важно контролировать момент появления изображения.HTMLImageElement.decode() позволяет синхронизировать отображение изображения с процессом его подготовки браузером и избежать визуальных артефактов при динамическом обновлении DOM.Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥8❤5🤝2
This media is not supported in your browser
VIEW IN TELEGRAM
На сайте собраны подробные статьи по фронтенду: HTML, CSS, JavaScript, TypeScript, React, Vue и другим технологиям. Можно найти разборы популярных методов, примеры кода, объяснения сложных тем и решения типичных ошибок, с которыми сталкиваются разработчики.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍8🔥5
Code Ready | Frontend pinned «Всем привет✊ ⠀ Запускаем этот канал, в котором будем делиться ссылками на готовый код для вашего сайта. Этот код будет написан на HTML, CSS или JavaScript. ⠀ Время от времени здесь будет появляться новый код на разные потребности! Мы - ваша готовая библиотека)…»
URLSearchParams — разбираем работу с параметрами URL!
При разработке интерфейсов часто приходится работать с параметрами из адресной строки: фильтры товаров, поиск, сортировка, пагинация или сохранение состояния страницы. Например, есть URL:
Здесь
Получить всю строку параметров можно через:
Результат:
Но ручной разбор через
Для этого в JavaScript есть стандартный API
Теперь получить значение параметра можно через
Результат:
Если параметра нет в URL, метод
Это удобно, когда логика интерфейса зависит от определённых параметров.
Результат:
Метод
Для удаления параметров используется
Если один параметр может иметь несколько значений, например несколько выбранных тегов, используется
Результат:
Для добавления дополнительного значения без замены существующего используется
Также
Результат:
Не нужно вручную вызывать
🔥
📣 Code Ready | #практика
При разработке интерфейсов часто приходится работать с параметрами из адресной строки: фильтры товаров, поиск, сортировка, пагинация или сохранение состояния страницы. Например, есть URL:
https://example.com/products?category=phone&page=2
Здесь
category и page — это query-параметры, которые содержат данные для отображения нужного состояния страницы.Получить всю строку параметров можно через:
const query = window.location.search;
console.log(query);
Результат:
?category=phone&page=2
Но ручной разбор через
split() быстро становится неудобным. Нужно самостоятельно обрабатывать специальные символы, проверять наличие значений и учитывать параметры с одинаковыми именами.Для этого в JavaScript есть стандартный API
URLSearchParams. Он позволяет получать, изменять и удалять параметры URL без ручной обработки строк. Создаём объект на основе query-части текущего URL:const params = new URLSearchParams(
window.location.search
);
Теперь получить значение параметра можно через
get():const category = params.get('category');
console.log(category);Результат:
phone
Если параметра нет в URL, метод
get() вернёт null. Перед чтением значения можно проверить наличие параметра через has():if (params.has('page')) {
console.log(params.get('page'));
}Это удобно, когда логика интерфейса зависит от определённых параметров.
URLSearchParams позволяет не только читать данные, но и изменять их. Например, добавим параметр сортировки:params.set(
'sort',
'price'
);
console.log(
params.toString()
);
Результат:
category=phone&page=2&sort=price
Метод
set() заменяет существующее значение или создаёт новый параметр, если его ещё нет.Для удаления параметров используется
delete():params.delete('page');Если один параметр может иметь несколько значений, например несколько выбранных тегов, используется
getAll():const params = new URLSearchParams(
'tag=js&tag=css'
);
console.log(
params.getAll('tag')
);
Результат:
['js', 'css']
Для добавления дополнительного значения без замены существующего используется
append():params.append(
'tag',
'html'
);
Также
URLSearchParams автоматически кодирует специальные символы. Например:const params = new URLSearchParams();
params.set(
'search',
'frontend developer'
);
console.log(
params.toString()
);
Результат:
search=frontend+developer
Не нужно вручную вызывать
encodeURIComponent() — кодирование выполняется автоматически при преобразовании параметров в строку.URLSearchParams часто используется вместе с фильтрами, роутингом и состоянием интерфейса. Например, каталог товаров может хранить выбранную категорию, сортировку и текущую страницу прямо в URL. При открытии такой ссылки приложение получает параметры и восстанавливает нужное состояние.URLSearchParams — стандартный инструмент JavaScript для работы с query-параметрами, который делает обработку URL проще и избавляет от ручного парсинга строк.Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤7🔥7
This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий помогает понять, из каких деталей состоит frontend-проект и что важно учитывать кроме самой вёрстки и JavaScript-кода. Внутри собраны практические рекомендации по HTML-структуре, CSS, JavaScript, производительности сайта, SEO, доступности, безопасности, оптимизации ресурсов, настройке изображений, метатегов и др.
Оставляю ссылочку: GitHub
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍8🤝5
Эти три тега используются для создания списков описаний, где каждому термину соответствует его определение или пояснение.
Каждый тег выполняет свою роль:
• <dl> — контейнер для всего списка.
• <dt> — термин или название.
• <dd> — описание или значение термина.
Использование этих тегов делает разметку более семантичной и помогает браузерам, поисковым системам и вспомогательным технологиям правильно интерпретировать содержимое.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤12🔥6
Element.replaceChildren() — полная замена содержимого элемента через DOM API!
Для полной замены содержимого элемента часто сначала очищают контейнер, а затем добавляют новые узлы либо используют
Для этой задачи DOM API предоставляет специализированный метод
Очистить элемент можно одним вызовом:
Метод удаляет все дочерние узлы элемента независимо от их типа. Одновременно можно передать новое содержимое, которое заменит существующее:
После вызова прежние дочерние узлы будут удалены, а переданный элемент станет единственным дочерним узлом контейнера. Метод принимает любое количество DOM-узлов:
Также можно передавать строки:
Они автоматически преобразуются в текстовые узлы. Если передать существующий DOM-узел, он будет не скопирован, а перемещён:
Это соответствует общей модели DOM: один узел не может одновременно находиться в нескольких местах дерева. В отличие от
В контейнер будет добавлен обычный текст:
Если требуется вставить HTML-разметку, можно использовать
🔥
📣 Code Ready | #практика
Для полной замены содержимого элемента часто сначала очищают контейнер, а затем добавляют новые узлы либо используют
innerHTML.Для этой задачи DOM API предоставляет специализированный метод
replaceChildren().Очистить элемент можно одним вызовом:
const list = document.querySelector('.list');
list.replaceChildren();Метод удаляет все дочерние узлы элемента независимо от их типа. Одновременно можно передать новое содержимое, которое заменит существующее:
const list = document.querySelector('.list');
const item = document.createElement('li');
item.textContent = 'JavaScript';
list.replaceChildren(item);После вызова прежние дочерние узлы будут удалены, а переданный элемент станет единственным дочерним узлом контейнера. Метод принимает любое количество DOM-узлов:
const container = document.querySelector('.container');
const title = document.createElement('h2');
title.textContent = 'Статьи';
const description = document.createElement('p');
description.textContent = 'Последние публикации';
container.replaceChildren(title, description);Также можно передавать строки:
container.replaceChildren('Загрузка...');Они автоматически преобразуются в текстовые узлы. Если передать существующий DOM-узел, он будет не скопирован, а перемещён:
const card = document.querySelector('.card');
const sidebar = document.querySelector('.sidebar');
sidebar.replaceChildren(card);Это соответствует общей модели DOM: один узел не может одновременно находиться в нескольких местах дерева. В отличие от
innerHTML, метод не разбирает переданные строки как HTML-разметку:container.replaceChildren('<strong>Text</strong>');В контейнер будет добавлен обычный текст:
<strong>Text</strong>
Если требуется вставить HTML-разметку, можно использовать
innerHTML или insertAdjacentHTML(), но только для доверенной либо предварительно санитизированной разметки. Более безопасный вариант — сформировать необходимое дерево DOM-узлов программно.replaceChildren() определён в DOM Standard и позволяет заменить всё содержимое одним вызовом. Это делает намерение кода более явным и избавляет от необходимости отдельно очищать контейнер перед добавлением новых узлов.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍9❤8
Свойство
all позволяет одновременно сбросить или переопределить почти все CSS-свойства элемента. Это удобно, когда нужно убрать влияние внешних стилей и начать оформление с чистого листа.Основные значения:
• initial — сбрасывает свойства к значениям по умолчанию;
• inherit — наследует все свойства от родителя;
• unset — сочетает initial и inherit в зависимости от свойства;
• revert — возвращает стили, заданные браузером или пользовательскими стилями.
all часто используют при создании собственных компонентов, кнопок и виджетов, чтобы быстро избавиться от нежелательных стилей без перечисления каждого свойства отдельно.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥6🤝4❤3
URL.canParse() — нативная проверка URL без try...catch!
При работе с пользовательскими данными часто требуется проверить, может ли строка быть разобрана как URL. Распространённый подход — использовать конструктор
Современный Web API предоставляет более удобный способ — статический метод
Для относительных адресов необходимо передать базовый URL:
Без базового URL такой вызов вернёт
Если нужен только результат проверки,
Если приложение допускает относительные адреса, передайте
Например, URL с протоколом
Перед выполнением запроса удобно сразу получить объект
🔥
📣 Code Ready | #практика
При работе с пользовательскими данными часто требуется проверить, может ли строка быть разобрана как URL. Распространённый подход — использовать конструктор
URL внутри try...catch, поскольку при некорректной строке он выбрасывает исключение:try {
new URL(value);
} catch {
console.log('Не удалось разобрать URL');
}Современный Web API предоставляет более удобный способ — статический метод
URL.canParse(). Он проверяет, может ли строка быть разобрана по алгоритму URL Standard, и возвращает true или false без использования try...catch:URL.canParse('https://example.com');
// true
URL.canParse('not-a-url');
// falseДля относительных адресов необходимо передать базовый URL:
URL.canParse('/users/1', 'https://example.com');
// trueБез базового URL такой вызов вернёт
false, поскольку относительный адрес невозможно разрешить без контекста.Если нужен только результат проверки,
URL.canParse() — оптимальный выбор. Если после проверки требуется объект URL, удобнее сразу использовать URL.parse(), чтобы не выполнять разбор дважды:const url = URL.parse(value);
if (url) {
console.log(url.hostname);
}
URL.parse() возвращает объект URL при успешном разборе и null при ошибке. Например, для проверки пользовательского ввода:const input = document.querySelector('input');
if (!URL.canParse(input.value)) {
input.setCustomValidity('Введите абсолютный URL');
} else {
input.setCustomValidity('');
}Если приложение допускает относительные адреса, передайте
document.baseURI вторым аргументом. Важно понимать, что URL.canParse() проверяет только возможность разбора строки. Метод не проверяет существование ресурса, доступность сервера, допустимость протокола для приложения или безопасность адреса. Например, URL с протоколом
javascript: или data: может успешно пройти проверку. Если приложение принимает только HTTPS, протокол необходимо проверить отдельно:const url = URL.parse(value);
if (url?.protocol === 'https:') {
// дальнейшая обработка
}
Перед выполнением запроса удобно сразу получить объект
URL:const url = URL.parse(apiUrl, document.baseURI);
if (!url || !['http:', 'https:'].includes(url.protocol)) {
throw new Error('Недопустимый адрес API');
}
await fetch(url);
document.baseURI учитывает базовый адрес документа, включая значение элемента <base>. Проверка протокола также не защищает от SSRF, поэтому на сервере необходима дополнительная валидация адресов.URL.canParse() подходит для случаев, когда нужна только проверка возможности разбора URL, а URL.parse() — когда требуется сразу получить объект URL. При использовании этих методов в проектах с поддержкой старых браузеров и устаревших WebView следует учитывать совместимость.Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥5🤝5❤1
Вышла интересная статья на Хабре: «TAMA-90: тамагочи из 90-х своими руками на JavaScript»!
В этой статье:
🔊 Продолжайте читать на Habr!
📣 Code Ready | #статья
В этой статье:
• Показывается, как создать современную версию тамагочи на чистом JavaScript без фреймворков и сторонних библиотек;• Разбирается архитектура проекта, работа с Canvas, localStorage, игровой логикой, случайными событиями и мини-играми;• Объясняется, как программно рисовать пиксельных питомцев, организовать сохранения, коллекцию персонажей и систему развития без готовых спрайтов.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13🤝7❤5
Тег
<abbr> используется для обозначения аббревиатур и сокращений. Благодаря атрибуту title можно указать их полную расшифровку, которую браузер обычно показывает при наведении курсора.Чаще всего <abbr> используют для:
• технических терминов (HTML, CSS, API);
• названий организаций;
• единиц измерения;
• общепринятых сокращений.
Для максимальной пользы рекомендуется всегда указывать атрибут
title с полной расшифровкой сокращения.Please open Telegram to view this post
VIEW IN TELEGRAM
❤17👍11🤝4🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь разобраны основы создания веб-страниц: структура HTML-документа, теги, семантика, CSS-свойства, блочная модель, позиционирование, формы, адаптивная верстка и работа с реальными макетами. Нужно не просто читать материал, а выполнять задания: сверстать блоки, меню, формы, вкладки и полноценную страницу по макету.
Оставляю ссылочку: GitHub
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12🔥8👍6
This media is not supported in your browser
VIEW IN TELEGRAM
Тег
<canvas> добавляет растровый холст на страницу. Этот холст можно использовать для отрисовки 2D- или 3D-графики, анимаций, видео.Он используется для:
• интерактивных графиков и диаграмм;
• анимаций и визуальных эффектов;
• браузерных игр;
• обработки изображений;
• 2D- и 3D-графики через Canvas API и WebGL.
Для работы с холстом обычно получают один из контекстов:
• 2d — обычная двумерная графика;
• webgl — аппаратно ускоренная 3D-графика.
Элементы, нарисованные внутри
<canvas>, не являются отдельными DOM-элементами — браузер воспринимает их как единое изображениеPlease open Telegram to view this post
VIEW IN TELEGRAM
👍17❤10🔥5
🔴 Тестовое собеседование на Frontend-разработчика со старшим разработчиком ex. Сбер
13 августа(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
📂 Даниил Дмитриев, старший разработчик в R-Vision, ex. Сбер, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Даниил будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Даниилу
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе.
13 августа(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
📂 Даниил Дмитриев, старший разработчик в R-Vision, ex. Сбер, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Даниил будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Даниилу
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе.
❤1
Почему CSS-переменные раньше не анимировались?
Многие пытаются сделать так:
Но обычная CSS-переменная — это просто строка. Браузер не знает, как плавно перейти от
Регистрируем переменную через
Теперь браузер знает тип значения и умеет интерполировать его.
Остаётся использовать переменную как обычно.
И менять её значение.
Теперь поворот происходит плавно без JS.
🔥
📣 Code Ready | #совет
Многие пытаются сделать так:
.box {
transition: --angle .3s;
}Но обычная CSS-переменная — это просто строка. Браузер не знает, как плавно перейти от
0deg к 180deg, поэтому анимация не работает.Регистрируем переменную через
@property.@property --angle {
syntax: "<angle>";
}Теперь браузер знает тип значения и умеет интерполировать его.
Остаётся использовать переменную как обычно.
.box {
transform: rotate(var(--angle));
}И менять её значение.
.box:hover {
--angle: 180deg;
}Теперь поворот происходит плавно без JS.
@property превращает CSS-переменные из обычных строк в типизированные значения, которые можно валидировать и анимировать. Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🔥9❤7