Записки фронтендера
423 subscribers
145 photos
42 videos
1 file
160 links
Все самые свежие обновления в мире Frontend

Бесплатная реклама твоего проекта
https://votby.ru

Общий чат
@fe_notes_chat

Чат помощи с поиском работы
@fe_notes_help

Написать в лс @usersavchenko
Download Telegram
Проблема с соотношением сторон была решена!

Ранее, чтобы добиться динамического соотношения сторон HTML элемента, приходилось придумывать разные костыли:
.container {
width: 100%;
padding-top: 56.25%;
}


С появлением свойства aspect-ratio, всё стало гораздо проще:
.container {
width: 100%;
aspect-ratio: 16 / 9;
}

Первым числовым аргументом указываем соотношение по ширине, а вторым по высоте. Теперь как бы мы не изменяли width, height будет подстраиваться автоматически.

Также у свойства есть и другие варианты синтаксиса.

🟢 Сокращённый вариант
aspect-ratio: 5; 

Он будет аналогичен этому
aspect-ratio: 5 / 1;


🟢 С ключевым словом auto
aspect-ratio: auto 16 / 9;

Он предназначен для элементов, которые изначально уже имеют собственную ширину и высоту (<img>, <video>, <canvas>, <iframe> и др.)

Суть такой записи в том, что если у элемента имеется собственное соотношение сторон, то 16 / 9 применено не будет и наоборот, если его нету (к примеру это <div> или <p>), то будет.

⚙️ Поддержка браузерами полная
🔥2
Please open Telegram to view this post
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Случайно наткнулся на очередной прикольный сервис, в котором удобно сравнивать характеристики пакетов.

Он включает в себя:
— Количество скачиваний за любой промежуток времени
— Количество звёзд и issues на github
— Дату последнего обновления
— Дату первой публикации пакета
— Размер при скачивании

npmtrends.com
👍1
В CSS добавили условные функции 🤯

В 137 версии Chrome были добавлены функции if(), style(), media() и supports(), благодаря которым теперь можно создавать свойства с множеством значений, которые применяются в зависимости от переданных условий.

Разберём пример:
.container {
--type: button;
width: 100px;
height: 100px;
background: if(
style(--type: card): blue;
style(--type: button): green;
else: yellow;
);
}

Внутри функции if() первыми двумя style() мы указываем проверку равенства CSS переменной --type определённому значению и передаём значение, которое должно быть возвращено в случае совпадения. Если ни одно из условий не будет удовлетворено, то будет возвращено содержимое else.

media() и supports() работают похожим образом, но указывают условия для медиа-выражений и для проверки поддерживаемости каких-либо свойств:
.card {
width: if(
media(min-width: 800px): 400px;
supports(display: grid): 100%;
else: auto
);
}


⚙️ Поддерживается пока что только в Chrome и Edge
👍5
Как вы знаете, React не умеет "в директивы" как например тот же Vue или Angular.

Эта проблема становится особенно болезненной, когда у нас в проекте появляются сложные многоуровневые блоки с условиями ввиде тернарных операторов:
<div>
{isLoading ? (
<p>Загрузка...</p>
) : status === 'error' ? (
<p>Произошла ошибка!</p>
) : status === 'success' ? (
isAdmin ? (
<p>Добро пожаловать, администратор.</p>
) : (
<p>Добро пожаловать, пользователь.</p>
)
) : (
<p>Непредвиденная ошибка</p>
)}
</div>

Выше представлен сильно упрощённый пример, но даже он достаточно сложен в восприятии.

Одно из решений этой проблемы — библиотека react-if
Она помогает разгрузить такой код блоками:
1) <If />
2) <Then />
3) <Else />
4) И многими другими...

Например:
<If condition={isAdmin}>
<Then>
<p>Добро пожаловать, администратор.</p>
</Then>
<Else>
<p>Добро пожаловать, пользователь.</p>
</Else>
</If>


⚡️ Ссылка на NPM
⚡️ Ссылка на Bundlephobia
⚡️ Ссылка на npmpackage.info
❤4👎3🤮3🔥1
Media is too big
VIEW IN TELEGRAM
Свойству text-wrap добавили новые значения

