TGViewer
<divelopers> <divelopers> @alexnozer_dev · 1.18K subscribers
Post #378 705
Вредные компоненты без JS

Мне нравится идея создания компонентов без JS. Видео Native CSS Components vs Modern UI Libraries показывает реализацию нескольких компонентов на HTML/CSS и сравнивает их с аналогами из Shadcn.

Компоненты в Shadcn действительно переусложнены. Но у показанных в видео аналогов есть проблемы. Рассмотрим, что не так с каждой реализацией и как можно сделать лучше (сейчас или в будущем).

Диалог

Диалог реализован с помощью Popover API. popover не задаёт нужную семантику. <div popover> остаётся контейнером с role="group". У диалога должна быть соответствующая семантика, состояния, поведение и UX.

Есть <dialog>, который обладает нужной семантикой и свойствами. Он работает с popover для немодальных диалогов, а с command для модальных и немодальных. Атрибут closedby="any" добавляет закрытие по нажатию вне диалога.

<!-- немодальный диалог с popover -->
<button
popovertarget="dlg"
popovertargetaction="show"
>
Open dialog
</button>
<dialog id="dlg" popover>
...
<button
popovertarget="dlg"
popovertargetaction="hide"
>
Close
</button>
</dialog>

<!-- немодальный диалог с command -->
<button
commandfor="dlg"
command="show-popover"
>
Open dialog
</button>
<dialog id="dlg" popover>
...
<button
commandfor="dlg"
command="hide-popover"
>
Close
</button>
</dialog>

<!-- модальный диалог с command и closedby -->
<button
commandfor="dlg"
command="show-modal"
>
Open dialog
</button>
<dialog id="dlg" closedby="any">
...
<button
commandfor="dlg"
command="close"
>
Close
</button>
</dialog>


Выпадающее меню


В видео выпадающее меню реализовано с помощью popover и Anchor Positioning. Как и с диалогом, меню не обладает нужной семантикой и поведением. Dropdown menu в Shadcn реализован как элемент с ролью menu.

Виджет menu предназначен для команд, а не навигационных ссылок. Внутри допустимы только определённые роли. Требуется навигация стрелками и Home/End. Для этого нужен JS. Всё может измениться с приходом focusgroup, но пока это экспериментальный API.

<button
commandfor="menu"
command="toggle-popover"
>
Open menu
</button>
<div
id="menu"
role="menu"
popover
focusgroup="menu"
>
<button role="menuitem">
Profile
</button>
<button role="menuitem">
Settings
</button>
<button role="menuitem">
Sign out
</button>
</div>


Всплывающая подсказка


В видео отображение подсказки реализовано через :hover/:focus и комбинатор ~. Роль подсказки — tooltip, а кнопка ссылается на неё через aria-describedby. Такая всплывающая подсказка нарушает критерий WCAG 1.4.13 Content on Hover or Focus.

Реализация поведения для соответствия 1.4.13 требует JS. Можно использовать popover с его закрытием по Esc, но отображение потребует JS. Interest Invokers API и popover="hint" позволят в будущем реализовать это без JS.

<button
interestfor="copy"
aria-describedby="copy"
>
Copy
</button>
<span
id="copy"
popover="hint"
role="tooltip"
>
Hover or focus me
</span>


Вкладки


Вкладки реализованы как набор радио-кнопок, которые в сочетании с псевдо-классом :checked и селектором :has() у родителя переключают дочерние панели. Вновь не хватает нужной семантики и поведения и в целом это хак.

На канале есть разбор вкладок с использованием ссылок <a> и псевдо-класса :target и почему это не вкладки. То же с радио-кнопоками и :has(). Реализовать вкладки без JS сейчас нельзя, но, возможно, появятся новые элементы или примитивы.

Аккордеон

На последок виджет аккордеона. В видео он сделан из нескольких <details> и <summary>. Также демонстрируется новый псевдо-элемент ::details-content и свойство interpolate-size: allow-keywords для анимации раскрытия.

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

#html #css #js #ui
  • 👍 7
  • ❤ 1
  • 🤝 1
More from @alexnozer_dev
  1. Sep 21, 2026Реализация пользовательских атрибутов Под конец прошлого года я рассказывал об API пользов…
  2. Sep 14, 2026Подклассы Event вместо CustomEvent Многие библиотеки предоставляют систему событий в качес…
  3. Sep 11, 2026Эволюция стилей в темах Shopify Адам Ватан на днях поделился новостью, что Shopify выкупил…
  4. Sep 9, 2026Persistent Widgets Многие сайты не должны быть SPA. Но иногда эта архитектура продиктована…
  5. Sep 7, 2026Processing Instructions и маркеры В DOM всё представлено в виде узлов (Node) разных типов.…
  6. Sep 1, 2026@scope и потоковая передача HTML Ноам Розенталь поделился интересной техникой, в которой с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →