Barra de Navegação do Apple Dock feito com JavaScript

Vamos desenvolver uma Barra de Navegação estilo Dock da Apple utilizando HTML, CSS e JavaScript! Esse projeto recriará o famoso Apple Dock, incorporando animações fluidas e interatividade para uma experiência de usuário sofisticada.
Utilizaremos HTML para a estrutura do dock, CSS para a estilização e animações, e JavaScript para implementar efeitos de escala dinâmica ao passar o cursor sobre os ícones.
Vamos iniciar a criação da Barra de Navegação estilo Dock da Apple. Esse projeto é ideal para aprender a construir elementos de navegação interativos que sejam tanto funcionais quanto visualmente atraentes. Vamos transformar esse design inspirado na Apple em realidade!
HTML
Este código HTML cria uma barra de navegação interativa estilizada como o Apple Dock. Cada item de navegação exibe um ícone de aplicativo e uma dica de ferramenta com o nome do aplicativo ao passar o mouse. O design usa uma estrutura de lista ( <ul>
com <li>
itens), onde cada item contém uma imagem de ícone e uma dica de ferramenta. CSS externo (style.css
) define a aparência e os efeitos de foco, enquanto o arquivo JavaScript (script.js
) provavelmente adiciona interatividade. A gsap
biblioteca também está incluída para animações avançadas. Este design é limpo, moderno e visualmente envolvente, ideal para mostrar aplicativos ou ferramentas.
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Apple Dock Navigation Bar | codingstella</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<section class="cloneable">
<div class="nav-wrap">
<nav class="nav-bar">
<ul class="nav-list">
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/notion.png" loading="eager" alt="Notion app icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Notion</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/vs-code.png" loading="eager" alt="VS code icon" class="image"></a>
<div class="nav-item__tooltip">
<div>VS Code</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/slack.png" loading="eager" alt="Slack icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Slack</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/loom.png" loading="eager" alt="Loom icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Loom</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/spotify.png" loading="eager" alt="Spotify icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Spotify</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/app-store.png" loading="eager" alt="App store icon" class="image"></a>
<div class="nav-item__tooltip">
<div>App Store</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/canva.png" loading="eager" alt="Canva icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Canva</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/adobe-illustrator.png" loading="eager" alt="Adobe Illustrator icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Adobe Illustrator</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/figma.png" loading="eager" alt="figma icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Figma</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/adobe-photoshop.png" loading="eager" alt="Photoshop icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Photoshop</div>
</div>
</li>
<li class="nav-item">
<a href="#" class="nav-item__link"><img src="/Images/adobe-premierepro.png" loading="eager" alt="Premiere Pro icon" class="image"></a>
<div class="nav-item__tooltip">
<div>Premiere Pro</div>
</div>
</li>
</ul>
</nav>
</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
CSS
Este CSS define uma barra de navegação responsiva e visualmente atraente e um estilo geral do site. Ele configura propriedades personalizadas (variáveis CSS) para cores, animações e espaçamento consistentes, com ajustes responsivos para diferentes tamanhos de tela. Os itens de navegação se expandem ao passar o mouse, afetando itens vizinhos para uma interação suave. Ele também inclui redefinições globais, oculta barras de rolagem para uma aparência limpa e estiliza dicas de ferramentas com animações para melhor experiência do usuário.
:root {
--color-light: var(--color-neutral-200);
--color-dark: var(--color-neutral-800);
--color-primary: #ff4c24;
--color-neutral-100: #ffffff;
--color-neutral-200: #efeeec;
--color-neutral-300: #e3e1de;
--color-neutral-400: #cbc8c5;
--color-neutral-500: #818180;
--color-neutral-600: #2c2c2c;
--color-neutral-700: #1f1f1f;
--color-neutral-800: #131313;
--color-neutral-900: #000000;
--color-white: var(--color-neutral-100);
--color-black: var(--color-neutral-900);
--color-error: var(--color-primary);
--color-success: #0ba954;
--cubic-default: cubic-bezier(0.65, 0.05, 0, 1);
--duration-default: 0.735s;
--animation-default: var(--duration-default) var(--cubic-default);
--gap: 2em;
--section-padding: calc(3.5em + (var(--gap) * 2));
--container-padding: 2em;
--header-height: calc(1.5em + (var(--gap) * 2));
--footer-height: calc(2.785em + (var(--gap) * 2));
}
/* Tablet */
@media screen and (max-width: 991px) {
:root {
--container-padding: 1.5em;
}
}
/* Mobile Landscape */
@media screen and (max-width: 767px) {
:root {
--container-padding: 1em;
}
}
/* Mobile Portrait */
@media screen and (max-width: 479px) {
:root {}
}
/* Desktop */
:root {
--size-unit: 16; /* body font-size in design - no px */
--size-container-ideal: 1440; /* screen-size in design - no px */
--size-container-min: 992px;
--size-container-max: 1920px;
--size-container: clamp(var(--size-container-min), 100vw, var(--size-container-max));
--size-font: calc(var(--size-container) / (var(--size-container-ideal) / var(--size-unit)));
}
/* Tablet */
@media screen and (max-width: 991px) {
:root {
--size-container-ideal: 834; /* screen-size in design - no px */
--size-container-min: 768px;
--size-container-max: 991px;
}
}
/* Mobile Landscape */
@media screen and (max-width: 767px) {
:root {
--size-container-ideal: 390; /* screen-size in design - no px */
--size-container-min: 480px;
--size-container-max: 767px;
}
}
/* Mobile Portrait */
@media screen and (max-width: 479px) {
:root {
--size-container-ideal: 390; /* screen-size in design - no px */
--size-container-min: 320px;
--size-container-max: 479px;
}
}
/* ------------------------- Hide Scrollbar -------------------------------------------------- */
body ::-webkit-scrollbar,
body::-webkit-scrollbar {display: none;}
body {-ms-overflow-style: none;}
html {scrollbar-width: none;}
/* ------------------------- Reset -------------------------------------------------- */
*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html {
scroll-behavior: initial;
}
html,
body {
-webkit-font-smoothing: antialiased;
}
svg {
max-width: none;
height: auto;
box-sizing: border-box;
vertical-align: middle;
}
a {
color: inherit;
}
/* Selection */
::selection {
background-color: var(--color-primary);
color: var(--color-dark);
text-shadow: none;
}
::-moz-selection {
background-color: var(--color-primary);
color: var(--color-dark);
text-shadow: none;
}
/* Additional Styling */
body {
background-color: var(--color-neutral-300);
color: var(--color-dark);
font-size: var(--size-font);
font-family: Arial, sans-serif;
}
.cloneable {
padding: var(--container-padding);
justify-content: center;
align-items: center;
min-height: 100vh;
display: flex;
position: relative;
}
.nav-wrap {
z-index: 100;
pointer-events: none;
justify-content: center;
align-items: flex-end;
display: flex;
position: fixed;
inset: 0 0 10vh;
}
.nav-list {
flex-flow: row;
justify-content: center;
align-items: flex-end;
margin-bottom: 0;
padding-left: 0;
display: flex;
font-size: 1.4vw;
}
.nav-item {
justify-content: center;
align-items: center;
width: 5em;
transition: width .5s cubic-bezier(.16, 1, .3, 1);
display: flex;
position: relative;
}
.nav-item.hover {
width: 8em;
}
.nav-item.sibling-close {
width: 7em;
}
.nav-item.sibling-far {
width: 6em;
}
.nav-item__link {
z-index: 1;
pointer-events: auto;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
padding-left: .5em;
padding-right: .5em;
display: flex;
position: relative;
}
.image {
object-fit: contain;
width: 100%;
}
.nav-item__tooltip {
z-index: 0;
background-color: var(--color-neutral-100);
opacity: 0;
white-space: nowrap;
border-radius: .25em;
padding: .4em .5em;
font-size: 1em;
transition: transform .5s cubic-bezier(.16, 1, .3, 1), opacity .5s cubic-bezier(.16, 1, .3, 1);
position: absolute;
top: 0;
transform: translate(0, -80%);
font-weight: 400;
}
.nav-item:hover .nav-item__tooltip {
opacity: 1;
transform: translate(0px, -140%);
}
JavaScript
Este código escuta a página carregar completamente e então adiciona efeitos de foco a elementos com a .nav-item
classe. Quando um item é focalizado, ele se destaca ( hover
class) e irmãos próximos usando classes personalizadas ( sibling-close
e sibling-far
) com base em sua distância. Essas classes são adicionadas ou removidas dinamicamente para criar efeitos de foco interativos, tornando a navegação visualmente envolvente.
document.addEventListener("DOMContentLoaded", () => {
// Select all .nav-item elements
const navItems = document.querySelectorAll('.nav-item');
// Helper function to add/remove a class to a sibling at a given offset
const toggleSiblingClass = (items, index, offset, className, add) => {
const sibling = items[index + offset];
if (sibling) {
sibling.classList.toggle(className, add);
}
};
// Event listeners to toggle classes on hover
navItems.forEach((item, index) => {
item.addEventListener('mouseenter', () => {
item.classList.add('hover'); // Add .hover to current item
// Toggle classes for siblings
toggleSiblingClass(navItems, index, -1, 'sibling-close', true); // Previous sibling
toggleSiblingClass(navItems, index, 1, 'sibling-close', true); // Next sibling
toggleSiblingClass(navItems, index, -2, 'sibling-far', true); // Previous-previous sibling
toggleSiblingClass(navItems, index, 2, 'sibling-far', true); // Next-next sibling
});
item.addEventListener('mouseleave', () => {
item.classList.remove('hover'); // Remove .hover from current item
// Toggle classes for siblings
toggleSiblingClass(navItems, index, -1, 'sibling-close', false); // Previous sibling
toggleSiblingClass(navItems, index, 1, 'sibling-close', false); // Next sibling
toggleSiblingClass(navItems, index, -2, 'sibling-far', false); // Previous-previous sibling
toggleSiblingClass(navItems, index, 2, 'sibling-far', false); // Next-next sibling
});
});
});
Concluímos nosso projeto Barra de Navegação estilo Dock da Apple utilizando HTML, CSS e JavaScript. Se seu projeto tiver problemas, não se preocupe. Basta clicar para baixar o código-fonte e encarar seus desafios de codificação com entusiasmo. Divirta-se codificando!

Sobre o Autor
0 Comentários