Efeito em campo de formulário com CSS e JavaScript

Para esse tutorial, na parte de JavaScript, iremos utilizar só a linguagem, sem adotar framework ou biblioteca, primeiro porque o script será pequeno, e segundo porque sempre interessante desacoplar sua aplicação de framework, e de quebra aprendemos coisas novas, nesse caso, recursos do ES6 ou ECMAScript 2015.

Vamos seguir a premissa de separar as responsabilidade: HTML marcação, CSS estilização, e JavaScript comportamento.

Escrevendo HTML

Vamos definir nossa marcação com HTML.

<form action="" class="form-container">

</form>

 

Definimos primeiro o formulário, que apenas terá uma classe, nesse exemplo, .form-container.

É interessante adicionar classes a elementos os quais você precise estilizar ou precise fazer alterações pontuais mas não quer interferir em outros elementos iguais.

Prefira classes ao invés de id. Isso porque o id ele precisa ser único na página, e existe uma tendência de querermos reaproveitar os estilos, e não poderia adicionar o mesmo id em outro elemento para aproveitar o estilo.

<form action="" class="form-container">
        <div class="fields">
          
        </div>
</form>

 

Vamos agora adicionar uma div com a classe .fields , que servirá para agrupar o elemento do formulário.

É comum vermos utilizar a tag de parágrafo para esse fim, mas semanticamente não seria o ideal, já que não se trata de um paragrafo, e a div é um elemento “não semântico”, e nesse caso se encaixa perfeitamente.

<form action="" class="form-container">
    <div class="fields">
        <input type="text" name="name"  class="input" placeholder="Digite seu nome"/>
        
    </div>
</form>

 

Agora adicionamos um campo do formulário, um input do tipo text. Iremos adicionar uma classe chamada .input .

<form action="" class="form-container">
    <div class="fields">
        <input type="text" name="name"  class="input" placeholder="Digite seu nome"/>
        <div class="highlight"></div>
    </div>
</form>

 

Agora adicionaremos uma div com uma classe chamada .highlight, ela irá ser responsável pelo efeito, como fosse simular uma barra que vai acompanhando enquanto digitamos.

Pronto, basicamente esse é no nosso HTML.

Escrevendo CSS

Vamos criar um arquivo chamado style.css, e adicionar numa pasta chamada css.

Estrutura da pasta para o CSS

Antes de escrever o CSS, vamos linkar ao nosso arquivo index.html

<link rel="stylesheet" href="css/style.css" />

Para informar que iremos utilizar esse arquivo css,  adicionamos a tag link, e no atributo href, indica onde está o arquivo, esse código ficará dentro do bloco da tag head

Para um melhor entendimento do nosso código CSS, deixarei os blocos separados para uma melhor explicar, e depois no final mostro todo código CSS.

.form-container{
    width:500px;
    margin:0 auto;
}

 

  • Na linha 1, selecionamos o elemento do formulário;
  • Na linha 2, definimos a largura do formulário;
  • Na linha 3, definimos para que ele fique centralizado na horizontal.
.form-container .fields {
    position: relative;
    width: 100%;
    margin:25px auto;
}

 

  • Na linha 1, selecionamos o .fields . Nesse caso, usamos a seleção  a partir do elemento pai, que seria o .form-container;
  • Na linha 2, definimos um position com valor relative, porque no elemento filho .highlight será definido como absoluto e para garantimos o posicionamento de acordo com elemento pai, esse elemento será definido como relativo;
  • Na linha 3, definimos uma largura de 100%;
  • Na linha 4, definimos uma margin com altura e base de 25px e direito e esquerda com auto;
