Como construir um efeito de deslocamento de sublinhado flutuante com CSS e JavaScript

No tutorial de hoje, vamos usar um pouco de CSS e JavaScript para criar um efeito de menu flutuante sofisticado. Não é um resultado final complicado, mas construí-lo será uma ótima oportunidade para praticar nossas habilidades de front-end.

Sem mais introduções, vamos conferir o que vamos construir:

A marcação

Começamos com algumas marcações bem básicas; uma nav elemento que contém o menu e um vazio span elemento:

O CSS

Com a marcação pronta, a seguir especificamos alguns estilos básicos para os elementos relacionados:

Observe que o span elemento (.target) está absolutamente posicionado. Como veremos em breve, usaremos JavaScript para determinar sua posição exata. Além disso, deve aparecer atras do os links do menu, por isso damos uma nota negativa z-index.

  • A propriedade z-index em CSS parece bastante simples, mas há muito o que descobrir sob a superfície se você realmente quiser entender como ela funciona. Nisso…

O JavaScript

Neste ponto, vamos focar nossa atenção no JavaScript necessário. Para começar, temos como alvo os elementos desejados. Também definimos um array de cores que usaremos mais tarde.

Eventos

A seguir, ouvimos o click e mouseenter eventos dos links do menu.

Quando o click evento acontecer, impedimos que a página seja recarregada. Claro, isso funciona no nosso caso porque todos os links têm um vazio href atributo. Em um projeto real, no entanto, cada um dos links do menu provavelmente abriria uma página diferente.

O mais importante é que assim que o mouseenter incêndios de eventos, o mouseenterFunc função de retorno de chamada é executada:

mouseenterFunc

O corpo do mouseenterFunc função fica assim:

Dentro desta função fazemos o seguinte:

  1. Adicione o active class para o pai imediato (li) do link de destino.
  2. Diminua o opacity de todos os links do menu, exceto o "ativo".
  3. Use o getBoundingClientRect método para recuperar o tamanho do link associado e sua posição em relação à viewport.
  4. Obtenha uma cor aleatória da matriz mencionada e passe-a como valor para o border-color propriedade do span elemento. Lembre-se, seu valor de propriedade inicial é definido como transparent.
  5. Atribua os valores extraídos do getBoundingClientRect método para as propriedades correspondentes do span elemento. Em outras palavras, o span tag herda o tamanho e a posição do link sobre o qual o cursor está passando.
  6. Redefina a transformação padrão aplicada ao span elemento. Esse comportamento só é importante na primeira vez que passamos o mouse sobre um link. Neste caso, a transformação do elemento vai de transform: translateX(-60px) para transform: none. Isso nos dá um bom efeito de deslizamento.

Se ativo

É importante observar que o código acima é executado toda vez que passamos o mouse sobre um link. Portanto, ele também é executado quando passamos o mouse sobre um link “ativo”. Para evitar esse comportamento, envolvemos o código acima dentro de um if declaração:

Até agora, nossa demonstração é a seguinte:

Quase, mas não completamente

Então, tudo parece funcionar como esperado, certo? Bem, isso não é verdade porque se rolarmos pela página ou redimensionarmos a janela de visualização e tentarmos selecionar um link, as coisas ficarão confusas. Especificamente, a posição do span elemento fica incorreto.

Brinque com a demonstração de página inteira (certifique-se de ter adicionado conteúdo fictício suficiente) para ver o que quero dizer.

Para resolvê-lo, temos que calcular o quanto rolamos do topo da janela e adicionar esse valor ao valor atual top valor do elemento de destino. Da mesma forma, devemos calcular o quanto o documento foi rolado horizontalmente (apenas no caso). O valor resultante é adicionado ao valor atual left valor do elemento de destino.

Aqui estão as duas linhas de código que atualizamos:

Tenha em mente que todo o código acima é executado assim que o navegador processa o DOM e encontra o script relevante. Novamente, para suas próprias implementações e designs, você pode querer executar este código quando a página for carregada, ou algo assim. Nesse cenário, você terá que incorporá-lo em um manipulador de eventos (por exemplo, load manipulador de eventos).

Janela de exibição

A última coisa que precisamos fazer é garantir que o efeito ainda funcione conforme redimensionamos a janela do navegador. Para isso, ouvimos o resize evento e registre o resizeFunc manipulador de eventos.

Aqui está o corpo deste manipulador:

Dentro da função acima, fazemos o seguinte:

  1. Verifique se há um item de lista de menu com a classe de active. Se lá é tal elemento, que indica que já passamos o mouse sobre um link.
  2. Obtenha o novo left e top propriedades do item “ativo” junto com as propriedades de janela relacionadas e atribua-as ao span elemento. Observe que recuperamos os valores apenas para as propriedades que mudam durante o resize evento. Isso significa que não há necessidade de recalcular a largura e a altura dos links do menu.

Suporte ao navegador

A demonstração funciona bem em todos os navegadores recentes. Se você encontrar algum problema, deixe-me saber nos comentários abaixo. Além disso, como você deve ter notado, usamos Babel para compilar nosso código ES6 para ES5.

Conclusão

Neste tutorial, passamos pelo processo de criação de um efeito de foco de menu simples, mas interessante.

Espero que você tenha gostado do que construímos aqui e se inspirado para desenvolver efeitos de menu ainda mais poderosos, como o que aparece (no momento da redação) no site do Stripe.

Você já criou algo parecido? Se sim, não deixe de compartilhar conosco os desafios que você enfrentou.

Deixe um comentário

O seu endereço de e-mail não será publicado.