Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-panel" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="2.5"/><path d="M9.5 4.5v15"/></symbol>
  <symbol id="i-inbox" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5h5l1.5 2.5h4l1.5-2.5h5"/><path d="M5.8 5.5h12.4l2.3 8v5.5a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1v-5.5z"/></symbol>
  <symbol id="i-user" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.7-6 7.5-6s6.7 2 7.5 6"/></symbol>
  <symbol id="i-hash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 4 8 20M16 4l-1.5 16M4.5 9h16M3.5 15h16"/></symbol>
  <symbol id="i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 4 2.5 5 5.5.8-4 3.9.9 5.5L12 16.6l-4.9 2.6.9-5.5-4-3.9L9.5 9z"/></symbol>
  <symbol id="i-send" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 3.5 10 14M20.5 3.5l-6.5 17-4-6.5-6.5-4z"/></symbol>
  <symbol id="i-message" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5.5h16v11H9.5L4 20.5z"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h9M17 7h3M4 17h3M11 17h9"/><circle cx="15" cy="7" r="2"/><circle cx="9" cy="17" r="2"/></symbol>
  <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol>
  <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></symbol>
  <symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 10.5 12 4l8.5 6.5V19.5a1 1 0 0 1-1 1h-5v-6h-5v6h-5a1 1 0 0 1-1-1z"/></symbol>
  <symbol id="i-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v12a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-15a1 1 0 0 1 1-1z"/><path d="M13.5 3.5v4h4"/></symbol>
  <symbol id="i-layers" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 8.5 4.5L12 12.5 3.5 8z"/><path d="m3.5 12 8.5 4.5 8.5-4.5M3.5 16l8.5 4.5 8.5-4.5"/></symbol>
  <symbol id="i-archive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4" width="17" height="5" rx="1.2"/><path d="M5 9v9.5A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5V9M10 13h4"/></symbol>
  <symbol id="i-chart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4v16h16"/><path d="M8.5 16v-4M12.5 16V8M16.5 16v-6"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
</svg>
<div><span class="lbl">Collapse with :has() and container queries</span>
<div class="mx-app">
  <nav class="mx" aria-label="Relay">
    <div class="mx-top"><a class="mx-brand" href="#"><span class="mx-logo" aria-hidden="true">R</span><span class="mx-label">Relay</span></a><label class="mx-toggle"><input class="mx-check" type="checkbox" aria-label="Collapse sidebar"><svg aria-hidden="true"><use href="#i-panel"/></svg></label></div>
    <ul>
      <li><a class="mx-link" href="#" aria-current="page"><svg aria-hidden="true"><use href="#i-inbox"/></svg><span class="mx-label">Inbox</span><span class="mx-count">12<span class="sr-only"> open</span></span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-user"/></svg><span class="mx-label">Assigned to me</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-hash"/></svg><span class="mx-label">Mentions</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-star"/></svg><span class="mx-label">Saved replies</span></a></li>
    </ul>
    <p class="mx-heading">Channels</p>
    <ul>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-send"/></svg><span class="mx-label">Email</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-message"/></svg><span class="mx-label">Live chat</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-bell"/></svg><span class="mx-label">Phone</span></a></li>
    </ul>
    <ul class="mx-foot">
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-sliders"/></svg><span class="mx-label">Settings</span></a></li>
    </ul>
  </nav>
  <div class="pg" style="--pg-bar:#f5d0fe">
    <div class="pg-head"><div><p class="pg-kicker">Relay · Support inbox</p><h2 class="pg-title">Inbox</h2></div><span class="pg-chip">12 open</span></div>
    <div class="pg-tiles"><div class="pg-tile"><span>First response</span><b>4m 20s</b></div><div class="pg-tile"><span>Resolved today</span><b>38</b><em>+6</em></div><div class="pg-tile"><span>Satisfaction</span><b>96%</b></div></div>
    <div class="pg-chart" aria-hidden="true"><i style="height:46%"></i><i style="height:60%"></i><i style="height:54%"></i><i style="height:72%"></i><i style="height:64%"></i><i style="height:58%"></i><i style="height:76%"></i><i style="height:70%"></i><i style="height:84%"></i><i style="height:66%"></i><i style="height:78%"></i><i style="height:88%"></i></div>
  </div>
</div></div>
<div><span class="lbl">Modal drawer: <dialog>, invoker commands, @starting-style</span>
<div class="mx-shell">
  <div class="mx-bar"><button class="mx-btn" type="button" commandfor="atlas-drawer" command="show-modal" aria-label="Open navigation"><svg aria-hidden="true"><use href="#i-menu"/></svg></button><b>Articles</b><span>Last edit 10:42</span></div>
  <div class="pg" style="--pg-bar:#f5d0fe">
    <div class="pg-head"><div><p class="pg-kicker">Atlas help centre</p><h2 class="pg-title">Articles</h2></div><span class="pg-chip">142 published</span></div>
    <div class="pg-tiles"><div class="pg-tile"><span>Views this week</span><b>21.4k</b><em>+8.0%</em></div><div class="pg-tile"><span>Rated helpful</span><b>91%</b></div><div class="pg-tile"><span>Searches with no result</span><b>37</b></div></div>
    <div class="pg-chart" aria-hidden="true"><i style="height:52%"></i><i style="height:44%"></i><i style="height:60%"></i><i style="height:68%"></i><i style="height:58%"></i><i style="height:74%"></i><i style="height:66%"></i><i style="height:80%"></i><i style="height:62%"></i><i style="height:76%"></i><i style="height:70%"></i><i style="height:84%"></i></div>
  </div>