.form-container .input {
    width:100%;
    height: 50px;
    font-size: 12px;
    line-height: 12px;
    font-family: Arial, Helvetica, sans-serif;
    border:0;
    outline: none;
    border-bottom:3px solid #000; 
}

 

  • Na linha 1, selecionamos o elemento do formulário, que atribuímos a classe .input;
  • Na linha 2, definimos uma largura de 100%;
  • Na linha 3, uma altura de 50px;
  • Na linha 4, o tamanho da fonte para 12px;
  • Na linha 5, o espaço entre linhas também de 12px
  • Na linha 6, a fonte escolhemos Arial, Helvetica, sans-serif;
  • Na linha 7, removemos a borda;
  • Na linha 8, removemos o contorno;
  • Na linha 9, adicionamos uma borda na base, com 3px, ele servirá como uma linha-guia para fazermos o efeito.
.form-container .highlight{
    position: absolute;
    left:0;
    bottom: 0; 
    width: auto;
    max-width: 100%;
    height:0;
    overflow: hidden;
    border-top:3px solid #F00;
    font-size: 12px;
    line-height: 12px;
    font-family: Arial, Helvetica, sans-serif;
}

 

  • Na linha 1, selecionamos a div.highlight;
  • Na linha 2, definimos um position como absolute em relação ao elemento pai, que no caso é o form.form-container, e como definimos ele como position como relative, o calculo da posição dele será baseado no do pai, senão tivesse definido como relative o elemento pai, a base do calculo da posição seria o body;
  • na linha 3, definimos left:0 para que elemento encoste a esquerda;
  • Na linha 4, definimos bottom:0, para o elemento encoste na base;
  • Na linha 5, definimos uma largura como automática, onde navegador irá definir essa largura;
  • Na linha 6, definimos uma largura máxima de 100%;
  • Na linha 7, definimos uma altura como zero para não mostrar o conteúdo que existirá dentro dela;
  • Na linha 8, definimos o overflow como hidden para não permitir que conteudo seja exibido além do que foi definido na width e height;
  • Na linha 9, definimos uma borda no topo, que será o efeito quando pessoa tiver digitando;
  • Na linha 10, definimos o tamanho da fonte;
  • Na linha 11, definimos o espaço entre linha;
  • Na linha 13, definimos a fonte;

É importante as definições da tamanho, espaço de linha e fonte sejam o mesmo, tanto do campo input quanto na div.highlight

.form-container{
    width:500px;
    margin:0 auto;
}

.form-container .fields {
    position: relative;
    width: 100%;
    margin:25px auto;
}

.form-container .input {
    width:100%;
    height: 50px;
    font-size: 12px;
    line-height: 12px;
    font-family: Arial, Helvetica, sans-serif;
    border:0;
    outline: none;
    border-bottom:3px solid #000; 
}

.form-container .highlight{
    position: absolute;
    left:0;
    bottom: 0; 
    width: auto;
    max-width: 100%;
    height:0;
    overflow: hidden;
    border-top:3px solid #F00;
    font-size: 12px;
    line-height: 12px;
    font-family: Arial, Helvetica, sans-serif;
}

 

Escrevendo o JavaScript

Vamos criar agora o código JavaScript, que definirá o comportamento que desejamos, que seria ao digitar no campo input, ele vai adicionar o mesmo conteúdo digitado no elemento .highlight .

Vamos criar um arquivo chamado main.js, e adicionar na pasta js.

Estrutura da pasta para o Javascript

Agora vamos adicionar o JavaScript na nossa página html.

<script type="text/javascript" src="js/main.js"></script>

 

Criamos uma tag script, e com atributo src indicamos onde está o arquivo js. Esse código será adicionado antes do fechamento da tag body.

Nessa parte, iremos fazer como mostrado na parte do HTML, adicionaremos cada parte e comentando, para um melhor entendimento.

let fields = document.querySelectorAll('.fields');

 

Definimos uma variável com palavra reservada let. Ele é diferente da palavra reservada var, porque a var ela defini uma variável global, e o let definir de acordo escopo de bloco.

Nessa variável fields, ele recebe todos os elementos que tenham a classe .fields. Se você já usou jQuery, essa sintaxe já é familiar, só que você pode fazer nativamente com querySelectorAll .

let fields = document.querySelectorAll('.fields');

