Alinhamento Vertical de Divs com JavaScript e JQuery

Passei um sufoco esses dias tentando alinhar um div dentro do outro apenas com CSS, o qual aliás não consegui nada satisfatório, mesmo achando algumas técnicas interessantes que não chegaram a funcionar comigo. Então parti para o JavaScript, para me ajudar. 🙂

Como neste projeto que eu precisava alinhar os divs, eu já estava usando a biblioteca JQuery (que por sinal tem um slogan legal – “Write less, do more” ou seja, escreva menos e faça mais), fiz o alinhamento usando ela mesmo.

Aqui está a explicação do problema:

Alinhamento Vertical

Onde eu tenho uma div maior, com altura definida. Um div (que tive que adicionar para poder alinhar) com altura variada por conter o texto e uma imagem os quais não tenho controle das suas respectivas alturas.

O primeiro detalhe que temos que fazer é adaptar o código (x)html para ser alinhado. Como disse tive que adicionar um div (o da altura variada), pois sem ele nada feito.

  1. <div class="alinhar">
  2. <div><img src="http://www.tuliofaria.net/imagem.jpg" />
  3. texto</div>
  4. </div>

Obs.: não pode haver nenhum espaço ou texto entre os dois divs, porque senão haverá um textNode entre eles e a técnica não funcionará. Tenho que arrumar um workaround para isso e para a preguiça. 🙂

[UPDATED 10/07/2007]

Agora vem a parte divertida, JavaScript, para conferir o código entre aqui e veja o Código Fonte de Exemplo.

Obs.: me desculpem por não ter percebido esse erro. Realmente o editor do blog cortou uma parte do fonte JS.

[/UPDATED 10/07/2007]

O que esse código faz, resumidamente, é pegar a altura dos dois divs, subtrair e dividir esse resultado por dois. Para saber o valor do padding-top que temos que definir no div de altura fixa. Que é o mesmo valor que tiraremos de sua altura.

Por que usei setTimeOut? Porque estava dando alguns problemas de não reconhecer a altura dos divs logo após o carregamento da página, assim depois de 1000ms possivelmente já terá renderizado corretamente.

Para baixarem a JQuery: www.jquery.com

Bom pessoal, até a próxima. Qualquer dúvida, comentem 🙂

