Centralizando um bloco div sem a largura

240

Tenho um problema quando tento centralizar o bloco div "produtos" porque não conheço antecipadamente a largura do div. Alguém tem uma solução?

Atualização: O problema que tenho é que não sei quantos produtos exibirei, posso ter 1, 2 ou 3 produtos, posso centralizá-los se fosse um número fixo, pois saberia a largura do pai div, eu simplesmente não sei como fazê-lo quando o conteúdo é dinâmico.

.product_container {
  text-align: center;
  height: 150px;
}

.products {
  height: 140px;
  text-align: center;
  margin: 0 auto;
  clear: ccc both; 
}
.price {
  margin: 6px 2px;
  width: 137px;
  color: #666;
  font-size: 14pt;
  font-style: normal;
  border: 1px solid #CCC;
  background-color:	#EFEFEF;
}
<div class="product_container">
  <div class="products" id="products">
    <div id="product_15">
      <img src="/images/ecommerce/card_default.png">
      <div class="price">R$ 0,01</div>
    </div>

    <div id="product_15">
      <img src="/images/ecommerce/card_default.png">
      <div class="price">R$ 0,01</div>
    </div>   

    <div id="product_15">
      <img src="/images/ecommerce/card_default.png">
      <div class="price">R$ 0,01</div>
    </div>
  </div>
</div>

Nhan
fonte
Qual é exatamente o problema que você está tendo?
Anand.trex 12/11/2008

Respostas:

254

Atualização 27 de fevereiro de 2015: Minha resposta original continua sendo votada, mas agora eu normalmente uso a abordagem de @ bobince.

.child { /* This is the item to center... */
  display: inline-block;
}
.parent { /* ...and this is its parent container. */
  text-align: center;
}

Minha postagem original para fins históricos:

Você pode tentar esta abordagem.

<div class="product_container">
    <div class="outer-center">
        <div class="product inner-center">
        </div>
    </div>
    <div class="clear"/>
</div>

Aqui está o estilo correspondente:

.outer-center {
    float: right;
    right: 50%;
    position: relative;
}
.inner-center {
    float: right;
    right: -50%;
    position: relative;
}
.clear {
    clear: both;
}

JSFiddle

A idéia aqui é que você contenha o conteúdo que deseja centralizar em duas divs, uma externa e outra interna. Você flutua as duas divs para que suas larguras diminuam automaticamente para se ajustarem ao seu conteúdo. Em seguida, posicione relativamente a div externa com sua borda direita no centro do contêiner. Por fim, você posiciona relativamente a div interna na direção oposta pela metade de sua própria largura (na verdade, a largura da div externa, mas elas são iguais). Em última análise, isso centraliza o conteúdo em qualquer container em que ele esteja.

Você pode precisar dessa div vazia no final se depender do conteúdo do "produto" para dimensionar a altura do "content_container".

Mike M. Lin
fonte
1
Se você não fornecer overflow:hiddenpara .product_containero outer-centerdiv se sobrepõem outros conteúdos próximas para a direita dele. Quaisquer links ou botões à direita outer-centernão funcionarão. Experimente a cor de fundo para outer-centerentender a necessidade overflow :hidden. Esta foi uma edição sugerida por Cicil Thomas
Benjol
Essa abordagem é perfeita para sites de desktop ... em dispositivos móveis, as divs internas parecem anexar à direita. Há uma solução?
precisa
3
Conte-me sobre isso! Às vezes, simplesmente precisamos de uma solução e não temos o luxo de ter uma boa para escolher. Uma tabela de célula única é outra opção, embora uma tabela com uma célula não seja realmente uma tabela, é?
Mike M. Lin
@fgysin Concordado, é um truque contra-intuitivo. E os designers se perguntam por que as pessoas ainda consideram voltar aos layouts baseados em tabelas.
Yuck
1
Esta pergunta tem cinco anos. Esta resposta está desatualizada, mas nunca foi muito elegante para começar. O que você deve fazer é usar display: bloco em linha
Wray Bowling
140

Um elemento com 'display: block' (como div é por padrão) tem uma largura determinada pela largura do seu contêiner. Você não pode tornar a largura de um bloco dependente da largura de seu conteúdo (encolher para ajustar).

(Exceto pelos blocos que são 'float: left / right' no CSS 2.1, mas isso não serve para centralizar.)

Você pode definir a propriedade 'display' como 'inline-block' para transformar um bloco em um objeto que se ajusta ao tamanho que pode ser controlado pela propriedade de alinhamento de texto do pai, mas o suporte ao navegador é irregular. Você pode se safar usando hacks (por exemplo, consulte -moz-inline-stack) se quiser seguir esse caminho.

O outro caminho a percorrer são as mesas. Isso pode ser necessário quando você tem colunas cuja largura realmente não pode ser conhecida antecipadamente. Eu realmente não sei dizer o que você está tentando fazer com o código de exemplo - não há nada óbvio lá que precisaria de um bloco de ajuste a encaixe - mas uma lista de produtos pode ser considerada tabular.

[PS. nunca use 'pt' para tamanhos de fonte na web. 'px' é mais confiável se você realmente precisar de texto de tamanho fixo; caso contrário, unidades relativas como '%' serão melhores. E "claro: ccc both" - um erro de digitação?]

.center{
   text-align:center; 
}

.center > div{ /* N.B. child combinators don't work in IE6 or less */
   display:inline-block;
}

JSFiddle

bobince
fonte
53
pai -> alinhamento de texto: centro | child-> display: inline-block
mdskinner
5
display: inline-blocknão é suportado no IE7 e versões mais antigas do Firefox
Jake Wilson
1
@Jakobud, para o IE7, use "display: inline; zoom: 1;" em vez de "display: inline-block;". Funciona para elementos de bloco.
Mihail-haritonov #
1
confira este link para obter mais informações sobre como usar esse método em vários navegadores - blog.mozilla.org/webdev/2009/02/20/cross-browser-inline-block
keyoke
1
Eu usei esse scss para implementá-lo, que funcionará enquanto sua estrutura html existir para suportá-lo: .center {text-align: center; &: primeiro filho {display: bloco embutido; }}
Dovev Hefetz 15/10
95

A maioria dos navegadores suporta a display: table;regra CSS. Esse é um bom truque para centralizar uma div em um contêiner sem adicionar HTML extra nem aplicar estilos de restrição ao contêiner (como o text-align: center;que centralizaria todo o outro conteúdo embutido no contêiner), mantendo a largura dinâmica da div contida:

HTML:

<div class="container">
  <div class="centered">This content is centered</div>
</div>

CSS:

.centered { display: table; margin: 0 auto; }


Atualização (09-03-2015):

A maneira correta de fazer isso hoje é realmente usar as regras do flexbox. O suporte ao navegador é um pouco mais restrito ( suporte à tabela CSS vs suporte flexbox ), mas esse método também permite muitas outras coisas e é uma regra CSS dedicada para esse tipo de comportamento:

HTML:

<div class="container">
  <div class="centered">This content is centered</div>
</div>

CSS:

.container {
  display: flex;
  flex-direction: column; /* put this if you want to stack elements vertically */
}
.centered { margin: 0 auto; }

Maxime Rossini
fonte
11
Eu acho que essa é definitivamente a melhor solução. Não envolve hacks estranhos com divs aninhados flutuantes, ou qualquer coisa assim. Eu acho que a única razão pela qual não foi classificada como alta é porque as pessoas foram longe demais nas mesas. Como não é uma tabela, acho que é um método perfeitamente legítimo.
Dan Jones
1
Concordado, esta parece ser a melhor solução. Embora a solução do @ bobince também seja simples, ela tem o efeito colateral de alterar estilos no elemento interno.
jorgeh
A display: table;variante é ideal para pseudoelementos ( ::before, ::after) nos quais você não pode adicionar marcação extra e deseja evitar interrupções nos estilos de elementos adjacentes.
Walf 13/03
20

seis maneiras de esfolar esse gato:

Botão um: qualquer coisa do tipo display: blockassumirá a largura total dos pais. (a menos que combinado com floatum dos display: flexpais). Verdade. Mau exemplo.

Botão 2: a busca display: inline-blocklevará à largura automática (em vez de cheia). Você pode centralizar usando text-align: center o bloco de embalagem . Provavelmente o mais fácil e o mais amplamente compatível, mesmo com navegadores 'antigos' ...