fields.forEach( element => {

});

 

Com document.querySelectorAll, ele retorna uma lista de elementos, e precisamos percorrer essa lista. E para isso usamos o forEach. Dentro desse forEach, executamos uma função anonima, que é passado o parâmetro o elemento que foi percorrido.

Essa sintaxe da função anonima é chamado arrow function. Seria uma forma curta para criação de uma função anonima, e onde o this é relacionado ao contexto e não define na função em si.

Isso poderia ser feito dessa forma, que no tutorial surgiria o mesmo efeito:

fields.forEach(function(element) {

});

 

Mas sempre é bom ver novos recursos, porque iremos ver cada vezes mais essa sintaxe.

let fields = document.querySelectorAll('.fields');

fields.forEach( element => {
    let input = element.querySelector('.input');
    let highlight = element.querySelector('.highlight');
});

 

Iremos recuperar o .input e .highlight. Agora usaremos o querySelector, que diferente do querySelectorAll, que retorna uma coleção de elementos, ele retorna apenas o primeiro. E usamos usando querySelector a partir os itens retornados do forEach.

let fields = document.querySelectorAll('.fields');

fields.forEach( element => {
    let input = element.querySelector('.input');
    let highlight = element.querySelector('.highlight');
    
    input.addEventListener('keyup', e => {

    });
});

 

Agora precisamos captura o que foi digitado pelo usuário. E pra isso adicionamos um evento ao input,  e para adicionar evento utilizamos addEventListener. No primeiro parâmetro informamos qual evento queremos, que seria keyup, e segundo o callback, que será executado quando for disparado o evento. Como é uma função anonima, usamos a sintaxe do arrow function.

let fields = document.querySelectorAll('.fields');

fields.forEach( element => {
    let input = element.querySelector('.input');
    let highlight = element.querySelector('.highlight');
    
    input.addEventListener('keyup', e => {
        let value = input.value;
        highlight.innerHTML = value;

    });
});

 

Agora criamos uma variável com nome value que recebe  o valor digitado no input. E depois adicionamos esse valor digitado dentro do elemento .highlight.

Pronto, dessa forma, basta digitar o valor do formulário, e vai aparecendo a barra acompanhando. Veja ele funcionando:

Algumas considerações

Quando foi solicitado para adicionar o JavaScript no final do body, ela é uma boa prática, para melhorar o carregamento da página. E outra questão, é porque é preciso carregar a estrutura dos elementos primeiro, para depois selecionarem. Mas se precisar adicionar na tag head, por exemplo? Precisaríamos informar para carregar o script só depois do carregamento do DOM. Para isso podemos fazer dessa forma:

document.addEventListener('DOMContentLoaded', function(){

 /*Aqui dentro iria o código*/

});

 

Adicionando a um evento DOMContentLoaded, que vai executar só quando carrega o DOM.

Outra questão é sobre o arrow functions. Lembre que informei sobre this, que ela é relacionado ao contexto, e não a ele mesmo. Vamos utilizar o tutorial para vermos isso na prática. Vamos trocar arrow functions para função anonima (expression functions).

let fields = document.querySelectorAll('.fields');

fields.forEach(function(element){
    let input = element.querySelector('.input');
    let highlight = element.querySelector('.highlight');
    input.addEventListener('keyup', function() {
        let value = this.value;
        highlight.innerHTML = value;
    });
});

 

Veja que o código permaneceu o mesmo, trocamos só arrow functions pelas funções anonimas (expression functions), mas dentro do evento keyup, ao invés de usar o input para recuperar o valor, usamos o this. Porque o this nesse caso, está relacionado a função, e não ao contexto, então ele pega o valor do evento disparado.

Nesse tutorial, vimos conceitos ES6, a definição de variável com let, arrow functions e a diferença com expression functions, como utilizar addEventListener, e como esperar a execução do código só apos carregar o DOM, com DOMContentLoaded.

Espero que tenham gostado e até a próxima.

 

 

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *