<!-- we make focus here LOOK like focus on the label -->
<input type="checkbox" id="sidebar_control" role="button" aria-label="Menu">

<!-- label does not have implicit tabindex -->
<label id="sidebar__button" for="sidebar_control" role="button">☰</label>

<!-- Clickable underlay to close sidebar that's displayed when the sidebar is visible -->
<label id="sidebar__underlay" for="sidebar_control"></label>

<!-- Actual sidebar -->
<div id="sidebar">
    This is a demo sidebar!
    You can tab-focus
    <a href="#" id="clickable">this link</a>,
    but <strong>not</strong> if the sidebar is hidden (as while offscreen, the sidebar's CSS includes <code>visibility: hidden</code>)
    Click on the gray area to my right to close the sidebar (it's a giant <code>&lt;label&gt;</code> that points to the hamburger menu).
  <p id="clickcount"></p>

<div id="help">This checkbox controls the sidebar and would normally be hidden</div>

<div id="intro">
  <p class="hint">
    To open or close the sidebar, click this hamburger menu.
    It opens and closes without JS and was used in the <a href="https://developer.chrome.com/devsummit" target="_blank">Chrome Dev Summit</a> site for 2018.
    To find out more about this no-JS sidebar, read
    <a href="https://dev.to/chromiumdev/the-chrome-dev-summit-site-case-study-15ng" target="_blank">The Chrome Dev Summit site: case study</a>.
body {
  font-family: 'Roboto', 'Arial', Sans-Serif;

strong {
  font-weight: bold;

p {
  margin-bottom: 0.5em;
  line-height: 20px;

#clickcount {
  font-style: italic;

label#sidebar__button {
  position: fixed;
  top: 16px;
  left: 16px;
  width: 32px;
  height: 32px;
  line-height: 32px;
  font-size: 18px;
  text-align: center;
  background: #aaa8;
  border-radius: 4px;
  user-select: none;
  cursor: pointer;
  z-index: 1;

#sidebar {
  position: fixed;
  width: 320px;
  max-width: 100vw;
  min-height: 100vh;
  background: #f0f0f0;
  box-shadow: 0 0 4px #3337;
  will-change: transform;
  transform: translateX(-100%) translateX(-16px);
  box-sizing: border-box;
  padding: 64px 16px 16px;
  visibility: hidden;

  transition: transform 0.33s ease-in-out, visibility 0.33s step-end;

#sidebar__underlay {
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: #0008;
  will-change: opacity;
  transition: opacity 0.5s;
  pointer-events: none;
  opacity: 0;

input#sidebar_control {
  position: fixed;
  right: 4px;
  bottom: 8px;
  z-index: 1;

  &:active {
    & + label#sidebar__button {
      // "default" focus styles
      outline: #2196f3 auto 5px;
      outline: Highlight auto 5px;
      outline: -webkit-focus-ring-color auto 5px;

  &:checked {
    & ~ #sidebar {
      transition: transform 0.33s ease-in-out;
      transform: translate(0);
      visibility: visible;
    & ~ #sidebar__underlay {
      opacity: 1;
      pointer-events: auto;

#help {
  font-size: 12px;
  line-height: 18px;
  position: fixed;
  right: 0;
  bottom: 0;
  padding: 8px;
  padding-right: 24px;
  background: #00f3;
  max-width: 240px;

#intro {
  padding-left: 64px;
  padding-top: 16px;

  p.hint {
    line-height: 32px;

code {
  display: inline-block;
  font-family: monospace;
View Compiled
// This just adds functionality to something in the sidebar. It's not part of the demo. ¯\_(ツ)_/¯
let clickCount = 0;
const clickCountEl = document.getElementById('clickcount');

const clickable = document.getElementById('clickable');
clickable.addEventListener('click', (ev) => {
  clickCountEl.textContent = `Link clicked ${clickCount} times`;
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.