.wrapTwo
  text-align: center;
.two
  display: inline-block; // instantly shrinks width

Botão 3: Não é necessário colocar nada no envoltório. Talvez essa seja a solução mais elegante. Também funciona verticalmente. (O suporte do navegador para transtlate é bom o suficiente (≥IE9) atualmente ...).

position: relative;
display: inline-block; // instantly shrinks width
left: 50%;
transform: translateX(-50%);

Btw: Também é uma ótima maneira de centralizar verticalmente blocos de altura desconhecida (em conexão com o posicionamento absoluto).

Botão 4: posicionamento absoluto. Apenas certifique-se de reservar altura suficiente no wrapper, pois ninguém mais o fará (nem clearfix nem implícito ...)

.four
  position absolute
  top 0
  left 50%
  transform translateX(-50%)
.wrapFour
  position relative // otherwise, absolute positioning will be relative to page!
  height 50px // ensure height
  background lightgreen // just a marker

Botão 5: flutuar (que também traz elementos em nível de bloco para a largura dinâmica) e uma mudança relativa. Embora eu nunca tenha visto isso na natureza. Talvez haja desvantagens ...

.wrapFive
  &:after // aka 'clearfix'
    content ''
    display table
    clear both

.five  
  float left
  position relative
  left 50%
  transform translateX(-50%)

Atualização: Botão 6: E hoje em dia, você também pode usar a caixa flexível. Observe que esses estilos se aplicam ao wrapper do objeto centralizado.

.wrapSix
  display: flex
  justify-content: center

→ código fonte completo (sintaxe da caneta)

Frank Nocke
fonte
17

Encontrei uma solução mais elegante, combinando "bloco em linha" para evitar o uso de float e o hacky clear: ambos. Ele ainda requer divs tho aninhados, o que não é muito semântico, mas simplesmente funciona ...

div.outer{
    display:inline-block;
    position:relative;
    left:50%;
}

div.inner{
    position:relative;
    left:-50%;
}

Espero que ajude!

JavierIEH
fonte
4
<div class="outer">
   <div class="target">
      <div class="filler">
      </div>
   </div>
</div>

.outer{
   width:100%;
   height: 100px;
}

.target{
   position: absolute;
   width: auto;
   height: 100px;
   left: 50%;
   transform: translateX(-50%);
}

.filler{
   position:relative;
   width:150px;
   height:20px;
}

Se o elemento de destino estiver absolutamente posicionado, você poderá centralizá-lo movendo-o 50% em uma direção ( left: 50%) e depois transformá-lo 50% na direção oposta ( transform:translateX(-50%)). Isso funciona sem definir a largura do elemento de destino (ou com width:auto). A posição do elemento pai pode ser estática, absoluta, relativa ou fixa.

West1
fonte
1
Isso ficará fora do centro pela metade da largura da coisa que você está centralizando.
4imble
@ 4imble Não, não vai. A propriedade "left" move 50% (50% da largura do pai) e translateX (-50%) move 50% para o outro lado (50% da largura do elemento de destino).
West1
Ahh sim, eu perdi o translateX. Não tenho certeza se isso é confiável em qualquer IE anterior ao IE 11. Mas você está certo.
4imble
3

Por padrão, os divelementos são exibidos como elementos de bloco e, portanto, têm 100% de largura, tornando-os sem sentido. Conforme sugerido por Arief, você deve especificar ae widthpoderá usá-lo autoao especificar marginpara centralizar a div.

Como alternativa, você também pode forçar display: inline, mas terá algo que se comporta como um em spanvez de um div, para que não faça muito sentido.

Adam Bellaire
fonte
3

Isso centralizará um elemento, como uma Lista ordenada, ou Lista não ordenada, ou qualquer elemento. Apenas envolva-o com um Div com a classe de outerElement e dê ao elemento interno a classe de innerElement.

A classe outerelement é responsável pelo IE, Mozilla antigo e navegadores mais recentes.

 .outerElement {
        display: -moz-inline-stack;
        display: inline-block;
        vertical-align: middle;
        zoom: 1;
        position: relative;
        left: 50%;
    }

.innerElement {
    position: relative;
    left: -50%;
} 
Greg Benner
fonte
Adicione uma descrição ao seu código. A publicação de código por si só não significa muito para os futuros visitantes do SO.
21412 Ren Ren
3

use css3 flexbox com justify-content: center;

    <div class="row">
         <div class="col" style="background:red;">content1</div>
          <div class="col" style="">content2</div>
    </div>


.row {
    display: flex; /* equal height of the children */
    height:100px;
    border:1px solid red;
    width: 400px;
    justify-content:center;
}
zloctb
fonte
1

Ligeira variação na resposta de Mike M. Lin

Se você adicionar overflow: auto;(ou hidden) a div.product_container, não precisará div.clear.

Isso é derivado deste artigo -> http://www.quirksmode.org/css/clearing.html

Aqui está o HTML modificado:

<div class="product_container">
    <div class="outer-center">
        <div class="product inner-center">
        </div>
    </div>
</div>

E aqui é CSS modificado:

.product_container {
  overflow: auto;
  /* width property only required if you want to support IE6 */
  width: 100%;
}

.outer-center {
  float: right;
  right: 50%;
  position: relative;
}

.inner-center {
  float: right;
  right: -50%;
  position: relative;
}

A razão, porque é melhor sem div.clear (além de parecer errado ter um elemento vazio) é a atribuição de margem excessivamente zelosa do Firefox.

Se, por exemplo, você tiver este html:

<div class="product_container">
    <div class="outer-center">
        <div class="product inner-center">
        </div>
    </div>
    <div style="clear: both;"></div>
</div>
<p style="margin-top: 11px;">Some text</p>

então, no Firefox (8.0 no momento da redação), você verá uma 11pxmargem antes product_container . O pior é que você terá uma barra de rolagem vertical para toda a página, mesmo que o conteúdo se encaixe perfeitamente nas dimensões da tela.

Alexander Pogrebnyak
fonte
1

Experimente este novo css e marcação

Aqui está o HTML modificado:

<div class="product_container">
<div class="products" id="products">
   <div id="product_15" class="products_box">
       <img src="/images/ecommerce/card_default.png">
       <div class="price">R$ 0,01</div>
   </div>
   <div id="product_15" class="products_box">
       <img src="/images/ecommerce/card_default.png">
       <div class="price">R$ 0,01</div>
   </div>   
   <div id="product_15" class="products_box">
       <img src="/images/ecommerce/card_default.png">
       <div class="price">R$ 0,01</div>
   </div>
</div>

E aqui é CSS modificado:

<pre>
.product_container 
 {
 text-align:    center;
 height:        150px;
 }

.products {
    left: 50%;
height:35px;
float:left;
position: relative;
margin: 0 auto;
width:auto;
}
.products .products_box
{
width:auto;
height:auto;
float:left;
  right: 50%;
  position: relative;
}
.price {
    margin:        6px 2px;
    width:         137px;
    color:         #666;
    font-size:     14pt;
    font-style:    normal;
    border:        1px solid #CCC;
    background-color:   #EFEFEF;
}

Shinov T
fonte
1
<div class="product_container">
<div class="outer-center">
<div class="product inner-center">
    </div>
</div>
<div class="clear"></div>
</div>

.outer-center
{
float: right;
right: 50%;
position: relative;
}
.inner-center 
{
float: right;
right: -50%;
position: relative;
}
.clear 
{
clear: both;
}

.product_container
{
overflow:hidden;
}

Se você não fornecer "overflow: hidden" para ".product_container", a div "outer-center" se sobreporá a outros conteúdos próximos à direita. Quaisquer links ou botões à direita do "centro externo" não funcionarão. Experimente a cor de plano de fundo em "centro externo" para entender a necessidade de "estouro: oculto"

Cicil Thomas
fonte
1

Encontrei uma solução interessante, eu estava fazendo slider e tive que centralizar os controles de slide, fiz isso e funciona bem. Você também pode adicionar uma posição relativa ao pai e mover a posição filho na vertical. Dê uma olhada http://jsfiddle.net/bergb/6DvJz/

CSS:

#parent{
        width:600px;
        height:400px;
        background:#ffcc00;
        text-align:center;
    }

#child{
        display:inline-block;
        margin:0 auto;
        background:#fff;
    }  

HTML:

<div id="parent">
    <div id="child">voila</div>
</div>
Nikola
fonte
1

Faça display:table;e defina margincomoauto

Importante parte do código:

.relatedProducts {
    display: table;
    margin-left: auto;
    margin-right: auto;
}

Não importa quantos elementos você tenha agora, ele se alinhará automaticamente no centro

Exemplo no trecho de código:

hahaha
fonte
0

Receio que a única maneira de fazer isso sem especificar explicitamente a largura seja usar tabelas (gasp).

Kon
fonte
5
reformulado: se você não quiser passar a próxima hora tentando todo tipo de combinação de CSS, DIVs e navegadores aninhados, vá diretamente para as tabelas.
23119 Eduardo Molteni
As tabelas não foram projetadas para serem usadas como elementos de design. Esse é um estilo ruim.
precisa saber é o seguinte
0

Correção ruim, mas funciona ...

CSS:

#mainContent {
    position:absolute;
    width:600px;
    background:#FFFF99;
}

#sidebar {
    float:left;
    margin-left:610px;
    max-width:300;
    background:#FFCCCC;
}
#sidebar{


    text-align:center;
}

HTML:

<center>
<table border="0" cellspacing="0">
  <tr>
    <td>
<div id="mainContent">
1<br/>
<br/>
123<br/>
123<br/>
123<br/>
</div><div id="sidebar"><br/>
</div></td>
</tr>
</table>
</center>
Lionel
fonte
0

Correção simples que funciona em navegadores antigos (mas usa tabelas e requer uma altura a ser definida):

<div style="width:100%;height:40px;position:absolute;top:50%;margin-top:-20px;">
  <table style="width:100%"><tr><td align="center">
    In the middle
  </td></tr></table>
</div>
Craigo
fonte
0
<style type="text/css">
.container_box{
    text-align:center
}
.content{
    padding:10px;
    background:#ff0000;
    color:#ffffff;

}

use span istead das divs internas

<div class="container_box">
   <span class="content">Hello</span>
</div>
alguém
fonte
0

Eu sei que essa pergunta é antiga, mas estou tentando entender. Muito semelhante à resposta de bobince, mas com um exemplo de código funcional.

Faça de cada produto um bloco embutido. Centralize o conteúdo do recipiente. Feito.

http://jsfiddle.net/rgbk/6Z2Re/

<style>
.products{
    text-align:center;
}

.product{
    display:inline-block;
    text-align:left;

    background-image: url('http://www.color.co.uk/wp-content/uploads/2013/11/New_Product.jpg');
    background-size:25px;
    padding-left:25px;
    background-position:0 50%;
    background-repeat:no-repeat;
}

.price {
    margin:        6px 2px;
    width:         137px;
    color:         #666;
    font-size:     14pt;
    font-style:    normal;
    border:        1px solid #CCC;
    background-color:   #EFEFEF;
}
</style>


<div class="products">
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
    <div class="product">
        <div class="price">R$ 0,01</div>
    </div>
</div>

Veja também: Centralize blocos embutidos com largura dinâmica em CSS

Wray Bowling
fonte
Essa resposta já não fornece a mesma solução? stackoverflow.com/a/284064/547733
Maxime Rossini
1
você está certo, madmox! Não é tão robusto. Também estou percebendo que definir alinhamento de texto para esquerda ou direita significa que isso nunca funcionará em um site com traduções que incluem a mudança da ordem de leitura da esquerda para a direita para a direita para a esquerda. alinhamento de texto é para alinhar texto, não elementos. Idealmente, em um futuro próximo, dependeremos da exibição: flexione-se para esse tipo de coisa.
Wray Bowling
0

Essa é uma maneira de centralizar qualquer coisa dentro de uma div que não conheça a largura interna dos elementos.

#product_15{
    position: relative;
    margin: 0 auto;
    display: table;
}
.price, img{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
Shirley Ashby
fonte
-1

minha solução foi:

.parent {
    display: flex;
    flex-wrap: wrap;
}

.product {
    width: 240px;
    margin-left: auto;
    height: 127px;
    margin-right: auto;
}
Byron
fonte
-7

adicione este css à sua classe product_container

    margin: 0px auto;
    padding: 0px;
    border:0;
    width: 700px;
Arief
fonte
A questão diz especificamente "sem largura"
Dez Udezue