Sem mais introdução, vamos explorar o resultado final!
1. Comece com a marcação da página
Dentro de um wrapper, colocaremos o gatilho modal e um elemento vazio. Também agruparemos o conteúdo do botão em um span
elemento.
1 |
|
2 |
|
3 |
Contact Us
|
4 |
|
5 |
|
6 |
|
Com relação à estrutura modal, vamos pegá-la emprestada junto com a maioria de seus estilos de um tutorial anterior:
1 |
|
2 |
|
3 |
|
4 |
✕ |
5 |
|
6 |
|
7 |
|
8 |
|
2. Adicione o CSS
O botão e o elemento vazio terão dimensões fixas e a mesma cor de fundo.
O botão terá 190px x 50px, enquanto seu irmão terá 50px x 50px.
Além disso, o elemento vazio será posicionado de forma absoluta dentro de seu elemento pai e oculto por padrão, pois o botão terá um valor mais alto. z-index
valor.
Aqui estão os estilos relacionados usando aninhamento CSS:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.wrapper { |
4 |
position: relative; |
5 |
|
6 |
> * { |
7 |
background: var(--black); |
8 |
}
|
9 |
|
10 |
.open-modal { |
11 |
position: relative; |
12 |
display: block; |
13 |
width: 190px; |
14 |
height: var(--base-width); |
15 |
color: var(--white); |
16 |
border-radius: 30px; |
17 |
font-weight: bold; |
18 |
z-index: 1; |
19 |
}
|
20 |
|
21 |
.next { |
22 |
position: absolute; |
23 |
top: 50%; |
24 |
left: 50%; |
25 |
transform: translate(-50%, -50%); |
26 |
width: var(--base-width); |
27 |
aspect-ratio: 1; |
28 |
border-radius: 50%; |
29 |
}
|
30 |
}
|
O modal será um elemento posicionado fixo e oculto por padrão.
Aqui estão todos os seus estilos:
1 |
/*CUSTOM VARIABLES HERE*/
|
2 |
|
3 |
.modal { |
4 |
position: fixed; |
5 |
left: 0; |
6 |
bottom: 0; |
7 |
right: 0; |
8 |
align-items: center; |
9 |
justify-content: center; |
10 |
background: var(--black); |
11 |
visibility: hidden; |
12 |
opacity: 0; |
13 |
z-index: 2; |
14 |
|
15 |
&,
|
16 |
.close-modal { |
17 |
top: 0; |
18 |
color: var(--white); |
19 |
}
|
20 |
|
21 |
.modal-dialog { |
22 |
display: flex; |
23 |
width: 100%; |
24 |
height: 100vh; |
25 |
overflow: auto; |
26 |
}
|
27 |
|
28 |
.modal-content { |
29 |
max-width: 800px; |
30 |
padding: 1rem; |
31 |
margin: auto; |
32 |
|
33 |
p + p { |
34 |
margin-top: 1rem; |
35 |
}
|
36 |
}
|
37 |
|
38 |
.close-modal { |
39 |
position: absolute; |
40 |
right: 30px; |
41 |
font-size: 2rem; |
42 |
}
|
43 |
}
|
3. Adicione o JavaScript
Assim que o botão for clicado, iremos ocultá-lo e exibir o modal. Para facilitar esse processo, inicializaremos um cronograma GSAP que executará as seguintes ações:
- Oculte o conteúdo do botão.
- Defina a largura do botão igual à largura do irmão.
- Dimensione o elemento vazio até um ponto em que ele cubra todo o tamanho da página. Para garantir isso, executaremos alguma lógica dentro do
scaledValues()
função. - Mostre o modal.
- Assim que a linha do tempo terminar, adicionaremos o
is-visible
classe para o modal.
Aqui está o código JavaScript relacionado:
1 |
const openModal = document.querySelector(".open-modal"); |
2 |
const span = openModal.querySelector("span"); |
3 |
const next = openModal.nextElementSibling; |
4 |
const modal = document.querySelector(".modal"); |
5 |
const closeModal = modal.querySelector(".close-modal"); |
6 |
const baseWidth = 50; |
7 |
const IS_VISIBLE_CLASS = "is-visible"; |
8 |
|
9 |
function scaledValue() { |
10 |
let windowWidth = window.innerWidth; |
11 |
const windowHeight = window.innerHeight; |
12 |
|
13 |
if (windowHeight > windowWidth) { |
14 |
windowWidth = windowHeight; |
15 |
}
|
16 |
const toScale = windowWidth / baseWidth + 10; |
17 |
return Math.ceil(toScale); |
18 |
}
|
19 |
|
20 |
openModal.addEventListener("click", function () { |
21 |
const tl = gsap.timeline({ |
22 |
onComplete: () => modal.classList.add(IS_VISIBLE_CLASS) |
23 |
});
|
24 |
tl.to(span, { opacity: 0, duration: 0.25 }) |
25 |
.to(this, { width: baseWidth }) |
26 |
.to(next, { scale: scaledValue() }) |
27 |
.to(modal, { autoAlpha: 1 }); |
28 |
});
|
Uma vez que .close-modal
botão é clicado ou o ESC
for pressionada, inverteremos a lógica. Neste caso, definiremos uma nova linha do tempo e reverteremos as animações anteriores.
Aqui está o código JavaScript responsável por fechar o modal:
1 |
...
|
2 |
|
3 |
closeModal.addEventListener("click", function () { |
4 |
const tl = gsap.timeline({ |
5 |
onComplete: () => modal.classList.remove(IS_VISIBLE_CLASS) |
6 |
});
|
7 |
tl.to(modal, { autoAlpha: 0 }) |
8 |
.to(next, { scale: 1 }) |
9 |
.to(openModal, { width: 190 }) |
10 |
.to(span, { opacity: 1, duration: 0.25 }); |
11 |
});
|
12 |
|
13 |
document.addEventListener("keyup", (e) => { |
14 |
if ( |
15 |
e.key == "Escape" && |
16 |
document.querySelector(`.modal.${IS_VISIBLE_CLASS}`) |
17 |
) { |
18 |
closeModal.click(); |
19 |
}
|
20 |
});
|
Implementação Alternativa (método 2)
Uma forma alternativa e mais dinâmica é criar apenas um cronograma para ambas as ações e deixar o GSAP lidar com a lógica reversa através de seu reverse()
método.
Aqui está a demonstração relacionada para isso:
Conclusão
Pronto, pessoal! Com essas etapas simples e a ajuda da poderosa biblioteca de animação JavaScript GSAP, desenvolvemos uma bela animação de botão para modal que chama a atenção dos visitantes e traz uma experiência UX única ao nosso site. Espero que você goste tanto quanto eu e o incorpore em um projeto da web.
Antes de encerrar, vamos relembrar nossa animação original:
Por último, não se esqueça de navegar na biblioteca Tuts+ para mais tutoriais de animação CSS e JavaScript.
Como sempre, muito obrigado pela leitura!