Voltando à ativa depois de tanto tempo de inatividade, quero mostrar a vocês um exemplo comum de uso das camadas de conteúdo e apresentação. Um menu com imagens e rollover, mais acessível do que o normal e não muito complicado de se fazer.

O conceito é bastante simples: um DIV contendo uma lista não ordenada (UL), cujos itens são posicionados de maneira absoluta, funcionando mais ou menos como um mapa de imagens (MAP). O rollover é obtido mudando o posicionamento da imagem de fundo. No final, vou mostrar algumas modificações que podem ser usadas para tornar o menu mais acessível.

Vamos começar do começo, como sempre:

Código HTML básico


<div id="menu">
  <ul>
    <li><a href=”#”>Início</a></li>
    <li><a href=”#”>Artigos</a></li>
    <li><a href=”#”>Contato</a></li>
  </ul>
</div>

O código acima é praticamente tudo que vamos precisar ter na camada de conteúdo. Bem simples, como deve ser. Veja o exemplo 1.

Posicionando o que tem que ser posicionado


  <style type="text/css">
    #menu{ position:relative; width:186px; height:35px; }
    #menu ul{ list-style:none; }
    #menu li{
      position:absolute;
      top:0;
      height:35px;
      border:1px solid;
    }
    #menu li a{
      display:block;
      width:100%;
      height:100%;
      top:0;
    }
    #um{ width:53px; left:0; }
    #dois{ width:61px; left:53px; }
    #tres{ width:72px; left:114px; }
  </style>

<div id=”menu”>
  <ul>
    <li id=”um”><a href=”#”>Início</a></li>
    <li id=”dois”><a href=”#”>Artigos</a></li>
    <li id=”tres”><a href=”#”>Contato</a></li>
  </ul>
</div>

Adicionamos um ID para cada item da lista, para que suas posições e larguras possam ser definidos separadamente.

O DIV menu precisa ter posicionamento relativo, para “conter” seus filhos, que serão posicionados de maneira absoluta. (leia meu artigo sobre posicionamento com CSS)

Note que cada LI tem uma largura (width) e uma posição horizontal (left) diferentes. O cálculo é simples: o valor de left é sempre a largura do LI anterior somado ao valor de left deste.

Usamos uma borda apenas para ilustrar. Veja o resultado no exemplo 2.

Adicionando uma imagem de fundo

A imagem de fundo deve ser o menu inteiro. Algo mais ou menos como a imagem abaixo:

Imagem usada para ser o fundo do menu

Esta imagem vai ser aplicada como fundo do DIV menu. E esta é a única mudança com relação ao exemplo anterior:


#menu{
  position:relative;
  width:186px;
  height:35px;
  background:url(img1.gif) no-repeat 0 0;
}

Veja o resultado no exemplo 3. Note que o texto está por cima da imagem. Vamos resolver isso.

Escondendo o texto

A forma mais simples de esconder o texto é usando a propriedade CSS text-indent com um valor negativo muito alto. Vamos usar -9999em. Isso faz com que o texto seja levado para a esquerda e fique fora do espaço visível.

Esta técnica tem sido muito usada para efeitos de image replacement, que é como chamamos os métodos usados para substituir texto por imagens, usando CSS.

Este método, usando text-indent negativo, é efetivo, porém tem o problema de não exibir conteúdo algum caso o browser tenha suporte a CSS ligado e suporte a imagens desligado. Esta é uma situação bem difícil de acontecer, mas nem por isso devemos deixar de nos preocupar. Vamos achar uma maneira de resolver este problema no último passo do tutorial.

O que muda no código:


#menu ul{
  list-style:none;
  text-indent:-9999em;
}
#menu li a{
  display:block;
  text-decoration:none;
  width:100%;
  height:100%;
  top:0;
}

O text-indent negativo foi aplicado ao UL e colocamos um text-decoration:none no A, para evitar que apareça uma linha azul estranhíssima em algumas versões do IE.

Veja o resultado no exemplo 4.

Adicionando o efeito de rollover

Para obter o efeito de rollover (ou seja, alguma mudança ao se passar o mouse sobre o elemento), vamos mudar a imagem usada como fundo. Apenas duplicamos a imagem e mudamos alguma coisa em cada um do itens. Neste caso, mudei a cor do texto. Veja:

Imagem preparada para o efeito de rollover

Mesmo a imagem tendo o dobro da altura da anterior, apenas a parte superior vai aparecer, já que nosso DIV tem uma altura fixa, em pixels.

Para o rollover, vamos usar a pseudo-classe :hover do A, e aplicar a imagem acima como fundo deste elemento, porém em posições diferentes para cada um deles. Veja:


#um a:hover{
  background:url(img2.gif) no-repeat 0 -35px;
}
#dois a:hover{
  background:url(img2.gif) no-repeat -53px -35px;
}
#tres a:hover{
  background:url(img2.gif) no-repeat -114px -35px;
}

O primeiro valor é a posição da imagem na horizontal (left) e o segundo, na vertical (top). Percebam que o primeiro valor é sempre igual ao left do LI que contém o A. Veja o exemplo 5.

Um pouco mais de acessibilidade

Lembra do que falei, lá em cima, sobre nada ser exibido caso tenhamos CSS habilitado e imagens desabilitadas? Pois bem, há uma solução. Mas, claro, não é de graça. Vamos ter que adicionar alguma coisa ao nosso código HTML.


<div id="menu">
  <ul>
    <li id=”um”><a href=”#”><span></span>Início</a></li>
    <li id=”dois”><a href=”#”><span></span>Artigos</a></li>
    <li id=”tres”><a href=”#”><span></span>Contato</a></li>
  </ul>
</div>

Colocamos um SPAN vazio dentro de cada A. Alguns podem achar isso um pouco “sujo” e, na verdade, não deixa de ser. Porém, não perdemos nada de substancial com o uso destes elementos vazios, e vamos, no entanto, ganhar um pouco em termos de acessibilidade. Na minha opinião, vale a pena. Você decide se vale ou não para você.

Os referidos SPANs vão ser declarados como elementos de bloco e posicionados de maneira absoluta, de modo que fiquem “por cima” de seus pais (A). Vamos colocar uma imagem de fundo para cada SPAN (o mesmo valor usado nos :hovers, mas com posição vertical 0 ao invés de -35px). Veja:


#menu li a span{
  display:block;
  position:absolute;
  width:100%;
  height:100%;
  top:0;
  cursor:pointer;
}
#um a span{
  background:url(img2.gif) no-repeat 0 0;
}
#dois a span{
  background:url(img2.gif) no-repeat -53px 0;
}
#tres a span{
  background:url(img2.gif) no-repeat -114px 0;
}

Percebam que tive que usar cursor:pointer para que o cursor padrão de ponteiro (aquela “mãozinha” que aparece quando você passa o mouse sobre um link) apareça no Internet Explorer.

Vejam o exemplo 6.

Rollover de novo

Vamos adicionar o efeito de rollover a esse nosso novo código.


#um a:hover span{
  background:url(img2.gif) no-repeat 0 -35px;
}
#dois a:hover span{
  background:url(img2.gif) no-repeat -53px -35px;
}
#tres a:hover span{
  background:url(img2.gif) no-repeat -114px -35px;
}

Se você acompanhou bem até aqui, acho que não preciso explicar, né? Vejam o exemplo 7.

Consertando o rollover no IE

Os mais atentos com certeza notaram que ocorre um problema com o exemplo acima no Internet Explorer. Quando você passa o mouse sobre um link, ele muda de cor, mas não volta à cor original quando o cursor é movido para fora do elemento. Não me perguntem por que isso acontece, não faço a mínima idéia.

Passei alguns minutos tentando achar uma solução, e achei!

Por algum motivo, se colocarmos o z-index (que é o posicionamento no eixo Z, ou seja, serve para colocar um elemento “por cima” de outro) do a:hover para um valor alto (vou usar 1000, que é o valor máximo), tudo passa a funcionar perfeitamente no IE, e continua funcionando normalmente nos outros browsers.


#menu ul li a:hover{
  z-index:1000;
}

Simples assim. Porém, notem que o seletor desta regra deve ser mais específico que o do :hover. Vou falar sobre especificidade um dia desses. Por agora, tente adicionar apenas um ID a mais no seletor (no caso #menu) e especificar cada um dos elementos, na ordem (no caso ul li). Isso vai funcionar.

Confira o resultado final.

O código foi testado e aprovado nos seguintes browsers:

  • Firefox 1.5
  • Opera 9
  • Internet Explorer 6
  • Swift (um “safari para windows”, muito experimental ainda, portanto não posso garantir que o resultado seja o mesmo no safari do Mac OS X).

Se algum de vocês puder testar em outros browsers e me dizer se funciona, agradeço. ;)

***

Espero que este exemplo seja de alguma utilidade para vocês. Dúvidas, sugestões e reclamações são muito bem vindas.

Leia também:

20 Comentários sobre “Menu com imagens e rollover - Exemplo de HTML e CSS”

  1. Pedro Rogério disse:

    Bem legal o Tuto, muito boa as dicas!!!

  2. Jader Rubini disse:

    Muito bom…
    Mas porque diabos uma span vazia?
    Eu entendi o motivo de ela estar ali, mas não consegui entender o porquê de, mesmo estando ela vazia, o texto continuar aparecendo ao desabilitar as imagens…

  3. bruno disse:

    Jader, o span é usado apenas pra receber uma imagem de fundo.
    ele fica dentro do A, antes do texto. Quando voce coloca ele como position:absolute, display:block e da as dimensões corretas, automaticamente ele fica “por cima” desse texto.
    Quando você desabilita as imagens, o texto aparece porque ele estava simplesmente “por trás da imagem”, e não escondido de verdade.

  4. Tiago Celestino disse:

    Muito bom mesmo.

  5. Tatiana disse:

    Oi.. Gostaria de saber como posso fazer um menu dessa maneira se ele for na vertical? Adorei esse estilo na horizontal e queria fazer na vertical.

    Obrigado

  6. joshua disse:

    Muito bom mesmo… infelizmente o IE sempre dando dor de cabeça. Vamos esperar o IE7 para ver.

  7. alan fabiano zabot disse:

    olá …gostaria de saber como
    faço para inserir e configurar
    um formMail no meu site
    eu tentei colocar …mas não deu certo
    eu quero que os post’s vão direto
    para o meu e-mail sem que seja
    aberto o outlook

    vlw

  8. Erick disse:

    Como faço para usar somente texto, sem imagem. Ex.: Mouseover (texto normal) Mouse On (texto sublinhado)

  9. francielly lilaz disse:

    muito bom XD

  10. Luiz Claido disse:

    http://www.sonhoseencantos.com.br/publique

    Fiz sua rotina, mas o texto no mouse on, sobe, não fica alinhado no meio. Como fazer para alinha o texto no meio?!

    Grato.,

    Luiz Claudio

  11. André disse:

    Por acaso vc já utilizou essa técnica para fazer um menu com submenus???
    Caso sim, gostaria de um exemplo!

    Grato!!

  12. Kevin disse:

    Esses codigos são muito dificeis de fazer, só consegui fazer meu menu até o exemplo 2, e depois não deu mais certo, o que queria mesmo é que este site tivesse um gerador de menus para as pessoas fazerem os seus e depois só era copiar o cod. do menu já pronto!!!

    Estou muito chateado por não ter conseguido ter feito.
    Nunca mais vou entrar neste site!

  13. Túlio Vargas disse:

    Opá.. ótimo tutorial !!

    Congratulation..

    []´s

  14. Em busca da simplicidade « Mundo web disse:

    […] em particular a possibilidade de substituir imagens quando o mouse passasse por cima do gif dando o efeito rollover, que antes eu fazia através de um gerador automático de código javascript que se juntava ao HTML […]

  15. Marcos disse:

    Beleza Pessoal?
    No IE 7 está perfeito, porém no Firefox 2.0.0.6 não faz o efeito rollover nem habilita o link.
    Abs
    Marcos

  16. Image Replacement: use com sabedoria disse:

    […] uma delas com seus prós e contras. Eu já usei uma dessas técnicas por aqui em um artigo sobre menus com imagens e rollover (que, a propósito, precisa de algumas atualizações e […]

  17. Hot Pitty disse:

    #um{ width:53px; left:0; }
    #dois{ width:61px; left:53px; }
    #tres{ width:72px; left:114px; }

    ESTOU ME ATRAPALHANDO NESSA PARTE AÍ

    —- PORQUE EU QUERO COLOCAR OITO… TUDO BEM EU COLOKO .. MAS NÃO ENTENDI ESSES TAMANHOS AÍ NÃO..SAI TUDO ERRADO UM POR CIMA DO OUTRO… ALGUEM ME AJUDA POR FAVOR —–

  18. GLAUCIA P. MACIEL disse:

    Sou iniciante por aqui, por isso minha dúvida é trivial.
    Quais comandos utilizo para colocar uma imagem como plano de fundo com uma mensagem inserida.

    Obrigada.

    Gláucia P. MAciel

  19. Adriano disse:

    Excelente Tutorial, funcionou perfeitamente no I.E. 6 e Firefox 2.0, parabéns pela iniciativa, o span também foi muito útil, pois concertou a seleção indesejada do Firefox.
    O único fato que ficou em duvida, e de que o parte do span só funcionou no firefox, portanto, coloquei o primeiro código para o IE, e o do span para o firefox.
    Você tem algum comentário sobre isso?

    Parabéns e Até

    Adriano

  20. Raphael Nikson disse:

    Bruno, pra vc não é problema o fato de usar o e não validar o código?

    Não acharia melhor usar

    Texto

    Colocaria no css display block para o A e aplicaria a como background nele.

    Daí esconderia o span com display none.

    O código ficaria validado.

Leave a Reply