34 Comment

  1. Fala Túlio. Gostaria que falasse mais sobre JQuery, escrevendo meio que um “tutorial de introdução”. Utilizo hoje o toolkit DOJO, porque me permite criar classes e heranças e importar outras bilbiotecas de uma maneira semelhante a que que programo em JAVA. Entretanto, estou tendo problemas com o tempo de carga, o browser “engasga” e não responde até todos os arquivos estarem carregados. Em fim, gosto muito do DOJO mas isso está me criando problemas.

    Estou em dúvida pra que lado vou correr, estou tendencioso para Mochikit. Como JQuery se compara a Dojo, Mochikit e Prototype? Pq escolheu este toolkit?

  2. Blz Gustavo,

    comecei a trabalhar com o JQuery como uma alternativa ao Prototype. Alguns dos fatores que me motivaram a começar a usá-la foram o seu tamanho (menor que o prototype) e o esquema de expressões que ela possui, assim conseguimos buscar um elemento na página usando atributos (e outros parâmetros), não apenas baseado no seu nome, id ou classe. E também por ela possuir “Efeitos”, como os do scriptaculus nativamente. Além de várias outras vantagens.

    Em um projeto grande que estou desenvolvendo atualmente, como não tenho muito problema com o tamanho do site (pelos usuários que irão fazer uso do sistema), estou usando tanto a Prototype quanto a JQuery, pois já haviam implementações usando o Prototype.

    Pretendo escrever algo sobre ela sim, e atualmente recomendo o uso, pois ela justifica o lema: “Write less, do more” (escreva menos, faça mais).

    Espero ter te ajudado na escolha 🙂

    Abraços,

  3. Eu to usando o Jquery em um projeto e está sendo muito util , principalmente o plugin de AjaxForm, depois da uma olhada. Vale a pena!

  4. Realmente 19Kb para o JQuery é muito interessante!

    Dojo é bastante poderoso quanto a buscar elementos por classes e atributos, mas no que diz respeito a velocidade, perde muito.

    Dojo tem um problema de “congelar” o navegador, que é quase uma marca registrada da biblioteca. Isso me irrita muito. O pior, só fui perceber isso depois de programar várias linhas e colocar minha aplicação para rodar na Web.

    Nos testes locais este problema não aparecia! Depois fui buscar informação sobre porque isso acontece, parece que é uma necessidade de sincronia entre o HTML/CSS/JS antes que tudo comece a rodar. Uma bosta. Tem maneiras de diminuir este “congelamento”, mas ele vai sempre existir.

    O problema que tenho agora é que o Dojo me permitiu modelar o sistema como classes, utilizando herança, construtores, etc. A biblioteca que preciso escolher deve me permetir trabalhar desta maneira também, ou vou ter trabalho dobrado em adaptar o código.

    JQuery parece uma forte promessa, tudo muito bem documentado, fácil de aprender. Só preciso ver se posso dar esta abordagem de classes. E ainda estou vendo o MochiKit pq tenta espelhar Python para JS e eu curto muito Python.

    Veremos, comunico aqui ao site qdo tomar uma decissão.

    Abraços

  5. O post já tá aí desde janeiro, mas só agora encontrei teu blog, pois buscava informações sobre o Cake.
    Maneiro o pessoal estar se interessando por jQuery, já sou discípulo desde o release 0.2 do jQuery e desde meados de 2006 venho tentando evangelizar a linguagem por aqui hehe.
    Só que como meu blog nunca sai do 0. Sorte tem tu está ai fazendo este ótimo trabalho de video aulas (pelo menos no Cake) e eu tinha pensado em fazer isso para jQuery e agora vou fazer mesmo.

  6. Ah, no seu post, pode ser transformado em ‘alinhando divs com jQuery’ somente, indico a todos a buscarem o plugin dimension que te permite pegar a posição/tamanho de qq elemento na tela. De uma forma ridiculamente simples. Jquery-style.

  7. Perdão, mas tem algum erro com os laços for() da sua função?

    Se “copiar e colar” e usar no $( document ).ready( function() da jQuery, o Firebug do Firefox acusa erro.

    Preciso demasiadamente dessa “correção”, mas com os erros de nada adianta. Acredito que seja pelo fato de a função estar quebrada em várias linhas, não sei.

    Poderia ajudar?

    Obrigado

  8. Amigo(a) jQuery Brasil, se sua intenção foi ajudar minha dúvida, aredite, não ajudou não, pois o link que você passou remete a esta mesma página.

    Grato

  9. Olá amigo,

    acho que você não entendeu… Esse comentário quer dizer que este post foi linkado ao site jQuery Brasil…

    sobre a sua pergunta, eu não entendi direito onde está o problema, já que este script foi testado…

    passe mais detalhes para que eu possa lhe ajudar…
    t+

  10. Também tive o mesmo problema, veja o debug do firefox:

    Erro: missing ; after for-loop condition
    Arquivo-fonte: file:///C:/Documents%20and%20Settings/danilo/Desktop/align.html
    Linha: 28, Coluna: 6
    Código-fonte:
    divs = $(ids[x]);

    segue o codigo do arquivo

    texto

    var vTime;
    function centraliza(){
    var ids = new Array();
    ids.push(“div.alinhar”);
    for(x=0;x
    divs = $(ids[x]);
    for(i=0; i
    h = divs[i].offsetHeight;
    hp = divs[i].childNodes[0].offsetHeight;
    padd = parseInt((h-hp)/2);
    nh = h-padd;
    $(divs[i]).css( { height: nh+”px” } );
    $(divs[i]).css( { paddingTop: padd+”px” });
    }
    }
    }
    $(document).ready(function(){
    vTime = setTimeout(“centraliza()”, 1000);
    });

  11. bem filtrou as tags… 🙁

  12. Amigo, olhei direito, há alguns erro no seu post, tente copiar e colar do seu site, n funciona. OK?

  13. Pode ser por causa dessa filtragem de tags que o sript não funcionou.

    Teria como você passar o script em um arquivo de texto puro ou sem passar pelo editor do blog?

    Obrigado

  14. Bruno e Danilo Freitas,

    realmente estava errado no post. Sinceras desculpas. E obrigado pelo alerta.

    Agora está corrigido.

    Até mais,

  15. Bom, não atualizei no servidor para adicionar o código. Mas ocalmente a mesma estrutura do servidor não consegui fazer funcionar.

    http://www.imaggens.net/admin.php?act=settings&section=system

    Esse é o link. O código é o mesmo.

    Porém não sei como fazer para adicionar corretamente em ids.push() as DIV’s

    Pode me ajudar?

  16. Olá Bruno,

    então você usaria um ids.push para cada div ou elemento em bloco que deseje centralizar.

    No caso do exemplo está ids.push(“div.alinhar”), ou seja, ele vai pegar todas as divs com classe alinhar e aplicar a centralização.

    Este “div.alinhar” segue o padrão de expressões do jQuery, ou seja, pode-se usar qualquer expressão válida (em jQuery).

    Você pode conferir mais sobre isso em: http://docs.jquery.com/Selectors

    Até mais….

  17. Deu não Túlio.

    Eu remontei o layout com ajuda de um amigo e agora ficou até que mais simples, embora tenha uns probleminhas de fluidez entre resoluções. Mas não vem ao caso.

    E aparentemente, o seletor que deveria usar é li.right, mas não acontece nada.

    O link do site é o mesmo ainda

    []’s

  18. Olá Bruno,

    então é porque você não tem um li tipo:

    1. <li class="right">Centraliza</li>

    Att,

  19. Ops, falh nosaa. A página que tem o li.riht é qualquer uma de dentro de uma das castegorias do link que eu passei, onde ficam as configurações detalhadas.

    []’s

  20. Em algum lugar dos comentarios acima, vc comenta, que o browser se enrola para baixar o codigo .JS, isso nao acontece com o JQUERY, o que ele faz pra ser mais rapido, vc manda por exemplo, um formulario INDEX.HTML, com 5 scripts relacionados, eu sei que enquanto nao carregar todas as .JS, o INDEX.HTML, nao vai aparecer, isso fica mais rapido com o JQUERY?
    []s … Sucesso

  21. Olá Ferdinando,

    não entendi muito a sua questão…

    Inté +

  22. Hello! Good Site! Thanks you! zaibzkrjxye

  23. É realmente é interessante, mas não concordo com a idéia de utilizar-se do Jquery, muito menos o prototype, eles são pessados, lentos e cheios de bugs, além de limitarem completamente o programador, concordo com a pratica sadia de ver o que eles fazem e fazer melhor no seu código, não só de usá-los sem saber o que esta fazendo.
    Claro que visto o ganho de tempo pode ser considerado uma vantagem, porém vejo como coisa de quem tem preguiça de pensar pra fazer algo tão simples.

    Veja o código:

    if(window.addEventListener)
    {
    window.addEventListener(“load”, function() { centraliza(); }, false);
    } else
    if(window.attachEvent)
    {
    window.attachEvent(“onload”, function() { centraliza(); });
    }
    function centraliza(){
    tam=document.documentElement.clientHeight;
    divisao=document.getElementById(‘teste’).style.height;
    tamstr=(divisao.length)-2;
    divisao=divisao.substr(0,tamstr);
    margem=(tam-divisao)/2;
    document.getElementById(‘teste’).style.marginTop=margem+”px”;
    setTimeout(“centraliza()”, 10);
    }

  24. O HTML

  25. <div id=”teste” style=”width:910px; height:400px; margin:auto; background:#000066;”>
    </div>

  26. João,

    é claro que se fosse para usar somente para o alinhamento poderia ser muito código (eu não acho muito não).

    Imagine em um script maior que você usasse:

    document.getElementById

    muitas vezes, você estaria escrevendo muito código a toa. Não concorda?

    Sem contar na perda de produtividade, re-uso de código e por aí vai….

    Bom essa é minha opinião….

    Abraços,

  27. Funcionou perfeitamente no IE 7 e 6 soh naum deu certo no FIREFOX… alguma sugestao??

  28. Joaz, eu tive esse problema no FIREFOX também,
    Depois descobri que a imagem não pode ter espaço entre o . Por ex,

    é necessario estar assim:

    Caso contrário teremos um problema no Firefox,
    Grande abraço.

  29. Perfeito! Acho que eu nunca iria desconfiar disso!

    muito obrigado =)

  30. Muito boa a iniciativa. Eu criei um plugin para alinhar os elementos verticalmente e horizontalmente. Para quem quiser aí tá o link no site do jQuery:
    http://plugins.jquery.com/project/elementcenter

    E a documentação em português:
    http://www.alexandremagno.net/blog/2008/03/23/jquery-center-plugin/#comments

    Espero que ajude…. parabéns pelo artigo.

  31. Estou implementando um site e tenho que centralizar o mesmo na horizontal e vertical. Horizontalmente ele já esta, só falta verticalmente. A bronca é que não dá para dar uma altura para div all. Tem alguma outra forma de centralizar?

  32. Já estava quase perdendo a cabeça até ver seu artigo. Muito bom e salvou-me de uma bela enrrascada. Parabéns pelo artigo.

  33. eu fiz assim e deu certo para mim

    * {
    margin:0px;
    padding:0px;
    }

    #imagem {
    width:450px;
    height:340px;
    border:1px solid green;

    }
    img {
    }
    html,body {
    width:800px;
    height:600px;
    margin:0px auto;
    }
    p {
    text-align:center;
    }

    $(document).ready(function() {
    var area=340;
    var dimensao=parseInt($(‘img’).height());
    console.log(dimensao);
    if(area > dimensao) {
    var novarea=area – dimensao;
    var margin=novarea/2;
    var novocss = {
    ‘margin-top’:margin+’px’
    }
    $(‘img’).css(novocss);
    }
    });

Deixe uma resposta