Construindo Formulários Semanticamente Corretos - Parte Final
Finalmente chegamos na tão esperada parte onde iremos estilizar nosso formulário, na segunda parte vimos diferentes formas de construir nosso xhtml e criamos então da forma mais simples possível, seguindo todos os conceitos de acessibilidade em formulários.
Vale lembrar que não existe nenhuma fórmula mágica para estilização destes elementos, então se você espera não ter que pensar/trabalhar na hora de construir formulários, está no site (e talvez até no emprego) errado.
Você pode conferir o que temos até agora
nesta página.
Antes de começar podemos fazer uma pequena análise de algumas características básicas:
- O texto é alinhado à direita em relação ao lado esquerdo da tela
- Existe uma certa padronização quanto às larguras dos campos de texto.
Feito isso já podemos fazer algumas coisas relacionadas à estrutura geral, e a aparência em si dos campos:
/*zerando as margens dos elementos*/
*{
margin:0;
padding:0;
}
form{
width:740px;
padding:15px;
/*largura total = 740+15+15*/
}
fieldset{
border:none;
margin-bottom:25px;
}
/*os 'legend' são itens de acessibilidade, não precisam ser
mostrados, ao menos não em nosso caso*/
legend{
display:none;
}
label, span{
color:#f00;
font:1.3em Arial, Helvetica, sans-serif;
}
input, textarea, select{
border:1px solid #00F;
}
/*o ie coloca bordas nos inputs do tipo radio e checkbox, então
precisamos de um pequeno concerto*/
input.radio {
border:none;
}
Adicione a classe "radio" nos inputs do primeiro fieldset, para os checkboxes lá em baixo, espere mais um pouco, vamos por partes, certo?
Veja que após acrescentar estas linhas nosso formulário já ganhou um aspecto muito melhor, o resto é simplesmente questão de posicionamento.
Para as larguras de campos há um grande problema semântico: Não se deve criar nomes de classes referentes à aparência dos elementos na tela, mas o problema dos input's é: "E então que nomes eu dou para as classes de forma a identificá-las mais tarde?"
Eu abro uma exceção à regra nesses casos, crio classes com os nomes "maior", "médio", "menor", realmente não encontrei uma alternativa que facilitasse.
Apenas uma ressalva: já vi pessoas criando os nomes de classe assim: "input432px", "input220px", "input45px".
Isso é loucura, além de ser totalmente não-semântico, você vai é ter um nó no cérebro se um dia precisar mudar alguma coisa.
Continuando, podemos ver que na maioria dos fieldsets temos os campos um abaixo do outro, acrescentando mais um pouco de código, vamos ter o efeito que precisamos (já fazendo o alinhamento à direita):
label, span{
color:#f00;
font:1.3em Arial, Helvetica, sans-serif;
display:block;
text-align:right;
}
Posicionado do modo correto, agora vamos cuidar dos tamanhos dos inputs, como comentei, defino os nomes de classe como "grande", "medio", "pequeno" ainda defini uma intermediária "médio-maior", eu sei que não é semântico, mas foi o método que considerei melhor:
/* tamanhos */
.grande{
width:500px;
}
.medio-maior{
width:430px;
}
.medio{
width:185px;
}
.pequeno{
width:30px;
}
E então fazemos algumas pequenas correções para os campos select, que devido à barra de seleção lateral, ficam com larguras diferentes:
/* correção de tamanhos para os selects */
select.pequeno{/*dia e ano de nascimento*/
width:40px;
}
select.pequeno-maior{/*mês de nascimento*/
width:100px;
}
select.medio{/*estado*/
width:189px;
}
Bem, agora precisamos colocar estas classes nos devidos elementos:
- A classe "grande" deve ser colocada em todos os inputs do fieldset "Dados familiares" e nas textarea. Isso nos indica que sequer precisamos desta classe, só precisamos colocar uma classe em cada um desses fieldsets e então definir as larguras, assim:
fieldset.dados-familiares input, fieldset.info-add textarea
{
width:500px;
}
E deletamos a classe "grande"
.grande{
width:500px;
}
- A classe "medio" deve ser colocada em todos os inputs que ocupam metade da largura do formulário, incluindo o select do estado. Ex.: Nome, Idade, Bairro, Cidade etc.
- A classe "pequeno" vai nos selects do dia de nascimento, do ano de nascimento e ainda no input "Nº" no fieldset de endereços.
- A classe "pequeno-maior" vai no select de mes de nascimento
- Finalmente, a classe "medio-maior" vai no input de endereço
Ufa, já tivemos um grande avanço não acham? Nosso formulário já está bem apresentável pelo menos

