UI Components Medium
RTL Navigation
Navigation bar and breadcrumb with full bidirectional support, properly mirroring icons and layout for RTL languages.
Open in Lab
MCP
css vanilla-js
Targets: JS HTML
Code
/* ── Reset & Base ── */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg-primary: #0a0a0a;
--bg-secondary: #111111;
--bg-tertiary: #1a1a1a;
--bg-dropdown: #151515;
--border: #222222;
--border-light: #333333;
--text-primary: #f0f0f0;
--text-secondary: #999999;
--text-muted: #666666;
--accent-blue: #3b82f6;
--accent-green: #22c55e;
--radius: 10px;
}
html {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.5;
}
body {
min-height: 100vh;
}
button {
font: inherit;
cursor: pointer;
border: none;
background: none;
color: inherit;
}
a {
color: inherit;
text-decoration: none;
}
ul,
ol {
list-style: none;
}
/* ── Navbar ── */
.navbar {
position: sticky;
inset-block-start: 0;
background: var(--bg-secondary);
border-block-end: 1px solid var(--border);
z-index: 100;
}
.nav-container {
display: flex;
align-items: center;
max-inline-size: 1200px;
margin-inline: auto;
padding-block: 0;
padding-inline: 24px;
block-size: 64px;
}
/* Logo */
.nav-logo {
display: flex;
align-items: center;
gap: 10px;
margin-inline-end: 40px;
flex-shrink: 0;
}
.logo-icon {
font-size: 1.4rem;
color: var(--accent-blue);
}
.logo-text {
font-size: 1.1rem;
font-weight: 700;
letter-spacing: -0.02em;
}
/* Menu */
.nav-menu {
display: flex;
align-items: center;
gap: 4px;
flex: 1;
}
.nav-item {
position: relative;
}
.nav-link {
display: inline-flex;
align-items: center;
gap: 6px;
padding-block: 8px;
padding-inline: 14px;
font-size: 0.88rem;
color: var(--text-secondary);
border-radius: 6px;
transition: color 0.2s, background 0.2s;
white-space: nowrap;
}
.nav-link:hover,
.nav-link.active {
color: var(--text-primary);
background: var(--bg-tertiary);
}
.chevron {
font-size: 0.65rem;
transition: transform 0.2s;
}
.dropdown-trigger[aria-expanded="true"] .chevron {
transform: rotate(180deg);
}
/* Dropdown */
.dropdown-menu {
position: absolute;
inset-block-start: calc(100% + 8px);
inset-inline-start: 0;
inline-size: 280px;
background: var(--bg-dropdown);
border: 1px solid var(--border);
border-radius: var(--radius);
padding-block: 8px;
padding-inline: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-8px);
transition: opacity 0.2s, transform 0.2s, visibility 0.2s;
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
}
.dropdown-menu.open {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.dropdown-link {
display: flex;
align-items: flex-start;
gap: 12px;
padding-block: 10px;
padding-inline: 12px;
border-radius: 8px;
transition: background 0.2s;
}
.dropdown-link:hover {
background: var(--bg-tertiary);
}
.dd-icon {
font-size: 1.2rem;
margin-block-start: 2px;
flex-shrink: 0;
}
.dd-content {
display: flex;
flex-direction: column;
}
.dd-title {
font-size: 0.88rem;
font-weight: 500;
color: var(--text-primary);
}
.dd-desc {
font-size: 0.76rem;
color: var(--text-muted);
}
/* Nav actions */
.nav-actions {
display: flex;
align-items: center;
gap: 12px;
margin-inline-start: auto;
}
.dir-toggle {
display: flex;
align-items: center;
gap: 6px;
padding-block: 6px;
padding-inline: 12px;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 0.8rem;
font-weight: 500;
color: var(--accent-blue);
transition: background 0.2s;
}
.dir-toggle:hover {
background: var(--bg-primary);
}
.nav-cta {
padding-block: 8px;
padding-inline: 18px;
background: var(--accent-blue);
color: #fff;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 600;
transition: background 0.2s;
white-space: nowrap;
}
.nav-cta:hover {
background: #2563eb;
}
[dir="rtl"] .nav-cta {
direction: ltr;
unicode-bidi: bidi-override;
}
/* Mobile */
.mobile-toggle {
display: none;
padding: 8px;
}
.hamburger {
display: block;
inline-size: 20px;
block-size: 2px;
background: var(--text-primary);
position: relative;
}
.hamburger::before,
.hamburger::after {
content: "";
position: absolute;
inline-size: 100%;
block-size: 2px;
background: var(--text-primary);
inset-inline-start: 0;
}
.hamburger::before {
inset-block-start: -6px;
}
.hamburger::after {
inset-block-start: 6px;
}
/* ── Breadcrumb ── */
.breadcrumb-container {
border-block-end: 1px solid var(--border);
background: var(--bg-primary);
}
.breadcrumb {
max-inline-size: 1200px;
margin-inline: auto;
padding-block: 12px;
padding-inline: 24px;
}
.breadcrumb-list {
display: flex;
align-items: center;
gap: 0;
flex-wrap: wrap;
}
.breadcrumb-item {
display: inline-flex;
align-items: center;
}
.breadcrumb-link {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 0.82rem;
color: var(--text-secondary);
padding-block: 4px;
padding-inline: 6px;
border-radius: 4px;
transition: color 0.2s, background 0.2s;
}
.breadcrumb-link:hover {
color: var(--text-primary);
background: var(--bg-tertiary);
}
.bc-home {
font-size: 0.9rem;
}
.breadcrumb-text {
font-size: 0.82rem;
color: var(--text-primary);
font-weight: 500;
padding-inline: 6px;
}
.breadcrumb-sep {
display: inline-flex;
align-items: center;
padding-inline: 4px;
}
.sep-arrow {
font-size: 1rem;
color: var(--text-muted);
line-height: 1;
display: inline-block;
transition: transform 0.2s;
}
/* Flip breadcrumb arrows in RTL */
[dir="rtl"] .sep-arrow {
transform: scaleX(-1);
}
/* ── Demo content ── */
.demo-content {
max-inline-size: 1200px;
margin-inline: auto;
padding-block: 48px;
padding-inline: 24px;
}
.demo-title {
font-size: 2rem;
font-weight: 700;
margin-block-end: 16px;
}
.demo-text {
font-size: 1rem;
color: var(--text-secondary);
max-inline-size: 640px;
margin-block-end: 32px;
line-height: 1.7;
}
.feature-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.feature {
display: flex;
align-items: center;
gap: 12px;
padding-block: 12px;
padding-inline: 16px;
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
max-inline-size: 480px;
}
.feature-icon {
inline-size: 28px;
block-size: 28px;
border-radius: 50%;
background: rgba(34, 197, 94, 0.15);
color: var(--accent-green);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
flex-shrink: 0;
}
.feature-text {
font-size: 0.9rem;
color: var(--text-secondary);
}
/* ── Mobile backdrop ── */
.mobile-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 90;
}
.mobile-backdrop.active {
display: block;
}
/* ── Responsive ── */
@media (max-width: 768px) {
.nav-container {
padding-inline: 16px;
position: relative;
}
.nav-menu {
position: fixed;
inset-block-start: 64px;
inset-inline-start: 0;
inset-inline-end: 0;
inset-block-end: 0;
background: var(--bg-secondary);
border-block-start: 1px solid var(--border);
flex-direction: column;
align-items: stretch;
gap: 2px;
padding-block: 12px;
padding-inline: 16px;
overflow-y: auto;
z-index: 95;
transform: translateY(-110%);
opacity: 0;
transition: transform 0.3s ease, opacity 0.25s ease;
}
.nav-menu.open {
transform: translateY(0);
opacity: 1;
}
.nav-link {
display: flex;
width: 100%;
padding-block: 12px;
padding-inline: 16px;
font-size: 0.95rem;
border-radius: 8px;
}
.nav-link:hover,
.nav-link.active {
background: var(--bg-tertiary);
}
.dropdown-trigger {
justify-content: space-between;
}
/* Dropdown inside mobile menu */
.nav-menu .dropdown-menu {
position: static;
inline-size: 100%;
box-shadow: none;
border: none;
background: transparent;
padding-block: 4px;
padding-inline: 0;
margin-inline-start: 12px;
opacity: 1;
visibility: visible;
transform: none;
display: none;
border-inline-start: 2px solid var(--border-light);
}
.nav-menu .dropdown-menu.open {
display: block;
}
.nav-menu .dropdown-link {
padding-block: 10px;
padding-inline: 14px;
}
/* Nav actions in mobile */
.nav-actions {
margin-inline-start: auto;
}
.nav-cta {
display: none;
}
.mobile-toggle {
display: flex;
align-items: center;
justify-content: center;
margin-inline-start: 8px;
width: 40px;
height: 40px;
border-radius: 8px;
}
.mobile-toggle:hover {
background: var(--bg-tertiary);
}
/* Hamburger animation */
.mobile-toggle.active .hamburger {
background: transparent;
}
.mobile-toggle.active .hamburger::before {
inset-block-start: 0;
transform: rotate(45deg);
}
.mobile-toggle.active .hamburger::after {
inset-block-start: 0;
transform: rotate(-45deg);
}
.hamburger,
.hamburger::before,
.hamburger::after {
transition: all 0.25s ease;
}
/* Breadcrumb */
.breadcrumb {
padding-inline: 16px;
}
/* Content */
.demo-content {
padding-block: 32px;
padding-inline: 16px;
}
.demo-title {
font-size: 1.5rem;
}
.feature {
max-inline-size: 100%;
}
}(() => {
const html = document.documentElement;
const dirToggle = document.getElementById("dir-toggle");
const dirLabel = document.getElementById("dir-label");
const mobileToggle = document.getElementById("mobile-toggle");
const navMenu = document.getElementById("nav-menu");
/* ── Direction toggle ── */
dirToggle.addEventListener("click", () => {
const isRtl = html.getAttribute("dir") === "rtl";
const newDir = isRtl ? "ltr" : "rtl";
html.setAttribute("dir", newDir);
html.setAttribute("lang", isRtl ? "en" : "ar");
dirLabel.textContent = newDir.toUpperCase();
});
/* ── Dropdown menus ── */
const triggers = document.querySelectorAll(".dropdown-trigger");
function closeAllDropdowns(except) {
triggers.forEach((t) => {
if (t !== except) {
t.setAttribute("aria-expanded", "false");
const id = t.getAttribute("data-dropdown");
const menu = document.getElementById("dropdown-" + id);
if (menu) menu.classList.remove("open");
}
});
}
triggers.forEach((trigger) => {
trigger.addEventListener("click", (e) => {
e.stopPropagation();
const id = trigger.getAttribute("data-dropdown");
const menu = document.getElementById("dropdown-" + id);
const isOpen = trigger.getAttribute("aria-expanded") === "true";
closeAllDropdowns(trigger);
trigger.setAttribute("aria-expanded", String(!isOpen));
menu.classList.toggle("open", !isOpen);
});
});
/* Close dropdowns on outside click */
document.addEventListener("click", () => {
closeAllDropdowns();
});
/* Prevent dropdown content clicks from closing */
document.querySelectorAll(".dropdown-menu").forEach((menu) => {
menu.addEventListener("click", (e) => e.stopPropagation());
});
/* ── Mobile menu ── */
function closeMobileMenu() {
navMenu.classList.remove("open");
mobileToggle.classList.remove("active");
var backdrop = document.getElementById("mobile-backdrop");
if (backdrop) backdrop.classList.remove("active");
}
mobileToggle.addEventListener("click", () => {
const opening = !navMenu.classList.contains("open");
navMenu.classList.toggle("open", opening);
mobileToggle.classList.toggle("active", opening);
var backdrop = document.getElementById("mobile-backdrop");
if (backdrop) backdrop.classList.toggle("active", opening);
});
/* Backdrop click closes menu */
var backdrop = document.getElementById("mobile-backdrop");
if (backdrop) backdrop.addEventListener("click", closeMobileMenu);
/* Close mobile menu on resize */
window.addEventListener("resize", () => {
if (window.innerWidth > 768) closeMobileMenu();
});
})();<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RTL Navigation</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="page">
<!-- ── Mobile backdrop ── -->
<div class="mobile-backdrop" id="mobile-backdrop"></div>
<!-- ── Navbar ── -->
<nav class="navbar" aria-label="Main navigation">
<div class="nav-container">
<!-- Logo -->
<a href="#" class="nav-logo">
<span class="logo-icon">◆</span>
<span class="logo-text">Acme Corp</span>
</a>
<!-- Menu -->
<ul class="nav-menu" id="nav-menu">
<li class="nav-item">
<a href="#" class="nav-link active">Home</a>
</li>
<li class="nav-item has-dropdown">
<button class="nav-link dropdown-trigger" aria-expanded="false" aria-haspopup="true" data-dropdown="products">
Products
<span class="chevron">▾</span>
</button>
<ul class="dropdown-menu" id="dropdown-products">
<li><a href="#" class="dropdown-link">
<span class="dd-icon">□</span>
<span class="dd-content">
<span class="dd-title">Dashboard</span>
<span class="dd-desc">Analytics and reporting tools</span>
</span>
</a></li>
<li><a href="#" class="dropdown-link">
<span class="dd-icon">✎</span>
<span class="dd-content">
<span class="dd-title">Editor</span>
<span class="dd-desc">Rich text and code editor</span>
</span>
</a></li>
<li><a href="#" class="dropdown-link">
<span class="dd-icon">⚙</span>
<span class="dd-content">
<span class="dd-title">Automation</span>
<span class="dd-desc">Workflow automation engine</span>
</span>
</a></li>
<li><a href="#" class="dropdown-link">
<span class="dd-icon">🔒</span>
<span class="dd-content">
<span class="dd-title">Security</span>
<span class="dd-desc">Enterprise security suite</span>
</span>
</a></li>
</ul>
</li>
<li class="nav-item has-dropdown">
<button class="nav-link dropdown-trigger" aria-expanded="false" aria-haspopup="true" data-dropdown="company">
Company
<span class="chevron">▾</span>
</button>
<ul class="dropdown-menu" id="dropdown-company">
<li><a href="#" class="dropdown-link">
<span class="dd-icon">🏠</span>
<span class="dd-content">
<span class="dd-title">About Us</span>
<span class="dd-desc">Our story and mission</span>
</span>
</a></li>
<li><a href="#" class="dropdown-link">
<span class="dd-icon">👥</span>
<span class="dd-content">
<span class="dd-title">Team</span>
<span class="dd-desc">Meet our people</span>
</span>
</a></li>
<li><a href="#" class="dropdown-link">
<span class="dd-icon">💼</span>
<span class="dd-content">
<span class="dd-title">Careers</span>
<span class="dd-desc">Join our growing team</span>
</span>
</a></li>
</ul>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Pricing</a>
</li>
<li class="nav-item">
<a href="#" class="nav-link">Contact</a>
</li>
</ul>
<!-- Actions -->
<div class="nav-actions">
<button class="dir-toggle" id="dir-toggle" type="button" aria-label="Toggle text direction">
<span id="dir-label">LTR</span>
<span>⇄</span>
</button>
<a href="#" class="nav-cta">Get Started →</a>
</div>
<!-- Mobile toggle -->
<button class="mobile-toggle" id="mobile-toggle" aria-label="Toggle menu">
<span class="hamburger"></span>
</button>
</div>
</nav>
<!-- ── Breadcrumb ── -->
<div class="breadcrumb-container">
<nav class="breadcrumb" aria-label="Breadcrumb">
<ol class="breadcrumb-list">
<li class="breadcrumb-item">
<a href="#" class="breadcrumb-link">
<span class="bc-home">🏠</span>
Home
</a>
</li>
<li class="breadcrumb-sep" aria-hidden="true">
<span class="sep-arrow">›</span>
</li>
<li class="breadcrumb-item">
<a href="#" class="breadcrumb-link">Products</a>
</li>
<li class="breadcrumb-sep" aria-hidden="true">
<span class="sep-arrow">›</span>
</li>
<li class="breadcrumb-item">
<a href="#" class="breadcrumb-link">Dashboard</a>
</li>
<li class="breadcrumb-sep" aria-hidden="true">
<span class="sep-arrow">›</span>
</li>
<li class="breadcrumb-item current" aria-current="page">
<span class="breadcrumb-text">Analytics</span>
</li>
</ol>
</nav>
</div>
<!-- ── Demo content ── -->
<div class="demo-content">
<h1 class="demo-title">Analytics Dashboard</h1>
<p class="demo-text">This page demonstrates a navigation bar and breadcrumb that correctly adapt to both LTR and RTL text directions. Toggle the direction using the button in the navbar to see how all elements mirror properly.</p>
<div class="feature-list">
<div class="feature">
<span class="feature-icon">✓</span>
<span class="feature-text">Navbar items reorder for RTL</span>
</div>
<div class="feature">
<span class="feature-icon">✓</span>
<span class="feature-text">Dropdown menus reposition correctly</span>
</div>
<div class="feature">
<span class="feature-icon">✓</span>
<span class="feature-text">Breadcrumb arrows flip direction</span>
</div>
<div class="feature">
<span class="feature-icon">✓</span>
<span class="feature-text">CTA buttons mirror their arrow icons</span>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>A navigation bar with dropdown menus and a breadcrumb trail that fully mirror for RTL languages, including flipped chevrons, repositioned dropdowns, and correct icon placement.