Advertisement

Polygon Sliced Theme Toggle Navbar

| by Vladimir | 2 min read | code by Jhey Tompkins
A11y Ready Advanced

Tech & Dependencies

HTML CSS Babel
normalize.css

Features

  • View Transitions
  • Trigonometric Hover
  • State Management

Browser Support

Chrome 111+ Edge 111+ Firefox 121+ Safari 17.4+

Core

This is a Polygon Sliced Theme Toggle Navbar. It handles global light/dark mode switching and primary site navigation. Its function is to provide fluid, state-driven visual feedback using native browser APIs, eliminating abrupt visual jumps during context shifts.

Specs

  • Weight: ~5 KB. Minimal payload.
  • Performance: High. Uses GPU-accelerated clip-path and translate. [!] The View Transitions API freezes the DOM momentarily to capture rasterized states; overuse on complex pages may cause micro-stutters.
  • Theming / Customization: Controlled entirely by CSS variables (--bg, --nav, --color) tied to .dark and .light root classes.
  • Responsiveness: Native CSS grid/flexbox logic. Mobile menu relies on a checkbox hack (:has(#menu:checked)) rather than JavaScript.
  • Web APIs: View Transitions API.
  • Graceful Degradation: If document.startViewTransition is not supported, the theme switches instantly. If CSS :has() is missing, the spatial nav hover effect degrades to a standard single-item hover.

Anatomy

  • HTML: Semantic structure. A <nav> for routing, a hidden checkbox for mobile toggling, and an <button aria-pressed="false"> for accessible theme switching.
  • CSS: The core engine. It manages complex sibling interactions via :has(), computes spatial offsets using trigonometric functions (sin()), and defines the custom ::view-transition logic.
  • JS: A minimal trigger. It intercepts the click, checks for API support, and wraps the DOM class change inside the startViewTransition method.

Logic

The architectural highlight is the integration of the View Transitions API with CSS polygon clipping.

const flip = () => {
  if (!document.startViewTransition) applyChange()
  document.startViewTransition(() => applyChange())
}
::view-transition-new(root) {
  z-index: 2;
  animation: slice 1s;
}
/* @keyframes slice applies a dynamic clip-path: polygon() */

JavaScript merely signals the intent to change state. The browser automatically screenshots the old and new states. CSS then targets the ::view-transition-new(root) pseudo-element, applying a complex @keyframes animation that visually “slices” the new theme over the old one using a moving clip-path: polygon().

Feel

Mechanical and deliberate. The navigation links react spatially to the cursor, pushing adjacent items away with organic trigonometric easing. The theme toggle executes a sharp, systematic slice across the viewport. It feels deeply integrated into the browser’s rendering engine, rather than layered on top.

Advertisement