</div>
<dialog class="mx mx-drawer" id="atlas-drawer" closedby="any" aria-label="Atlas navigation">
  <div class="mx-top"><a class="mx-brand" href="#"><span class="mx-logo" aria-hidden="true">A</span><span class="mx-label">Atlas</span></a><button class="mx-btn" type="button" commandfor="atlas-drawer" command="close" aria-label="Close navigation"><svg aria-hidden="true"><use href="#i-x"/></svg></button></div>
  <nav class="mx-nav" aria-label="Atlas">
    <ul>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-home"/></svg><span class="mx-label">Home</span></a></li>
      <li><a class="mx-link" href="#" aria-current="page"><svg aria-hidden="true"><use href="#i-file"/></svg><span class="mx-label">Articles</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-layers"/></svg><span class="mx-label">Collections</span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-archive"/></svg><span class="mx-label">Drafts</span><span class="mx-count">3<span class="sr-only"> drafts</span></span></a></li>
      <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-chart"/></svg><span class="mx-label">Analytics</span></a></li>
    </ul>
  </nav>
  <ul class="mx-foot">
    <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-sliders"/></svg><span class="mx-label">Settings</span></a></li>
    <li><a class="mx-link" href="#"><svg aria-hidden="true"><use href="#i-logout"/></svg><span class="mx-label">Log out</span></a></li>
  </ul>
</dialog></div>
CSS
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* 1. The layout grid reacts to the checkbox inside it (:has), and the sidebar is a size container,
      so its own width decides whether labels show (@container). No JavaScript. */
.mx-app{display:grid;grid-template-columns:244px minmax(0,1fr);height:520px;background:#fff;border:1px solid #d6dce5;border-radius:16px;overflow:hidden;
  box-shadow:0 1px 2px rgba(15,23,42,.05),0 18px 40px -22px rgba(15,23,42,.28);transition:grid-template-columns .3s cubic-bezier(.4,0,.2,1)}
.mx-app:has(.mx-check:checked){grid-template-columns:72px minmax(0,1fr)}
.mx{--mx-accent:#a21caf;--mx-active-bg:#fbeaff;--mx-active-ink:#86198f;--mx-ink:#52525b;--mx-strong:#18181b;--mx-muted:#63636d;--mx-line:#e7e5eb;--mx-hover:#f4f4f5;
  container-type:inline-size;display:flex;flex-direction:column;min-width:0;padding:16px 12px;background:#fcfbfd;border-right:1px solid var(--mx-line);
  overflow:hidden;font-size:.875rem}
