Skip to content
NativeCSS
Docs contents

Touch & Mobile Viewports

Two topics that stay invisible on desktop and only show up on real devices.

Touch Devices Have No Hover

A tap on iPhone/Android doesn't reliably trigger :hover rules - a button whose only visual feedback is a :hover state therefore feels completely dead on touch. Every visually significant :hover rule in ncss is therefore wrapped in @media (hover: hover) and (pointer: fine) (only devices with a real pointing device), never unconditional. :focus-visible (keyboard focus) always stays ungated by this.

Tactile Feedback: :active Instead of :hover

For tactile feedback on touch, :active applies (works for every pointing device including touch, no gate needed) - .ncss-btn has its own, component-wide :active state (scale: 0.95) and every color variant additionally gets a real color change on :active (the same values as :hover, just unconditional).

A tap often lasts only ~100-150ms - the normal transition duration (200ms) frequently doesn't even reach its target value in that time. A dedicated token --ncss-motion-duration-fast (100ms), overridden only as transition-duration on the :active rule itself - the entry into the pressed look is thereby fast, the spring-back stays at the normal, softer duration.

For a custom element: .ncss-press (helpers/animations.css, likewise :active-based with the same fast entry, combinable with any element).

<div class="ncss-card ncss-press">Any element with tap feedback</div>

Full Screen Height on Mobile

100vh/height: 100% correspond on mobile browsers to the largest possible height (address bar hidden) - if the address bar is currently visible, a 100vh element extends beyond the actually visible area.

UnitBehaviorUse in ncss
svhSmallest possible value, always fitsModal, off-canvas, .ncss-sticky-container - elements that must stay guaranteed visible without scrolling (with vh as fallback: height: 100vh; height: 100svh;)
lvhIdentical to classic vh - stable, doesn't change while scrollingcomponents/scroll-stack.css - scroll-linked animations need timing that doesn't get recalculated mid-scroll
dvhRecalculates live as soon as the address bar shows/hidesDeliberately NOT used for scroll-linked animations (known jank behavior in mobile Safari)
.ncss-full-height {
  height: 100vh;   /* fallback for older browsers */
  height: 100svh;  /* wins where supported - always fits */
}