Agora só falta o posicionamento em si.
Para isso pode-se usar floats para os label (e encarar todos os bugs que podem acontecer no IE) ou usar um método um pouco mais "chato" baseado em display inline e margens direita e esquerda, que é o que vamos usar aqui.
Primeiramente vamos transformar os label's (e span's) que precisamos em elementos "inline", quais são eles? Todos os que devem ficar lado a lado. Falando nisso, vamos aproveitar a dar uma classe para cada fieldset, vamos usar cada uma delas agora:
/*labels que precisam ser inline*/
fieldset.interesses label,
fieldset.turnos label,
fieldset.info-pessoal label,
fieldset.info-pessoal span,
fieldset.dados-postais label,
fieldset.dados-postais span{
display:inline;
}
Parece que estamos regredindo? Não se preocupe, é assim mesmo, agora o que precisamos é dar as devidas margens para posicionar os label, também dando classes para os mesmos, utilizando inclusive os seus próprios textos para nomes dessas classes:
/*posições - labels inline*/
/*fieldset de informações pessoais*/
label.nome{
margin-left:177px;
margin-right:12px;
}
label.idade{
margin-left:179px;
margin-right:12px;
}
label.masculino{
margin-right:37px;
}
span.data-de-nascimento{
margin-left:99px;
}
label.signo{
margin-left:11px;
}
label.signo input{
width:239px;
}
/* fieldset de dados postais */
label.endereco{
margin-left:141px;
margin-right:6px;
}
label.bairro{
margin-left:174px;
}
/*pequeno ajuste de largura-alinhamento*/
label.cidade input, label.cep input{
width:237px;
}
label.estado{
margin-left:165px;
margin-right:21px;
} E aí está! Todos os campos alinhados e no lugar! Só falta uma pequena correção para o IE, via comentários condicionais:
<!--[if IE]>
<style type="text/css">
label.masculino{margin-right:25px;}
</style>
<![endif]-->
Vamos partir agora para o fieldset de "info-add", vemos que está bem posicionado, mas o texto deve ficar no início de cada textarea e não embaixo, alguém poderia pensar em colocar um span envolvendo este texto e posicioná-lo, e admito que eu também pensei isso, mas não será possível fazê-lo apenas com CSS?
Vamos pensar nessa separação como duas colunas distintas, primeiro eu empurro os textareas para a direita com float:right, então vemos os respectivos labels perdendo as margens entre eles e subindo, logo damos de volta esta margem com a diferença de não influenciar nos textarea, que estão com float, entender melhor? Assim:
fieldset.info-add label textarea{
float:right;
}
fieldset.info-add label{
margin-bottom:80px;
}
E já temos quase tudo alinhado, só falta uma pequena margem negativa no textarea:
fieldset.info-add label textarea{
float:right;
[b]margin-top:-20px;[/b]
}
Tudo bem alinhado aí? Aqui também está certo, com o único problema de o texto estar em cima do textarea.
O que precisamos fazer agora é posicioná-lo para a esquerda, mas como fazer para apenas o texto se mexer? Veja:
fieldset.info-add label{
margin-bottom:80px;
[b]position:relative;[/b]
[b]right:502px;[/b]
}
fieldset.info-add label textarea{
float:right;
margin-top:-20px;
[b]position:relative;[/b]
[b]left:502px;[/b]
}
O que fizemos? Colocamos o label inteiro 502 pixels para a esquerda e depois somente o textarea 502 pixels para a direita, fácil né?
Vamos apenas corrigir uma falha visual do IE, que deixou muita margem entre os label:
<!--[if IE]>
<style type="text/css">
fieldset.info-add{margin-bottom:-65px;}
fieldset.info-add label{margin-bottom:65px;}
</style>
<![endif]-->
Mais um detalhe: percebeu como o IE deixa a barra de rolagem no textarea mesmo sem precisar? O problema é que o padrão do IE é diferente do Firefox neste caso, vamos torná-los iguais:
textarea{
overflow:auto;
}
Vamos lá que falta pouco! Passando para os checkboxes, podemos usar o mesmo procedimento que fizemos com os label's inline lá de cima, colocando as devidas classes e não esquecendo de retirar a borda que fica no IE:
fieldset.turnos label{
float:right;
margin-right:70px;
}
fieldset.turnos input{
border:none;
/*para alinhar verticalmente*/
position:relative;
top:-3px;
margin-right:5px;
}
E outra correção para o IE, que deixa os checkboxes alinhados por padrão (lembre-se de colocar essas correções dentro do mesmo 'if' condicional):
<!--[if IE]>
<style type="text/css">
fieldset.turnos input{position:static;}
</style>
<![endif]-->
Agora note uma coisa: Onde está a palavra "Turnos" em nosso XHTML? Exato, agora é hora de usarmos o legend oculto para auxiliar, portanto não há necessidade de mexer em nosso XHTML! Primeiramente colocamos as mesmas propriedades de label e span neste legend:
label, span, [b]fieldset.turnos legend[/b]{
display:block;
text-align:right;
color:#f00;
font:1.3em Arial, Helvetica, sans-serif;
}
E então posicionamos no lugar certo:
fieldset.turnos legend{
text-align:left;
padding-left:168px;
margin-bottom:-25px;
}
Já no IE foi necessário posicionar de outra forma:
<!--[if IE]>
<style type="text/css">
fieldset.turnos legend{
position:relative;
top:23px;
padding-left:160px;
margin-bottom:0;
}
</style>
<![endif]-->
Mais um último fôlego pois estamos quase terminando!
No último fieldset vamos usar mais uma vez o legend como identificador e posicionar os labels com float e margens, assim como fizemos acima:
label, span, fieldset.turnos legend,
[b]fieldset.interesses legend[/b]{
display:block;
text-align:right;
color:#f00;
font:1.3em Arial, Helvetica, sans-serif;
}
fieldset.interesses legend{
text-align:left;
padding-left:132px;
margin-bottom:-25px;
}
fieldset.interesses label{
float:left;margin-right:18px;
}
fieldset.interesses input{
border:none;
margin-right:5px;
margin-bottom:3px;
}
E novamente ajustes para o IE:
<!--[if IE]>
<style type="text/css">
fieldset.interesses input{
margin-bottom:0;
}
fieldset.interesses legend{
padding-left:124px;
}
</style>
<![endif]-->
E então o posicionamento via margens como já conhecemos:
label.natacao{
position:relative;
left:-5px;
/*como o valor é negativo, não podemos
usar margem.
*/
}
label.informatica, label.bingo, label.viagens{
margin-left:320px;
}
label.xadrez{
margin-left:20px;
}
label.livros{
margin-left:48px;
}
label.games{
margin-left:51px;
}
label.tecnologia{
margin-left:25px;
}
label.sobrenatural{
position:relative;
left:5px;
}
E mais correções para IE:
<!--[if IE]>
<style type="text/css">
label.informatica, label.bingo, label.viagens{
margin-left:299px;
}
</style>
<![endif]-->
Agora a única coisa que falta é o campo de anexos. Há algo a falar sobre ele, este tipo de campo é o que mais costuma mudar em cada browser, sua aparência é extremamente diferente entre Firefox, IE, Opera e Safari por exemplo.
Para ter uma idéia, o Firefox sequer aceita aumentar a largura dele (aumenta sim, mas apenas o background, não a posição do botão). Sua estilização foi abordada
neste tutorial de Peter-Paul Koch, mas apesar de tudo o resultado final não é de todo satisfatório e prefiro continuar com a estilização padrão que eles aceitam.
Aqui apenas adicionei isto:
fieldset.dados-familiares input,
fieldset.info-add textarea,
[b]fieldset.anexos input[/b]{
width:500px;
}
E pronto! Estamos com nosso formulário 100% pronto! Você pode ver o resultado final completo
nesta página.
Sei que deu trabalho, mas espero que tenham gostado e consigam adaptar em seus projetos, pessoal!