.mx ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}
.mx-top{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 0 14px 6px}
.mx-brand{display:flex;align-items:center;gap:10px;border-radius:8px;color:var(--mx-strong);font-size:1rem;font-weight:700;text-decoration:none;white-space:nowrap}
.mx-logo{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:10px;background:conic-gradient(from 200deg,#a21caf,#db2777,#f59e0b,#a21caf);color:#fff;font-size:.85rem;font-weight:800}
.mx-toggle{position:relative;flex:none;display:grid;place-items:center;width:32px;height:32px;border:1px solid #d4d4d8;border-radius:8px;background:#fff;color:var(--mx-ink);cursor:pointer;
  transition:background-color .15s}
.mx-toggle:hover{background:var(--mx-hover)}
.mx-toggle input{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.mx-toggle svg{width:16px;height:16px}
.mx-toggle:has(:focus-visible){outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-heading{margin:16px 0 6px;padding:0 10px;font-size:.6875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mx-muted);white-space:nowrap}
.mx-link{position:relative;display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:9px;color:var(--mx-ink);font-weight:500;text-decoration:none;white-space:nowrap;
  transition:background-color .15s,color .15s}
.mx-link svg{width:20px;height:20px;flex:none}
.mx-link:hover{background:var(--mx-hover);color:var(--mx-strong)}
.mx-link[aria-current="page"]{background:var(--mx-active-bg);color:var(--mx-active-ink);font-weight:600}
.mx-count{margin-left:auto;padding:0 7px;border-radius:999px;background:var(--mx-accent);color:#fff;font-size:.7rem;font-weight:700;line-height:1.6}
.mx a:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx .mx-foot{margin-top:auto}
@container (max-width:140px){
  .mx-top{flex-direction:column;padding:0 0 10px;gap:12px}
  .mx-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
  .mx-heading{height:1px;margin:12px 10px;padding:0;background:var(--mx-line);overflow:hidden;color:transparent}
  .mx-link{justify-content:center;padding:10px}
  .mx-count{position:absolute;top:2px;right:2px;padding:0 5px;font-size:.625rem}
  .mx-toggle svg{transform:scaleX(-1)}
}

/* 2. Drawer: a modal <dialog>. command="show-modal" opens it with no script, closedby="any" closes it on a backdrop click,
      @starting-style animates both ways. */
.mx-shell{display:flex;flex-direction:column;height:460px;background:#fff;border:1px solid #d6dce5;border-radius:16px;overflow:hidden;
  box-shadow:0 1px 2px rgba(15,23,42,.05),0 18px 40px -22px rgba(15,23,42,.28)}
.mx-bar{display:flex;align-items:center;gap:12px;padding:12px 18px;border-bottom:1px solid #e7e5eb}
.mx-bar b{color:#18181b}
.mx-bar span{margin-left:auto;font-size:.8rem;color:#63636d}
.mx-btn{display:grid;place-items:center;width:36px;height:36px;padding:0;border:1px solid #d4d4d8;border-radius:10px;background:#fff;color:#18181b;cursor:pointer;transition:background-color .15s}
.mx-btn:hover{background:#f4f4f5}
.mx-btn svg{width:18px;height:18px}
.mx-btn:focus-visible{outline:2px solid #a21caf;outline-offset:2px}
.mx-drawer{position:fixed;inset:10px auto 10px 10px;width:min(300px,calc(100vw - 20px));height:auto;max-width:none;max-height:none;margin:0;
  flex-direction:column;border:0;border-radius:18px;box-shadow:0 30px 60px -20px rgba(24,24,27,.45);
  translate:calc(-100% - 20px) 0;transition:translate .32s cubic-bezier(.3,0,.2,1),display .32s allow-discrete,overlay .32s allow-discrete}
.mx-drawer:not([open]){display:none}
.mx-drawer[open]{display:flex;translate:0 0}
@starting-style{.mx-drawer[open]{translate:calc(-100% - 20px) 0}}
.mx-drawer::backdrop{background:rgba(24,24,27,0);backdrop-filter:blur(0);
  transition:background-color .32s,backdrop-filter .32s,display .32s allow-discrete,overlay .32s allow-discrete}
.mx-drawer[open]::backdrop{background:rgba(24,24,27,.4);backdrop-filter:blur(3px)}
@starting-style{.mx-drawer[open]::backdrop{background:rgba(24,24,27,0);backdrop-filter:blur(0)}}
.mx-drawer .mx-top{padding:0 0 14px 6px}

@media (max-width:640px){
  .mx-app{grid-template-columns:minmax(0,1fr);height:auto}
  .mx-app>.mx{border-right:0;border-bottom:1px solid var(--mx-line)}
  .mx-app:has(.mx-check:checked){grid-template-columns:72px minmax(0,1fr)}
  .mx-app:has(.mx-check:checked)>.mx{border-right:1px solid var(--mx-line);border-bottom:0}
}
@media (prefers-reduced-motion:reduce){.mx-app,.mx-drawer,.mx-drawer::backdrop,.mx-link,.mx-toggle,.mx-btn{transition:none}}
JavaScript
// Only for browsers without invoker commands (command / commandfor): wire the same buttons to the dialog API.
if (!('command' in HTMLButtonElement.prototype)) {
  document.querySelectorAll('button[commandfor]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var dialog = document.getElementById(btn.getAttribute('commandfor'));
      if (!dialog) return;
      if (btn.getAttribute('command') === 'show-modal') dialog.showModal(); else dialog.close();
    });
  });
}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-panel" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="2.5"/><path d="M9.5 4.5v15"/></symbol>
  <symbol id="i-inbox" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5h5l1.5 2.5h4l1.5-2.5h5"/><path d="M5.8 5.5h12.4l2.3 8v5.5a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1v-5.5z"/></symbol>
  <symbol id="i-user" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.7-6 7.5-6s6.7 2 7.5 6"/></symbol>
  <symbol id="i-hash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 4 8 20M16 4l-1.5 16M4.5 9h16M3.5 15h16"/></symbol>
  <symbol id="i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 4 2.5 5 5.5.8-4 3.9.9 5.5L12 16.6l-4.9 2.6.9-5.5-4-3.9L9.5 9z"/></symbol>
  <symbol id="i-send" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 3.5 10 14M20.5 3.5l-6.5 17-4-6.5-6.5-4z"/></symbol>
  <symbol id="i-message" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5.5h16v11H9.5L4 20.5z"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h9M17 7h3M4 17h3M11 17h9"/><circle cx="15" cy="7" r="2"/><circle cx="9" cy="17" r="2"/></symbol>
  <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol>
  <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></symbol>
  <symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 10.5 12 4l8.5 6.5V19.5a1 1 0 0 1-1 1h-5v-6h-5v6h-5a1 1 0 0 1-1-1z"/></symbol>
  <symbol id="i-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v12a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-15a1 1 0 0 1 1-1z"/><path d="M13.5 3.5v4h4"/></symbol>
  <symbol id="i-layers" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 8.5 4.5L12 12.5 3.5 8z"/><path d="m3.5 12 8.5 4.5 8.5-4.5M3.5 16l8.5 4.5 8.5-4.5"/></symbol>
  <symbol id="i-archive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4" width="17" height="5" rx="1.2"/><path d="M5 9v9.5A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5V9M10 13h4"/></symbol>
  <symbol id="i-chart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4v16h16"/><path d="M8.5 16v-4M12.5 16V8M16.5 16v-6"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
</svg>
<div><span class="lbl">Collapse with :has() and container queries</span>
<div class="mx-app">
  <nav class="mx" aria-label="Relay">
    <div class="mx-top"><a class="mx-brand" href="#"><span class="mx-logo" aria-hidden="true">R</span><span class="mx-label">Relay</span></a><div class="mx-toggle-wrap"><input class="btn-check mx-check" id="mx-collapse" type="checkbox" autocomplete="off"><label class="btn mx-toggle" for="mx-collapse"><svg aria-hidden="true"><use href="#i-panel"/></svg><span class="visually-hidden">Collapse sidebar</span></label></div></div>
    <ul class="nav flex-column flex-nowrap">
      <li class="nav-item"><a class="nav-link mx-link" href="#" aria-current="page"><svg aria-hidden="true"><use href="#i-inbox"/></svg><span class="mx-label">Inbox</span><span class="mx-count badge rounded-pill">12<span class="visually-hidden"> open</span></span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-user"/></svg><span class="mx-label">Assigned to me</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-hash"/></svg><span class="mx-label">Mentions</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-star"/></svg><span class="mx-label">Saved replies</span></a></li>
    </ul>
    <p class="mx-heading">Channels</p>
    <ul class="nav flex-column flex-nowrap">
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-send"/></svg><span class="mx-label">Email</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-message"/></svg><span class="mx-label">Live chat</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-bell"/></svg><span class="mx-label">Phone</span></a></li>
    </ul>
    <ul class="nav flex-column flex-nowrap mx-foot">
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-sliders"/></svg><span class="mx-label">Settings</span></a></li>
    </ul>
  </nav>
  <div class="pg" style="--pg-bar:#f5d0fe">
    <div class="pg-head"><div><p class="pg-kicker">Relay · Support inbox</p><h2 class="pg-title">Inbox</h2></div><span class="pg-chip">12 open</span></div>
    <div class="pg-tiles"><div class="pg-tile"><span>First response</span><b>4m 20s</b></div><div class="pg-tile"><span>Resolved today</span><b>38</b><em>+6</em></div><div class="pg-tile"><span>Satisfaction</span><b>96%</b></div></div>
    <div class="pg-chart" aria-hidden="true"><i style="height:46%"></i><i style="height:60%"></i><i style="height:54%"></i><i style="height:72%"></i><i style="height:64%"></i><i style="height:58%"></i><i style="height:76%"></i><i style="height:70%"></i><i style="height:84%"></i><i style="height:66%"></i><i style="height:78%"></i><i style="height:88%"></i></div>
  </div>
</div></div>
<div><span class="lbl">Modal drawer: <dialog>, invoker commands, @starting-style</span>
<div class="mx-shell">
  <div class="mx-bar"><button class="btn mx-btn" type="button" commandfor="atlas-drawer" command="show-modal" aria-label="Open navigation"><svg aria-hidden="true"><use href="#i-menu"/></svg></button><b>Articles</b><span>Last edit 10:42</span></div>
  <div class="pg" style="--pg-bar:#f5d0fe">
    <div class="pg-head"><div><p class="pg-kicker">Atlas help centre</p><h2 class="pg-title">Articles</h2></div><span class="pg-chip">142 published</span></div>
    <div class="pg-tiles"><div class="pg-tile"><span>Views this week</span><b>21.4k</b><em>+8.0%</em></div><div class="pg-tile"><span>Rated helpful</span><b>91%</b></div><div class="pg-tile"><span>Searches with no result</span><b>37</b></div></div>
    <div class="pg-chart" aria-hidden="true"><i style="height:52%"></i><i style="height:44%"></i><i style="height:60%"></i><i style="height:68%"></i><i style="height:58%"></i><i style="height:74%"></i><i style="height:66%"></i><i style="height:80%"></i><i style="height:62%"></i><i style="height:76%"></i><i style="height:70%"></i><i style="height:84%"></i></div>
  </div>
</div>
<dialog class="mx mx-drawer" id="atlas-drawer" closedby="any" aria-label="Atlas navigation">
  <div class="mx-top"><a class="mx-brand" href="#"><span class="mx-logo" aria-hidden="true">A</span><span class="mx-label">Atlas</span></a><button class="btn mx-btn" type="button" commandfor="atlas-drawer" command="close" aria-label="Close navigation"><svg aria-hidden="true"><use href="#i-x"/></svg></button></div>
  <nav class="mx-nav" aria-label="Atlas">
    <ul class="nav flex-column flex-nowrap">
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-home"/></svg><span class="mx-label">Home</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#" aria-current="page"><svg aria-hidden="true"><use href="#i-file"/></svg><span class="mx-label">Articles</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-layers"/></svg><span class="mx-label">Collections</span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-archive"/></svg><span class="mx-label">Drafts</span><span class="mx-count badge rounded-pill">3<span class="visually-hidden"> drafts</span></span></a></li>
      <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-chart"/></svg><span class="mx-label">Analytics</span></a></li>
    </ul>
  </nav>
  <ul class="nav flex-column flex-nowrap mx-foot">
    <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-sliders"/></svg><span class="mx-label">Settings</span></a></li>
    <li class="nav-item"><a class="nav-link mx-link" href="#"><svg aria-hidden="true"><use href="#i-logout"/></svg><span class="mx-label">Log out</span></a></li>
  </ul>
</dialog></div>
CSS
/* Bootstrap version: .btn-check + .btn for the collapse toggle, .nav/.nav-link lists, .badge, .btn for the drawer buttons. */

/* 1. The layout grid reacts to the checkbox inside it (:has), and the sidebar is a size container,
      so its own width decides whether labels show (@container). No JavaScript. */
.mx-app{display:grid;grid-template-columns:244px minmax(0,1fr);height:520px;background:#fff;border:1px solid #d6dce5;border-radius:16px;overflow:hidden;
  box-shadow:0 1px 2px rgba(15,23,42,.05),0 18px 40px -22px rgba(15,23,42,.28);transition:grid-template-columns .3s cubic-bezier(.4,0,.2,1)}
.mx-app:has(.mx-check:checked){grid-template-columns:72px minmax(0,1fr)}
.mx{--mx-accent:#a21caf;--mx-active-bg:#fbeaff;--mx-active-ink:#86198f;--mx-ink:#52525b;--mx-strong:#18181b;--mx-muted:#63636d;--mx-line:#e7e5eb;--mx-hover:#f4f4f5;
  container-type:inline-size;display:flex;flex-direction:column;min-width:0;padding:16px 12px;background:#fcfbfd;border-right:1px solid var(--mx-line);
  overflow:hidden;font-size:.875rem}
.mx .nav{gap:2px}
.mx-top{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:0 0 14px 6px}
.mx-brand{display:flex;align-items:center;gap:10px;border-radius:8px;color:var(--mx-strong);font-size:1rem;font-weight:700;text-decoration:none;white-space:nowrap}
.mx-logo{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:10px;background:conic-gradient(from 200deg,#a21caf,#db2777,#f59e0b,#a21caf);color:#fff;font-size:.85rem;font-weight:800}
.mx-toggle{--bs-btn-padding-x:0;--bs-btn-padding-y:0;display:grid;place-items:center;width:32px;height:32px;border:1px solid #d4d4d8;border-radius:8px;background:#fff;color:var(--mx-ink);cursor:pointer;
  transition:background-color .15s}
.mx-toggle:hover{background:var(--mx-hover)}
.btn-check:checked+.mx-toggle{background:#fff;color:var(--mx-ink);border-color:#d4d4d8}
.mx-toggle svg{width:16px;height:16px}
.btn-check:focus-visible+.mx-toggle{box-shadow:none;outline:2px solid var(--mx-accent);outline-offset:2px}
.mx-heading{margin:16px 0 6px;line-height:1.5;padding:0 10px;font-size:.6875rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--mx-muted);white-space:nowrap}
.mx .nav-link{position:relative;display:flex;font-size:.875rem;line-height:1.5;align-items:center;gap:12px;padding:9px 12px;border-radius:9px;color:var(--mx-ink);font-weight:500;text-decoration:none;white-space:nowrap;
  transition:background-color .15s,color .15s}
.mx .nav-link svg{width:20px;height:20px;flex:none}
.mx .nav-link:hover{background:var(--mx-hover);color:var(--mx-strong)}
.mx .nav-link[aria-current="page"]{background:var(--mx-active-bg);color:var(--mx-active-ink);font-weight:600}
.mx .badge{margin-left:auto;padding:0 7px;border-radius:999px;background:var(--mx-accent);color:#fff;font-size:.7rem;font-weight:700;line-height:1.6}
.mx a:focus-visible,.mx-btn:focus-visible{box-shadow:none}
.mx a:focus-visible{outline:2px solid var(--mx-accent);outline-offset:2px}
.mx .mx-foot{margin-top:auto}
@container (max-width:140px){
  .mx-top{flex-direction:column;padding:0 0 10px;gap:12px}
  .mx-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
  .mx-heading{height:1px;margin:12px 10px;padding:0;background:var(--mx-line);overflow:hidden;color:transparent}
  .mx .nav-link{justify-content:center;padding:10px}
  .mx .badge{position:absolute;top:2px;right:2px;padding:0 5px;font-size:.625rem}
  .mx-toggle svg{transform:scaleX(-1)}
}

/* 2. Drawer: a modal <dialog>. command="show-modal" opens it with no script, closedby="any" closes it on a backdrop click,
      @starting-style animates both ways. */
.mx-shell{display:flex;flex-direction:column;height:460px;background:#fff;border:1px solid #d6dce5;border-radius:16px;overflow:hidden;
  box-shadow:0 1px 2px rgba(15,23,42,.05),0 18px 40px -22px rgba(15,23,42,.28)}
.mx-bar{display:flex;align-items:center;gap:12px;padding:12px 18px;border-bottom:1px solid #e7e5eb}
.mx-bar b{color:#18181b}
.mx-bar span{margin-left:auto;font-size:.8rem;color:#63636d}
.mx-btn{--bs-btn-padding-x:0;--bs-btn-padding-y:0;display:grid;place-items:center;width:36px;height:36px;padding:0;border:1px solid #d4d4d8;border-radius:10px;background:#fff;color:#18181b;cursor:pointer;transition:background-color .15s}
.mx-btn:hover{background:#f4f4f5}
.mx-btn svg{width:18px;height:18px}
.mx-btn:focus-visible{outline:2px solid #a21caf;outline-offset:2px}
.mx-drawer{position:fixed;inset:10px auto 10px 10px;width:min(300px,calc(100vw - 20px));height:auto;max-width:none;max-height:none;margin:0;
  flex-direction:column;border:0;border-radius:18px;box-shadow:0 30px 60px -20px rgba(24,24,27,.45);
  translate:calc(-100% - 20px) 0;transition:translate .32s cubic-bezier(.3,0,.2,1),display .32s allow-discrete,overlay .32s allow-discrete}
.mx-drawer:not([open]){display:none}
.mx-drawer[open]{display:flex;translate:0 0}
@starting-style{.mx-drawer[open]{translate:calc(-100% - 20px) 0}}
.mx-drawer::backdrop{background:rgba(24,24,27,0);backdrop-filter:blur(0);
  transition:background-color .32s,backdrop-filter .32s,display .32s allow-discrete,overlay .32s allow-discrete}
.mx-drawer[open]::backdrop{background:rgba(24,24,27,.4);backdrop-filter:blur(3px)}
@starting-style{.mx-drawer[open]::backdrop{background:rgba(24,24,27,0);backdrop-filter:blur(0)}}
.mx-drawer .mx-top{padding:0 0 14px 6px}

@media (max-width:640px){
  .mx-app{grid-template-columns:minmax(0,1fr);height:auto}
  .mx-app>.mx{border-right:0;border-bottom:1px solid var(--mx-line)}
  .mx-app:has(.mx-check:checked){grid-template-columns:72px minmax(0,1fr)}
  .mx-app:has(.mx-check:checked)>.mx{border-right:1px solid var(--mx-line);border-bottom:0}
}
@media (prefers-reduced-motion:reduce){.mx-app,.mx-drawer,.mx-drawer::backdrop,.mx .nav-link,.mx-toggle,.mx-btn{transition:none}}
JavaScript
// Only for browsers without invoker commands (command / commandfor): wire the same buttons to the dialog API.
if (!('command' in HTMLButtonElement.prototype)) {
  document.querySelectorAll('button[commandfor]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var dialog = document.getElementById(btn.getAttribute('commandfor'));
      if (!dialog) return;
      if (btn.getAttribute('command') === 'show-modal') dialog.showModal(); else dialog.close();
    });
  });
}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-panel" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4.5" width="17" height="15" rx="2.5"/><path d="M9.5 4.5v15"/></symbol>
  <symbol id="i-inbox" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 13.5h5l1.5 2.5h4l1.5-2.5h5"/><path d="M5.8 5.5h12.4l2.3 8v5.5a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1v-5.5z"/></symbol>
  <symbol id="i-user" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4.5 20.5c.8-4 3.7-6 7.5-6s6.7 2 7.5 6"/></symbol>
  <symbol id="i-hash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M9.5 4 8 20M16 4l-1.5 16M4.5 9h16M3.5 15h16"/></symbol>
  <symbol id="i-star" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 4 2.5 5 5.5.8-4 3.9.9 5.5L12 16.6l-4.9 2.6.9-5.5-4-3.9L9.5 9z"/></symbol>
  <symbol id="i-send" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20.5 3.5 10 14M20.5 3.5l-6.5 17-4-6.5-6.5-4z"/></symbol>
  <symbol id="i-message" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5.5h16v11H9.5L4 20.5z"/></symbol>
  <symbol id="i-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 1.5h-15z"/><path d="M10 20.5a2 2 0 0 0 4 0"/></symbol>
  <symbol id="i-sliders" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h9M17 7h3M4 17h3M11 17h9"/><circle cx="15" cy="7" r="2"/><circle cx="9" cy="17" r="2"/></symbol>
  <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h16"/></symbol>
  <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></symbol>
  <symbol id="i-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 10.5 12 4l8.5 6.5V19.5a1 1 0 0 1-1 1h-5v-6h-5v6h-5a1 1 0 0 1-1-1z"/></symbol>
  <symbol id="i-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 3.5h7l4 4v12a1 1 0 0 1-1 1h-10a1 1 0 0 1-1-1v-15a1 1 0 0 1 1-1z"/><path d="M13.5 3.5v4h4"/></symbol>
  <symbol id="i-layers" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 3.5 8.5 4.5L12 12.5 3.5 8z"/><path d="m3.5 12 8.5 4.5 8.5-4.5M3.5 16l8.5 4.5 8.5-4.5"/></symbol>
  <symbol id="i-archive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="4" width="17" height="5" rx="1.2"/><path d="M5 9v9.5A1.5 1.5 0 0 0 6.5 20h11a1.5 1.5 0 0 0 1.5-1.5V9M10 13h4"/></symbol>
  <symbol id="i-chart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4v16h16"/><path d="M8.5 16v-4M12.5 16V8M16.5 16v-6"/></symbol>
  <symbol id="i-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M14 4h4.5A1.5 1.5 0 0 1 20 5.5v13a1.5 1.5 0 0 1-1.5 1.5H14"/><path d="M9.5 16.5 5 12l4.5-4.5M5 12h10"/></symbol>
</svg>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5b6474] uppercase">Collapse with :has() and container queries</span>
<div class="grid h-[520px] grid-cols-[244px_minmax(0,1fr)] overflow-hidden rounded-2xl border border-[#d6dce5] bg-white shadow-[0_1px_2px_rgba(15,23,42,.05),0_18px_40px_-22px_rgba(15,23,42,.28)] transition-[grid-template-columns] duration-300 ease-[cubic-bezier(.4,0,.2,1)] has-checked:grid-cols-[72px_minmax(0,1fr)] motion-reduce:transition-none max-[640px]:h-auto max-[640px]:grid-cols-[minmax(0,1fr)] max-[640px]:has-checked:grid-cols-[72px_minmax(0,1fr)]">
  <nav class="@container flex min-w-0 flex-col overflow-hidden border-r border-[#e7e5eb] bg-[#fcfbfd] px-3 py-4 text-[.875rem] max-[640px]:border-r-0 max-[640px]:border-b max-[640px]:in-has-checked:border-r max-[640px]:in-has-checked:border-b-0" aria-label="Relay">
    <div class="flex items-center justify-between gap-2 pb-3.5 pl-1.5 @max-[140px]:flex-col @max-[140px]:gap-3 @max-[140px]:pb-2.5 @max-[140px]:pl-0"><a class="flex items-center gap-2.5 rounded-lg text-[1rem] font-bold whitespace-nowrap text-[#18181b] no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf]" href="#"><span class="grid size-8 flex-none place-items-center rounded-[10px] bg-[conic-gradient(from_200deg,#a21caf,#db2777,#f59e0b,#a21caf)] text-[.85rem] font-extrabold text-white" aria-hidden="true">R</span><span class="@max-[140px]:sr-only">Relay</span></a><label class="relative grid size-8 flex-none cursor-pointer place-items-center rounded-lg border border-[#d4d4d8] bg-white text-[#52525b] transition-colors duration-150 hover:bg-[#f4f4f5] has-focus-visible:outline-2 has-focus-visible:outline-offset-2 has-focus-visible:outline-[#a21caf] motion-reduce:transition-none"><input class="absolute inset-0 m-0 cursor-pointer opacity-0" type="checkbox" aria-label="Collapse sidebar"><svg class="size-4 @max-[140px]:-scale-x-100" aria-hidden="true"><use href="#i-panel"/></svg></label></div>
    <ul class="m-0 flex list-none flex-col gap-0.5 p-0">
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#" aria-current="page"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-inbox"/></svg><span class="@max-[140px]:sr-only">Inbox</span><span class="ml-auto rounded-full bg-[#a21caf] px-[7px] text-[.7rem] leading-[1.6] font-bold text-white @max-[140px]:absolute @max-[140px]:top-0.5 @max-[140px]:right-0.5 @max-[140px]:px-[5px] @max-[140px]:text-[.625rem]">12<span class="sr-only"> open</span></span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-user"/></svg><span class="@max-[140px]:sr-only">Assigned to me</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-hash"/></svg><span class="@max-[140px]:sr-only">Mentions</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-star"/></svg><span class="@max-[140px]:sr-only">Saved replies</span></a></li>
    </ul>
    <p class="mx-0 mt-4 mb-1.5 px-2.5 text-[.6875rem] font-bold tracking-[.08em] whitespace-nowrap text-[#63636d] uppercase @max-[140px]:mx-2.5 @max-[140px]:my-3 @max-[140px]:h-px @max-[140px]:overflow-hidden @max-[140px]:bg-[#e7e5eb] @max-[140px]:p-0 @max-[140px]:text-transparent">Channels</p>
    <ul class="m-0 flex list-none flex-col gap-0.5 p-0">
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-send"/></svg><span class="@max-[140px]:sr-only">Email</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-message"/></svg><span class="@max-[140px]:sr-only">Live chat</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-bell"/></svg><span class="@max-[140px]:sr-only">Phone</span></a></li>
    </ul>
    <ul class="m-0 flex list-none flex-col gap-0.5 p-0 mt-auto">
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-sliders"/></svg><span class="@max-[140px]:sr-only">Settings</span></a></li>
    </ul>
  </nav>
  <div class="flex min-w-0 flex-1 flex-col gap-[18px] overflow-hidden bg-[#f8fafc] px-7 py-[26px] max-[640px]:px-[18px] max-[640px]:py-5">
    <div class="flex flex-wrap items-end justify-between gap-3"><div><p class="m-0 text-[.75rem] text-[#5b6474]">Relay · Support inbox</p><h2 class="mt-0.5 mb-0 text-[1.25rem] leading-[1.3] font-bold tracking-[-.02em] text-[#0f172a]">Inbox</h2></div><span class="rounded-full border px-3 py-[5px] text-[.75rem] font-semibold border-[#d9dfe8] bg-white text-[#334155]">12 open</span></div>
    <div class="grid grid-cols-[repeat(auto-fit,minmax(128px,1fr))] gap-3"><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">First response</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">4m 20s</b></div><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">Resolved today</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">38</b><em class="text-[.72rem] font-semibold not-italic text-[#047857]">+6</em></div><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">Satisfaction</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">96%</b></div></div>
    <div class="flex min-h-[110px] flex-1 items-end gap-2 rounded-xl border border-[#e2e8f0] bg-white px-4 pt-4 max-[640px]:h-[90px] max-[640px]:min-h-0 max-[640px]:flex-none" aria-hidden="true"><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:46%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:60%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:54%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:72%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:64%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:58%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:76%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:70%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:84%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:66%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:78%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:88%"></i></div>
  </div>
</div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5b6474] uppercase">Modal drawer: <dialog>, invoker commands, @starting-style</span>
<div class="flex h-[460px] flex-col overflow-hidden rounded-2xl border border-[#d6dce5] bg-white shadow-[0_1px_2px_rgba(15,23,42,.05),0_18px_40px_-22px_rgba(15,23,42,.28)]">
  <div class="flex items-center gap-3 border-b border-[#e7e5eb] px-[18px] py-3"><button class="grid size-9 cursor-pointer place-items-center rounded-[10px] border border-[#d4d4d8] bg-white p-0 text-[#18181b] transition-colors duration-150 hover:bg-[#f4f4f5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none" type="button" commandfor="atlas-drawer" command="show-modal" aria-label="Open navigation"><svg class="size-[18px]" aria-hidden="true"><use href="#i-menu"/></svg></button><b class="text-[#18181b]">Articles</b><span class="ml-auto text-[.8rem] text-[#63636d]">Last edit 10:42</span></div>
  <div class="flex min-w-0 flex-1 flex-col gap-[18px] overflow-hidden bg-[#f8fafc] px-7 py-[26px] max-[640px]:px-[18px] max-[640px]:py-5">
    <div class="flex flex-wrap items-end justify-between gap-3"><div><p class="m-0 text-[.75rem] text-[#5b6474]">Atlas help centre</p><h2 class="mt-0.5 mb-0 text-[1.25rem] leading-[1.3] font-bold tracking-[-.02em] text-[#0f172a]">Articles</h2></div><span class="rounded-full border px-3 py-[5px] text-[.75rem] font-semibold border-[#d9dfe8] bg-white text-[#334155]">142 published</span></div>
    <div class="grid grid-cols-[repeat(auto-fit,minmax(128px,1fr))] gap-3"><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">Views this week</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">21.4k</b><em class="text-[.72rem] font-semibold not-italic text-[#047857]">+8.0%</em></div><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">Rated helpful</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">91%</b></div><div class="rounded-xl border border-[#e2e8f0] bg-white px-[15px] py-[13px]"><span class="block text-[.75rem] text-[#5b6474]">Searches with no result</span><b class="mt-[3px] block text-[1.2rem] leading-[1.3] tracking-[-.01em] text-[#0f172a]">37</b></div></div>
    <div class="flex min-h-[110px] flex-1 items-end gap-2 rounded-xl border border-[#e2e8f0] bg-white px-4 pt-4 max-[640px]:h-[90px] max-[640px]:min-h-0 max-[640px]:flex-none" aria-hidden="true"><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:52%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:44%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:60%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:68%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:58%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:74%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:66%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:80%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:62%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:76%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe] opacity-70" style="height:70%"></i><i class="flex-1 rounded-t-[5px] bg-[#f5d0fe]" style="height:84%"></i></div>
  </div>
</div>
<dialog class="fixed inset-y-2.5 right-auto left-2.5 m-0 h-auto max-h-none w-[min(300px,calc(100vw-20px))] max-w-none -translate-x-[calc(100%+20px)] flex-col overflow-hidden rounded-[18px] border-0 bg-[#fcfbfd] px-3 py-4 text-[.875rem] shadow-[0_30px_60px_-20px_rgba(24,24,27,.45)] transition-[translate,display,overlay] transition-discrete duration-[320ms] ease-[cubic-bezier(.3,0,.2,1)] backdrop:bg-[rgba(24,24,27,0)] backdrop:transition-[background-color,backdrop-filter,display,overlay] backdrop:transition-discrete backdrop:duration-[320ms] open:flex open:translate-x-0 open:backdrop:bg-[rgba(24,24,27,.4)] open:backdrop:backdrop-blur-[3px] starting:open:-translate-x-[calc(100%+20px)] starting:open:backdrop:bg-[rgba(24,24,27,0)] starting:open:backdrop:backdrop-blur-none motion-reduce:transition-none motion-reduce:backdrop:transition-none" id="atlas-drawer" closedby="any" aria-label="Atlas navigation">
  <div class="flex items-center justify-between gap-2 pb-3.5 pl-1.5"><a class="flex items-center gap-2.5 rounded-lg text-[1rem] font-bold whitespace-nowrap text-[#18181b] no-underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf]" href="#"><span class="grid size-8 flex-none place-items-center rounded-[10px] bg-[conic-gradient(from_200deg,#a21caf,#db2777,#f59e0b,#a21caf)] text-[.85rem] font-extrabold text-white" aria-hidden="true">A</span>Atlas</a><button class="grid size-9 cursor-pointer place-items-center rounded-[10px] border border-[#d4d4d8] bg-white p-0 text-[#18181b] transition-colors duration-150 hover:bg-[#f4f4f5] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none" type="button" commandfor="atlas-drawer" command="close" aria-label="Close navigation"><svg class="size-[18px]" aria-hidden="true"><use href="#i-x"/></svg></button></div>
  <nav aria-label="Atlas">
    <ul class="m-0 flex list-none flex-col gap-0.5 p-0">
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-home"/></svg><span class="@max-[140px]:sr-only">Home</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#" aria-current="page"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-file"/></svg><span class="@max-[140px]:sr-only">Articles</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-layers"/></svg><span class="@max-[140px]:sr-only">Collections</span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-archive"/></svg><span class="@max-[140px]:sr-only">Drafts</span><span class="ml-auto rounded-full bg-[#a21caf] px-[7px] text-[.7rem] leading-[1.6] font-bold text-white @max-[140px]:absolute @max-[140px]:top-0.5 @max-[140px]:right-0.5 @max-[140px]:px-[5px] @max-[140px]:text-[.625rem]">3<span class="sr-only"> drafts</span></span></a></li>
      <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-chart"/></svg><span class="@max-[140px]:sr-only">Analytics</span></a></li>
    </ul>
  </nav>
  <ul class="m-0 flex list-none flex-col gap-0.5 p-0 mt-auto">
    <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-sliders"/></svg><span class="@max-[140px]:sr-only">Settings</span></a></li>
    <li><a class="relative flex items-center gap-3 rounded-[9px] px-3 py-[9px] font-medium whitespace-nowrap text-[#52525b] no-underline transition-colors duration-150 hover:bg-[#f4f4f5] hover:text-[#18181b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#a21caf] motion-reduce:transition-none aria-[current=page]:bg-[#fbeaff] aria-[current=page]:font-semibold aria-[current=page]:text-[#86198f] @max-[140px]:justify-center @max-[140px]:p-2.5" href="#"><svg class="size-5 flex-none" aria-hidden="true"><use href="#i-logout"/></svg><span class="@max-[140px]:sr-only">Log out</span></a></li>
  </ul>
</dialog></div>
JavaScript
// Only for browsers without invoker commands (command / commandfor): wire the same buttons to the dialog API.
if (!('command' in HTMLButtonElement.prototype)) {
  document.querySelectorAll('button[commandfor]').forEach(function (btn) {
    btn.addEventListener('click', function () {
      var dialog = document.getElementById(btn.getAttribute('commandfor'));
      if (!dialog) return;
      if (btn.getAttribute('command') === 'show-modal') dialog.showModal(); else dialog.close();
    });
  });
}

About this set

Two sidebars that use current CSS and HTML for behaviour that usually needs JavaScript. The first is a support inbox whose collapse toggle is a checkbox inside the sidebar. The layout grid watches it with :has() and changes its first column from 244px to 72px, and the change animates because grid-template-columns can transition. The sidebar is also a size container, so a container query hides the labels, turns the Channels heading into a divider and moves the count onto the icon whenever the sidebar is narrower than 140px. That means the same markup compacts itself in any narrow column, not only when toggled. The second is a help-centre drawer built on a modal dialog element. The menu button opens it with command=”show-modal” and commandfor, the close button uses command=”close”, Esc closes it, and closedby=”any” closes it on a backdrop click. @starting-style animates the slide in both directions and the backdrop blurs the page behind. Because the dialog is modal, focus stays inside it and the page behind cannot be reached. A short script is included only for browsers that do not support invoker commands yet.

What’s included

  • Collapse driven by :has() on the layout grid, no JavaScript
  • Container query compacts the sidebar whenever it is narrow
  • Animated grid-template-columns change
  • Modal dialog drawer opened with invoker commands
  • Enter and exit animation with @starting-style and a blurred backdrop

Accessibility

The collapse toggle is a real checkbox labelled Collapse sidebar, and its visible square shows a focus outline when the checkbox has focus. Collapsed labels are visually hidden but still name every link. The drawer is a modal dialog with an aria-label, so it traps focus, makes the page inert and closes with Esc; its buttons have aria-labels. All transitions stop under prefers-reduced-motion.

Customise it

Change the --mx-* custom properties on .mx for colours, the 244px and 72px values in .mx-app for widths, and the 140px container query for the point where labels hide. Bootstrap uses a .btn-check toggle with the same CSS; Tailwind uses has-checked:, @container and @max-[140px]: utilities.