Marcação HTML
Use elementos semânticos e um botão flutuante para abrir o menu em telas pequenas:
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0">
<title>Layout Responsivo</title>
<link rel="stylesheet" href="/css/layout.css">
</head>
<body>
<div class="wrapper">
<nav class="drawer" id="drawer">
<h2 class="drawer-title">Navegação</h2>
<ul class="drawer-list">
<li class="drawer-item"><a href="#">Seção 1</a></li>
<li class="drawer-item"><a href="#">Seção 2</a></li>
<li class="drawer-item"><a href="#">Seção 3</a></li>
<li class="drawer-item"><a href="#">Seção 4</a></li>
</ul>
</nav>
<main class="main-content">
<h1>Conteúdo principal</h1>
<p>Texto de exemplo...</p>
</main>
</div>
<button class="menu-btn" id="menuBtn" aria-label="Abrir menu">
<span class="menu-btn__bar"></span>
<span class="menu-btn__bar"></span>
<span class="menu-btn__bar"></span>
</button>
<script src="/js/menu.js"></script>
</body>
</html>
Estilos CSS
A base é mobile-first: o menu é oculto fora da tela e o botão de menu é visível. Em telas maiores, o menu volta a ser uma coluna lateral e o botão some.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body, .wrapper {
height: 100%;
min-height: 100vh;
}
body {
font-family: system-ui, -apple-system, sans-serif;
}
.wrapper {
display: flex;
flex-direction: column;
}
.main-content {
flex: 1 1 auto;
padding: 1rem;
}
.drawer {
position: fixed;
top: 0;
left: 0;
width: 80vw;
max-width: 280px;
height: 100vh;
overflow-y: auto;
background-color: #2c3e50;
color: #ecf0f1;
transform: translateX(-100%);
transition: transform 0.3s ease-in-out;
z-index: 500;
padding: 1rem;
}
.drawer.visible {
transform: translateX(0);
}
.drawer-title {
font-size: 1.5rem;
margin-bottom: 1rem;
}
.drawer-list {
list-style: none;
}
.drawer-item {
margin-bottom: 0.75rem;
}
.drawer-item a {
color: inherit;
text-decoration: none;
}
.menu-btn {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
width: 50px;
height: 50px;
border: none;
border-radius: 50%;
background: #e67e22;
color: #fff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 5px;
z-index: 900;
cursor: pointer;
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
.menu-btn__bar {
display: block;
width: 24px;
height: 3px;
background: currentColor;
border-radius: 2px;
}
@media screen and (min-width: 501px) {
.wrapper {
flex-direction: row;
align-items: stretch;
}
.drawer {
position: static;
transform: none;
width: 260px;
max-width: none;
height: auto;
flex: 0 0 auto;
}
.main-content {
flex: 1 1 auto;
padding: 1.5rem;
}
.menu-btn {
display: none;
}
}
Controle em JavaScript
O script apenas alterna a classe do painel quando o botão é pressionado:
(function () {
const toggle = document.getElementById('menuBtn');
const drawer = document.getElementById('drawer');
const links = drawer.querySelectorAll('a');
function toggleMenu() {
drawer.classList.toggle('visible');
}
toggle.addEventListener('click', toggleMenu);
links.forEach(function (link) {
link.addEventListener('click', function () {
drawer.classList.remove('visible');
});
});
})();
Com essa abordagem, telas amplas exibem o menu lateral automaticamente, enquanto em telas pequenas ele aparece deslizando ao toque no botão.