balance — разбивает текст так, чтобы в каждой строке было примерно одинаковое количество символов.

pretty — использует более сложный и медленный алгоритм, который позволяет предотвращать появление в последней строке "сирот" из одного слова и прочих эстетических недостатков. Подробнее об алгоритме можно почитать в этом документе.

⚙️ Поддержка браузерами пока что неполная: balance, pretty
🔥5
Новый семантический тег

В HTML5 было добавлено много различных тегов вроде <header>, <footer>, <nav> и других. Скорее всего вы все их знаете.

Относительно недавно к этому списку был добавлен новый — <search>

Он должен быть использован в качестве обёртки для полей поиска или фильтрации / сортировки чего-либо:
<search>
<form action="/search">
<input type="search" placeholder="Поиск" />
<button type="submit">Найти</button>
</form>
</search>


<search>
<label>
Сортировать:
<select name="sort">
<option value="price_asc">Цена ↑</option>
<option value="price_desc">Цена ↓</option>
</select>
</label>
</search>


Если вы ранее пользовались ARIA-атрибутом role со значением search для доступности, то при использовании <search> он больше не нужен.

<form role="search">...</form>

заменяем на
<search>
<form>...</form>
</search>


⚙️ Поддержка браузерами широкая
Media is too big
VIEW IN TELEGRAM
Решена проблема с внешними скроллами

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

Стандартным решением этой проблемы является отключение скролла у всей страницы вцелом при помощи:
body.modal-open {
overflow-y: hidden;
}


Но что, если мы хотим сохранить внешний скролл и просто изменить это поведение?

Это стало возможным с появлением свойства overscroll-behavior

Свойство имеет 3 возможных значения:
1) auto (по-умолчанию) — при достижении края внутреннего скролла, взаимодействие автоматически переходит на внешний
2) contain — отключает переход на внешний скролл, но сохраняет "отскок" на мобильных устройствах при достижении края прокрутки
3) none — отключает переход на внешний скролл и отключает "отскок" на мобильных устройствах при достижении края прокрутки

⚙️ Поддержка браузерами широкая
👍4
Media is too big
VIEW IN TELEGRAM
Lazy Loading стал доступным нативно!🔥

Ранее, чтобы подгрузить картинку только в тот момент, когда она нужна, использовали различные библиотеки или писали собственные решения на основе IntersectionObserver. Это было достаточно муторно.

Недавно в HTML был добавлен атрибут loading, который позволяет делать это нативно и без кучи дополнительного кода:
<img src="image.png" loading="lazy">


Атрибут имеет 2 возможных значения:
1) eager — подгружает изображение немедленно (значение по-умолчанию)
2) lazy — подгружает изображение только тогда, когда пользователь приблизился к изображению в результате скролла

Он также работает c <picture> и <iframe>
<picture>
<source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">

<img src="image.png" loading="lazy">
</picture>


<iframe
src="someresource.com"
loading="lazy"
width="560"
height="315"
>
</iframe>


⚙️ Поддержка браузерами широкая
🔥5❤1
CSS не перестаёт удивлять

В 138 версии Chrome были добавлены 2 функции: sibling‑index() и sibling‑count()

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

Вариантов применения уйма, для простоты понимания представлю самые базовые:
.child {
width: calc(sibling-index() * 100px);
}

.child {
width: calc(100% / sibling-count() - 30px);
}


⚙️ Поддерживаются пока что только в Chrome: sibling-index(), sibling-count()
😱3🔥2
Новое значение для width / height — stretch

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

Для решения этой проблемы свойствам width, height и другим подобным было добавлено новое значение — stretch

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

⚙️ Поддержка браузерами пока что средняя
👍4🔥3
Новый API для работы с куками

Большинство разработчиков скорее всего сейчас вспомнят о document.cookie. Он сильно неудобен тем, что запись, удаление и другие операции приходится производить вручную. Также он синхронный и не может быть использован внутри сред, где не поддерживается document, например в web воркерах.

