Navigation✨ Premium

Bracket Hover

[ ] brackets that slide in and fade on hover — 100% CSS navigation effect, no JavaScript, compatible with any framework.

CSSText

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Navigation has 36 effects, including 4 free. Explore the category →

3 usage examples

Main navigation bar — Agency or portfolio site — Bracket Hover example 1

① Main navigation bar — Agency or portfolio site

WhenHorizontal navigation on a portfolio, creative agency, or dark-mode SaaS site — 3 to 6 short menu items.
WhyThe bracket effect is understated and directional: it signals the hovered item without icons or loud colors, suiting visual identities that rely on typography.
Settings--space-8: 2.5rem to spread short items, transition: .2s for a snappier feel, hover color --text-primary: #e2e8f0 if the background is not pure black.
Documentation table of contents — Internal navigation links — Bracket Hover example 2

② Documentation table of contents — Internal navigation links

WhenSidebar or inline table of contents on a technical documentation site, guide, or long tutorial.
WhyBrackets evoke programming-language syntax, reinforcing a technical identity without adding any JS dependency to the page.
Settingsfont-size: 14px, --space-8: 1rem to tighten the list, --text-secondary: #64748b on a light background — adapt --text-primary to the doc's accent color.
Retro terminal menu — Simulated CLI or text-based game — Bracket Hover example 3

③ Retro terminal menu — Simulated CLI or text-based game

WhenMain menu of a text game, simulated CLI interface, developer easter egg, or technical dark-mode dashboard.
Why<code>[ ]</code> brackets are the iconic motif of terminal menus. The CSS animation reinforces the retro/hacker aesthetic without any JS — a monospace font amplifies the effect.
Settingsfont-family: 'Courier New', monospace, --text-secondary: #4ade80 (terminal green), --text-primary: #86efac, transition: .15s for a crisper response.

How it works

The effect relies entirely on the ::before and ::after pseudo-elements of the .link-bracket class. Each pseudo-element holds a character ("[" and "]") initially hidden (opacity: 0) and inset (translateX(+10px) for ::before, translateX(-10px) for ::after). On hover, a single transition: .3s brings both properties to their final values — the brackets slide in and appear simultaneously.

The spacing between the bracket and the text is handled by the combination of margin-right/margin-left (0 px at rest → 5 px on hover) and the return to translateX(0). Both properties animate together in the same transition, producing an opening motion — as if the brackets were spreading away from the word rather than simply appearing beside it.

The text color transitions in parallel from --text-secondary (#a1a1aa) to --text-primary (#ffffff) via transition: color .3s on .nav-link-demo. Both transitions (text + brackets) share the same duration, synchronising them without extra code.

No JavaScript is used. Simply add the .link-bracket class to any inline element — <a>, <span>, <li> — that already has the base styles, and the effect activates through pure CSS. Zero dependencies, zero bundle.

Accessibility

  • prefers-reduced-motion absent: the source code contains no prefers-reduced-motion media query. The animation (slide + fade) fires regardless of system preferences. For motion-sensitive users, add @media (prefers-reduced-motion: reduce) { .link-bracket::before, .link-bracket::after { transition: opacity .3s; transform: none; } }.
  • Resting contrast: #a1a1aa on #0a0a0f — ratio ≈ 7.9:1, above WCAG AA (4.5:1) and AAA (7:1) thresholds for body text. On hover (#ffffff), ratio = 21:1.
  • The demo elements are non-focusable <span> tags. In production, use native <a href> links: they are keyboard-focusable, support :visited, and are correctly announced by screen readers — the effect CSS applies unchanged.
  • No aria-* attributes are present in the demo. For a main navigation, wrap the links in a <nav aria-label="Main navigation"> and use aria-current="page" on the active link.
  • The brackets generated by ::before/::after are purely decorative. They are ignored by screen readers (CSS pseudo-elements are not exposed in the accessibility tree).

Browser compatibility

Requires CSS pseudo-elements and transitions — supported in all modern browsers since 2013. Zero JavaScript dependency.

Chrome 26+✓ Full
Firefox 16+✓ Full
Safari 9+✓ Full
Edge 12+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

On browsers without CSS transition support, the brackets appear and disappear instantly on hover — the effect still works, with no errors.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<nav class="nav-demo">
  <a class="nav-link-demo link-bracket" href="#">Home</a>
  <a class="nav-link-demo link-bracket" href="#">Services</a>
  <a class="nav-link-demo link-bracket" href="#">Contact</a>
</nav>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
--text-secondary #a1a1aa Link color at rest. Adapt to your brand palette — maintain a ratio ≥ 4.5:1 against the background.
--text-primary #ffffff Text and bracket color on hover.
--space-8 2rem Gap between navigation items. Reduce to 1rem for a compact vertical list.
--space-2 0.5rem Vertical padding on each link — enlarges the click area.
transition .3s Animation duration for brackets and color. Set in .link-bracket::before, .link-bracket::after and .nav-link-demo. Lower to .15s for a snappier feel, raise to .5s for a softer one.
translateX (rest) 10px / -10px Initial slide distance of the brackets — translateX(10px) in .link-bracket::before, translateX(-10px) in .link-bracket::after. Increase for a more pronounced slide.
margin (hover) 5px Gap between bracket and text on hover — margin-right: 5px in .link-bracket:hover::before, margin-left: 5px in .link-bracket:hover::after.
content "[" / "]" Characters used as brackets — swap for "«" / "»", "<" / ">", or "(" / ")" for stylistic variations.

FAQ

No — the effect is 100% CSS: pseudo-elements, opacity, transform, and transition. No script is included. You can integrate it into any framework (React, Vue, Svelte, Angular) without a dedicated component: just apply the CSS classes to your navigation elements.
Edit the content property in .link-bracket::before (e.g. content: "«") and .link-bracket::after (e.g. content: "»"). Works with any Unicode character, emoji, or short string. Adjust margin-right/margin-left on hover if the replacement character is wider than the original bracket.
Yes — apply the nav-link-demo link-bracket classes directly to your <a> tags. The demo uses <span> for neutrality, but in production native links are preferred: they are keyboard-focusable, tracked as visited, and correctly announced by screen readers. The CSS effect applies identically.