defuss-shadcn / Guides / native-web-apis
Native Web APIs
If the browser can do it, we don't write JavaScript for it. defuss-shadcn builds on modern browser APIs instead of third-party libraries.
On this page (2)
§The native-first principle
Traditional component libraries ship thousands of lines of JavaScript to implement behaviors that browsers now provide natively - dropdown positioning, modal focus trapping, popover light-dismiss, auto-growing textareas. defuss-shadcn eliminates that JavaScript entirely by building on the platform.
<!-- Dropdown: Floating UI + JS toggle + click-outside + focus trap + scroll lock + virtual positioning --><div class="dropdown-trigger" onclick="..."> Open Menu</div><div class="dropdown-panel" style="position:absolute;top:...;left:..."> ...</div><!-- Popover API + CSS Anchor Positioning Browser handles: positioning, light-dismiss, top-layer, and auto-flip --><button popovertarget="menu"> Open Menu</button><div id="menu" popover class="dropdown-content"> ...</div>§API reference
Every native API available for the component library, what it replaces, and where it applies.
| Native API | Replaces | Components |
|---|---|---|
| HTML Elements & Attributes | ||
<dialog> | JS modal + overlay + focus trap | Dialog, Alert Dialog, Sheet, Command |
<details>/<summary> | JS toggle + height animation | Accordion, Collapsible |
<details name> (exclusive) | JS single-expand accordion logic | Accordion (single mode) |
<progress> | Custom div-based progress bars | Progress |
<meter> | Custom gauge components | Password strength, storage indicators |
<output> | Manual aria-live regions | Slider displays, form totals, live results |
inert | JS focus trap + aria-hidden toggling | Overlays, collapsed sidebars, loading states |
| Popover API | JS show/hide, z-index management, click-outside | Popover, Dropdown, Tooltip, Toast, Combobox, Context Menu, Nav Menu |
popover="hint" | Custom tooltip z-index management | Tooltip, descriptive hovers |
Invoker Commands (commandfor/command) | JS click handlers calling showModal()/togglePopover() | Dialog, Alert Dialog, Sheet, Popover |
| CSS Layout & Positioning | ||
| CSS Anchor Positioning | Floating UI, Popper.js | Dropdown, Popover, Tooltip, Combobox, Nav Menu |
| Container Queries | Viewport media queries | Card, Table |
| Subgrid | Manually synchronized column widths | Form layouts, settings pages, description lists |
| Logical properties | Separate LTR/RTL stylesheets | All components (RTL support) |
Dynamic viewport units (dvh/svh/lvh) | JS innerHeight hacks for mobile chrome | Full-screen overlays, mobile layout |
| CSS Animations & Transitions | ||
@starting-style + allow-discrete | JS class toggling for enter/exit animations | All overlays (Dialog, Sheet, Dropdown, Tooltip, Command, Accordion) |
| Individual transforms | Compound transform strings | Accordion, composable animations |
interpolate-size: allow-keywords | JS height measurement + max-height hacks | Accordion, Collapsible, expanding UI |
| Scroll-driven animations | Scroll listeners + IntersectionObserver for effects | Progress indicators, scroll reveals, parallax |
| View Transitions API | JS DOM-diffing + class-toggled crossfades | SPA navigation, tab switches, list reordering |
@property | JS-animated values, non-animatable custom properties | Progress rings, gradient transitions |
| CSS Colors & Theming | ||
oklch() + relative color syntax | Hardcoded hex/hsl, manual color derivation | All tokens, all focus/hover states |
color-mix() | Sass darken()/lighten(), hardcoded variants | Hover/disabled states, tinted backgrounds |
light-dark() | Media queries or class toggles for dark mode values | Inline light/dark switching |
color-scheme | Manual dark overrides on native controls | Design tokens (global) |
accent-color | Custom-styled replacement form controls | Slider, Checkbox, Radio, Progress |
| CSS Selectors & Pseudo-classes | ||
:has() | JS class propagation | Label, Tabs, Avatar, Form |
:focus-visible | JS focus-ring detection | All interactive components |
:user-valid / :user-invalid | JS blur + class toggling for validation | Input, Textarea, Select, Checkbox |
:is() / :where() | Repeated selectors, specificity hacks | Component resets, grouped selectors |
::backdrop + backdrop-filter | JS-managed overlay divs, canvas blur | Dialog, Alert Dialog, Sheet, Command |
::details-content | JS measured height + animation | Accordion, Collapsible |
:popover-open | JS class toggling for open state | All popover components |
:indeterminate | JS class for indeterminate state | Progress, Checkbox |
| CSS Typography & Form | ||
text-wrap: balance | JS text-balancing libraries | Typography (headings) |
text-wrap: pretty | Manual for orphan prevention | Typography (body text) |
field-sizing: content | JS auto-resize scripts | Textarea, Input |
hanging-punctuation | Negative text-indent hacks | Blockquotes, pull quotes |
| CSS Scrolling | ||
scroll-snap | JS snap-to-slide calculations | Carousel |
overscroll-behavior: contain | JS scroll-lock libraries | Command, Dropdown, Sheet, Scroll Area |
scrollbar-gutter: stable | Padding hacks for scrollbar width | Command, Scroll Area |
| CSS Architecture | ||
CSS nesting / @layer | Sass, Less, PostCSS | All components |
@scope | BEM naming, Shadow DOM, CSS modules | Scoped component styles |
@supports | Modernizr, JS feature detection | Progressive enhancement |
@media (scripting) | <noscript> only | No-JS fallbacks |
CSS math (clamp/min/max/round) | JS responsive calculations | Fluid typography, responsive spacing |
content-visibility | JS lazy rendering | Accordion, Collapsible, Tree View |
| CSS Accessibility | ||
prefers-reduced-motion | No motion accommodation | All animated components (critical for a11y) |
prefers-color-scheme | JS-only dark mode detection | Auto dark mode |
prefers-contrast | No contrast accommodation | All components (high contrast support) |
forced-colors | Broken styles in Windows High Contrast | All components (system color fallbacks) |
| JavaScript APIs | ||
| Web Animations API | CSS class toggling for sequenced animations | Toast |
Intl.DateTimeFormat | moment.js, date-fns | Calendar |
Intl.NumberFormat | numeral.js, manual formatting | Statistic, Number Input |
Intl.RelativeTimeFormat | timeago.js, moment .fromNow() | Timeline, activity feeds |
Intl.ListFormat | Manual join/comma logic | Tag lists, multi-select displays |
| Drag and Drop API | SortableJS, drag libraries | Sortable |
CustomEvent | Framework event buses | Calendar, inter-component communication |
checkVisibility() | Manual offset/dimension calculations | Tree View |
IntersectionObserver | Scroll listeners + getBoundingClientRect() | Lazy loading, infinite scroll, reveal effects |
ResizeObserver | Window resize listeners + polling | Responsive components, Carousel |
MutationObserver | Polling loops, framework lifecycle | Auto-init for dynamically added components |
| Clipboard API | execCommand('copy') | Copy buttons, share links, code blocks |
CloseWatcher | Manual Escape key listeners | Custom overlays, full-screen views |
ElementInternals | Hidden <input> proxy patterns | Custom form controls (Web Components) |
FormData | Manual value collection loops | Form, search, filters |
AbortController | Boolean flags, manual cleanup | Search-as-you-type, debounced fetches |
structuredClone() | lodash cloneDeep, JSON round-trip | State management, undo/redo |
| Navigation API | History API hacks, router libraries | SPA router, pagination |
| Selection API | Range/offset calculations | Text editors, annotation features |
| View Transitions API (JS) | DOM-diffing + class-toggled crossfades | SPA navigation, content swaps |
These APIs are supported in the latest versions of Chrome, Edge, Firefox, and Safari. Some newer features (Invoker Commands, CSS Anchor Positioning, ::details-content, field-sizing, interpolate-size, View Transitions, Scroll-Driven Animations) may have varying cross-browser support - check Baseline for current compatibility status and each component's component-skill.md for the specific APIs used.
Comments, ideas or improvements? Edit this page's source on GitHub