Для простоты работы с куки были даже созданы отдельные библиотеки вроде js-cookie или cookie-universal. Но так или иначе это решало проблему лишь наполовину.

Именно поэтому и был создан Cookie Store API, решающий все вышеперечисленные проблемы.

Краткий обзор его возможностей:
1) cookieStore.get(name) — возвращает промис с куки по имени
2) cookieStore.getAll() — возвращает промис с массивом всех кук
3) cookieStore.set(name, value) — создаёт или обновляет указанную куку, возвращает промис
4) cookieStore.delete(name) — удаляет куки по имени, возвращает промис
5) cookieStore.addEventListener('change', (event) => { ... }) — позволяет следить за изменением кук

⚙️ Поддержка браузерами широкая
👍13⚡3🔥2🍾1
В JS добавлен новый оператор — using 🔥

Если вы ранее работали с файлами в Node.js, то знаете, что при чтении файла каждый раз необходимо закрывать соединение за собой:
import { open } from "node:fs/promises";

let fileHandle;

try {
fileHandle = await open("thefile.txt", "r");
} finally {
await fileHandle?.close();
}


С появлением оператора using теперь это стало делать проще, при помощи функции очистки.

Она выполняется автоматически как только интерпретатор доходит до последней строки блока (в нашем случае это if):
import { open } from "node:fs/promises";

const getFileHandle = async (path: string) => {
const fileHandle = await open(path, "r");

return {
fileHandle,
[Symbol.asyncDispose]: async () => {
await fileHandle.close();
},
};
};

if (condition) {
await using fileHandle = await getFileHandle("thefile.txt");
// какой-то другой код, закрытие соединения ещё не происходит
} // вызов функции очистки


Как можно увидеть из примера, чтобы всё завелось, нам также потребовался Symbol с функцией очистки. Использовался Symbol.asyncDispose(), т.к. очистка асинхронная, для синхронных операций нужен Symbol.dispose().

Но это не просто "синтаксический сахар". В случае с return / break / continue / throw очистка будет выполнена до их выполнения, что гарантирует, что у нас не будет непредвиденных утечек памяти. То есть, даже если во время выполнения кода, внезапно появится ошибка, то сначала будет выполнена очистка, а уже затем интепретатор перейдёт к обработке этой самой ошибки.

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

⚙️ Поддержка браузерами пока что средняя
❤4👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Атрибут inert

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

Различия:
1) disabled меняет стиль встроенных элементов вроде <button> или <input>, а inert нет

2) Оба игнорируют события вроде кликов, но на элементы с inert перестают действовать даже псевдоклассы вроде :hover или :active

3) Элемент с inert полностью удаляется из Accessibility Tree как если бы ему добавили aria-hidden="true"

4) inert распространяется на всё поддерево ниже, disabled если не брать в расчёт <fieldset>, то только на отдельные элементы

5) inert блокирует выделение текста на элементе, а disabled нет

6) При поиске при помощи Ctrl + F, disabled элемент будет найден, а inert нет

7) Фокус на элементах и с inert и disabled не работает, но если использовать <fiedset> с disabled, то потомкам будет доступна фокусировка

⚙️ Поддержка браузерами широкая
👍5❤1
Функцию attr() проапгрейдили

Ранее она работала только с content, теперь же может быть использована с любым свойством. Также были добавлены новые параметры и синтаксис функции теперь выглядит так:
attr(<attr-name> <attr-type>? , <fallback-value>?)


<attr-name> — имя атрибута, из которого будет браться значение
<attr-type> — тип передаваемого значения
<fallback-value> — запасное значение на случай, если будет передано значение некорректного типа или не будет передано вовсе

Пример:
<div data-width="100px"></div>

width: attr(data-width type(<length>), 200px);


Без type(<length>) работать не будет, т.к. значение будет воспринято как raw-string (значение по-умолчанию):
width: attr(data-width raw-string, 200px);


В качестве <attr-type> можно также передавать единицы измерения, * или raw-string, упомянутый ранее:
<div data-width="100"></div>

width: attr(data-width px, 200px);


Также можно передать сразу несколько типов, разделяя их "|"

🔗 Подробнее можно почитать на MDN
⚙️ Поддержка браузерами пока что небольшая
🔥7
This media is not supported in your browser
VIEW IN TELEGRAM
React Bits

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

Отличное решение для промо-страниц вашего сайта.

Библиотека не является стандартной и не выгружена на NPM. Весь необходимый код можно скопировать прямо из документации или скачать при помощи CLI.
🔥5🤔1
Media is too big
VIEW IN TELEGRAM
В CSS добавили новые формы скругления! 🔥

В 139 версии Chrome добавили новое свойство corner-shape, которое вместе с общеизвестным border-raduis позволяют образовывать не только эллиптические скругления, но и квадратные, угловые, ромбовидные и другие.

Возможные значения:
round — классическое эллиптическое скругление
(эквивалентно superellipse(1))

bevel — прямой диагональный срез
(эквивалентно superellipse(0))

scoop — впадина, обратна эллипсу
(эквивалентно superellipse(-1))

notch — прямой (90°) угол внутрь
(эквивалентно superellipse(-infinity))

square — ничего не меняет, визуально
совпадает с border-radius: 0, по сути полезно только для плавных анимаций (эквивалентно superellipse(infinity))

squircle — промежуточная форма между эллипсом и квадратом (эквивалентно superellipse(2))

superellipse(K) — функция для создания суперэллиптической кривой

🔗 Ссылка на спецификацию
🔗 Ссылка на статью с подробным обзором

⚙️ Поддерживается пока что только в Chrome
👍10🔥2❤1
В CSS появились кастомные функции! 🔥

В 139 версии Chrome добавили новую директиву @function, которая работает аналогично функциям из языков программирования. Она принимает параметры и возвращает какое-либо значение на их основе. Впоследствии мы её можем использовать с любым CSS свойством.

Например:
@function --opacity(--color, --opacity) {
result: rgb(from var(--color) r g b / var(--opacity));
}

div {
background-color: --opacity(red, 50%);
}

Эта функция позволяет получить нужный оттенок цвета при помощи процентов прозрачности.

🔗 Ссылка на спецификацию
🔗 Видео обзор других примеров использования

⚙️ Поддержка браузерами
👍7🔥1
Новый статический метод промисов

В ES2025 промисам был добавлен метод try, позволяющий удобно обернуть выполнение функции в промис

Например:
Promise.try(getUsers)
.then((result) => {
// Успешное выполнение функции
})
.catch((error) => {
// Возникла ошибка
})

Этот метод можно использовать как с синхронными, так и с асинхронными функциями. Фишка заключается в том, что мы можем переиспользовать .catch() для обоих типов функций, полностью отбросив блоки try...catch

Синтаксис:
Promise.try(func, arg1, arg2, ..., argN)

🔹 func (обязательный) — функция, которая выполняется сразу
🔹 arg1, arg2, ..., argN (необязательные) — аргументы, передаваемые этой функции

Ранее добиться того же эффекта можно было, но пришлось бы написать вот такую громоздкую конструкцию:
new Promise(resolve => resolve(func()))


⚙️ Поддержка браузерами широкая
👍3🔥3
Псевдоэлементы для работы с текстом

Не все знают о современных возможностях стилизации текста при помощи CSS. Исправляем это!

::selection — стилизует выделенный пользователем текст

::target-text — стилизует фрагмент якорного текста, к которому был осуществлён переход по типу mysite.com#:~:text=hello

::spelling-error — стилизует текст с орфографическими ошибками

::grammar-error — стилизует текст с грамматическими ошибками

Прошу обратить внимание на то, что каждый псевдоэлемент в этой статье является ссылкой на MDN, которая позволяет узнать о нём поподробнее. Но наиболее интересным вам, скорее всего, будет раздел Allowable properties, который имеется почти у каждого псевдоэлемента. В нём указаны все доступные для него CSS свойства.

Также я сознательно не написал о ::highlight() из нового Custom Highlight API, т.к. это более сложный псевдоэлемент, который заслуживает отдельной статьи.

⚙️ Поддержка браузерами хорошая: ::selection, ::target-text, ::spelling-error, ::grammar-error
👍7