Centrar un bloque div sin el ancho

241

Tengo un problema cuando intento centrar los "productos" del bloque div porque no conozco de antemano el ancho del div. ¿Alguien tiene una solución?

Actualización: el problema que tengo es que no sé cuántos productos mostraré, puedo tener 1, 2 o 3 productos, puedo centrarlos si fuera un número fijo ya que sabría el ancho del padre div, simplemente no sé cómo hacerlo cuando el contenido es 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
fuente
¿Cuál es exactamente el problema que tienes?
anand.trex

Respuestas:

256

Actualización 27 de febrero de 2015: mi respuesta original sigue siendo votada, pero ahora normalmente uso el enfoque de @bobince.

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

Mi publicación original para fines históricos:

Es posible que desee probar este enfoque.

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

Aquí está el estilo a juego:

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

JSFiddle

La idea aquí es que contiene el contenido que desea centrar en dos divs, uno externo y uno interno. Flota ambos divs para que sus anchos se reduzcan automáticamente para adaptarse a su contenido. Luego, colocas relativamente el div externo con su borde derecho en el centro del contenedor. Por último, colocas relativamente el div interno en la dirección opuesta por la mitad de su propio ancho (en realidad, el ancho del div externo, pero son iguales). En última instancia, eso centra el contenido en cualquier contenedor en el que se encuentre.

Es posible que necesite ese div vacío al final si depende del contenido de su "producto" para dimensionar la altura del "contenedor_producto".

Mike M. Lin
fuente
1
Si no te dan overflow:hiddenpara .product_containerel outer-centerdiv se solapará otros contenidos cercanos a la derecha de la misma. Cualquier enlace o botón a la derecha outer-centerno funcionará. Pruebe el color de fondo para outer-centercomprender la necesidad overflow :hidden. Esta fue una edición sugerida por Cicil Thomas
Benjol
Sin embargo, este enfoque es perfecto para sitios web de escritorio ... en dispositivos móviles, los divs internos parecen adjuntarse a la derecha. ¿Hay alguna solución?
Mich Dart
3
¡Cuéntame sobre eso! A veces simplemente necesitamos una solución y no tenemos el lujo de tener una buena opción para elegir. Una tabla de celda única es otra opción, aunque una tabla con una celda no es realmente una tabla, ¿verdad?
Mike M. Lin
@fgysin De acuerdo, es un truco contra intuitivo. Y los diseñadores se preguntan por qué la gente sigue considerando recurrir a diseños basados ​​en tablas.
Yuck
1
Esta pregunta tiene cinco años. Esta respuesta está desactualizada pero nunca fue muy elegante para empezar. Lo que debe hacer es usar display: bloque en línea
Wray Bowling
140

Un elemento con 'display: block' (como div es por defecto) tiene un ancho determinado por el ancho de su contenedor. No puede hacer que el ancho de un bloque dependa del ancho de su contenido (reducir para ajustar).

(Excepto para los bloques que son 'flotante: izquierda / derecha' en CSS 2.1, pero eso no sirve para centrar).

Puede establecer la propiedad 'display' en 'inline-block' para convertir un bloque en un objeto que se ajuste para que se pueda controlar mediante la propiedad de alineación de texto de su padre, pero el soporte del navegador es irregular. En su mayoría, puede salirse con la suya utilizando hacks (por ejemplo, ver -moz-inline-stack) si desea seguir ese camino.

La otra manera de ir es tablas. Esto puede ser necesario cuando tiene columnas cuyo ancho realmente no se puede conocer de antemano. Realmente no puedo decir qué está tratando de hacer con el código de ejemplo: no hay nada obvio allí que necesite un bloque de contracción, pero una lista de productos podría considerarse tabular.

[PD. nunca use 'pt' para tamaños de fuente en la web. 'px' es más confiable si realmente necesita texto de tamaño fijo, de lo contrario, las unidades relativas como '%' son mejores. Y "claro: ccc ambos": ¿un error tipográfico?]

.center{
   text-align:center; 
}

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

JSFiddle

bobince
fuente
53
padre -> alinear texto: centro | child-> display: inline-block
mdskinner
55
display: inline-blockno es compatible con IE7 y versiones anteriores de Firefox
Jake Wilson
1
@Jakobud, para IE7 use "display: inline; zoom: 1;" en lugar de "display: inline-block;". Funciona para elementos de bloque.
mihail-haritonov
1
consulte este enlace para obtener más información sobre cómo utilizar este método de navegador cruzado - blog.mozilla.org/webdev/2009/02/20/cross-browser-inline-block
keyoke
1
Utilicé este scss para implementarlo, lo que funcionará mientras exista su estructura html para admitirlo: .center {text-align: center; &: primer hijo {display: bloque en línea; }}
Dovev Hefetz
95

La mayoría de los navegadores admiten la display: table;regla CSS. Este es un buen truco para centrar un div en un contenedor sin agregar HTML adicional ni aplicar estilos de restricción al contenedor (como el text-align: center;que centraría el resto del contenido en línea en el contenedor), mientras se mantiene el ancho dinámico para el div contenido:

HTML:

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

CSS:

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


Actualización (2015-03-09):

La forma correcta de hacer esto hoy es usar reglas de flexbox. El soporte del navegador es un poco más restringido ( soporte de tabla CSS frente a soporte de flexbox ) pero este método también permite muchas otras cosas, y es una regla CSS dedicada para este tipo de comportamiento:

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
fuente
11
Creo que esta es definitivamente la mejor solución. No involucra hacks extraños con divs anidados flotantes, ni nada de eso. Creo que la única razón por la que no tiene una calificación más alta es porque las personas han ido demasiado lejos en contra de las mesas. Esta no es una tabla, así que creo que es un método perfectamente legítimo.
Dan Jones
1
De acuerdo, esta parece ser la mejor solución. Si bien la solución de @bobince también es simple, tiene el efecto secundario de alterar los estilos en el elemento interno.
jorgeh
La display: table;variante es ideal para pseudo-elementos ( ::before, ::after) donde no puede agregar marcas adicionales y desea evitar la interrupción de los estilos de elementos adyacentes.
Walf
20

seis formas de pelar a ese gato:

Botón uno: cualquier cosa de tipo display: blockasumirá el ancho completo de los padres. (a menos que se combine con floato un display: flexpadre). Cierto. Mal ejemplo.

Botón 2: ir a display: inline-blockconducirá a un ancho automático (en lugar de completo). Luego puede centrarse usando text-align: center en el bloque de envoltura . Probablemente el más fácil y más compatible, incluso con navegadores 'vintage' ...

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

Botón 3: no es necesario poner nada en la envoltura. Quizás esta sea la solución más elegante. También funciona verticalmente. (La compatibilidad del navegador para la traducción es lo suficientemente buena (≥IE9) en estos días ...).

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

Por cierto: también es una excelente manera de centrar verticalmente bloques de altura desconocida (en relación con el posicionamiento absoluto).

Botón 4: posicionamiento absoluto. Solo asegúrese de reservar suficiente altura en el contenedor, ya que nadie más lo hará (ni clearfix ni 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ón 5: flotante (que también trae elementos de nivel de bloque al ancho dinámico) y un cambio relativo. Aunque he nunca visto esto en la naturaleza. Quizás hay desventajas ...

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

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

Actualizar: Botón 6: Y hoy en día, también puedes usar flex-box. Tenga en cuenta que los estilos se aplican al contenedor del objeto centrado.

.wrapSix
  display: flex
  justify-content: center

→ código fuente completo (sintaxis del lápiz)

Frank Nocke
fuente
17

Encontré una solución más elegante, combinando "bloque en línea" para evitar el uso de flotante y hacky clear: ambos. Todavía requiere divs anidados, que no es muy semántico, pero simplemente funciona ...

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

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

¡Espero eso ayude!

JavierIEH
fuente
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;
}

Si el elemento objetivo está absolutamente posicionado, puede centrarlo moviéndolo 50% en una dirección ( left: 50%) y luego transformándolo 50% en la dirección de oposición ( transform:translateX(-50%)). Esto funciona sin definir el ancho del elemento de destino (o con width:auto). La posición del elemento padre puede ser estática, absoluta, relativa o fija.

West1
fuente
1
Esto estará descentrado en la mitad del ancho de la cosa que está centrando.
4imble
@ 4imble No, no lo hará. La propiedad "izquierda" lo mueve 50% (50% del ancho de su padre), y translateX (-50%) lo mueve 50% en la otra dirección (50% del ancho del elemento objetivo).
West1
Ahh sí, me perdí el translateX. No estoy seguro de que esto sea confiable en cualquier IE anterior a IE 11. Pero tiene razón.
4imble
3

Por defecto, los divelementos se muestran como elementos de bloque, por lo que tienen un ancho del 100%, por lo que centrarlos no tiene sentido. Según lo sugerido por Arief, debe especificar ay widthluego puede usarlo autoal especificar marginpara centrar a div.

Alternativamente, también podría forzar display: inline, pero entonces tendría algo que se comportaría como un en spanlugar de un div, por lo que no tiene mucho sentido.

Adam Bellaire
fuente
3

Esto centrará un elemento como una Lista ordenada, o Lista no ordenada, o cualquier elemento. Simplemente envuélvelo con un Div con la clase de innerElement y dale al elemento interno la clase de innerElement.

La clase outerelement representa IE, el antiguo Mozilla y la mayoría de los navegadores más nuevos.

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

.innerElement {
    position: relative;
    left: -50%;
} 
Greg Benner
fuente
Por favor agregue una descripción con su código. Publicar código por sí solo no significará mucho para los futuros visitantes de SO.
Ren
3

use css3 flexbox con 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
fuente
1

Ligera variación en la respuesta de Mike M. Lin

Si agrega overflow: auto;(o hidden) a div.product_container, entonces no necesita div.clear.

Esto se deriva de este artículo -> http://www.quirksmode.org/css/clearing.html

Aquí está HTML modificado:

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

Y aquí está 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;
}

La razón, por qué es mejor sin div.clear (aparte de que se siente mal tener un elemento vacío) es la asignación de margen excesivamente celosa de Firefox.

Si, por ejemplo, tienes 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>

luego, en Firefox (8.0 en el punto de escritura), verá 11pxmargen antes product_container . Lo peor es que obtendrá una barra de desplazamiento vertical para toda la página, incluso si el contenido se ajusta perfectamente a las dimensiones de la pantalla.

Alexander Pogrebnyak
fuente
1

Prueba este nuevo CSS y marcado

Aquí está 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>

Y aquí está 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
fuente
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;
}

Si no proporciona "desbordamiento: oculto" para ".product_container", el div "centro exterior" se superpondrá a otros contenidos cercanos a la derecha del mismo. Cualquier enlace o botón a la derecha del "centro exterior" no funcionará. Pruebe el color de fondo para "centro exterior" para comprender la necesidad de "desbordamiento: oculto"

Cicil Thomas
fuente
1

Encontré una solución interesante, estaba haciendo un control deslizante y tuve que centrar los controles deslizantes e hice esto y funciona bien. También puede agregar una posición relativa al padre y mover la posición del niño vertical. Echar un vistazo 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
fuente
1

Hacer display:table;y configurar marginaauto

Bit de código importante:

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

No importa cuántos elementos tenga ahora, se alineará automáticamente en el centro

Ejemplo en fragmento de código:

jajaja
fuente
0

Me temo que la única forma de hacerlo sin especificar explícitamente el ancho es usar tablas (jadeo).

Kon
fuente
55
reformulado: Si no desea pasar la próxima hora probando todo tipo de combinación de CSS, DIV anidados y navegadores, vaya directamente a las tablas.
Eduardo Molteni
Las tablas no están diseñadas para ser utilizadas como elementos de diseño. Eso es mal estilo.
Sebi2020
0

Arreglo horrible, pero 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
fuente
0

Solución simple que funciona en navegadores antiguos (pero usa tablas y requiere una altura para ser establecida):

<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
fuente
0
<style type="text/css">
.container_box{
    text-align:center
}
.content{
    padding:10px;
    background:#ff0000;
    color:#ffffff;

}

use span en lugar de los divs internos

<div class="container_box">
   <span class="content">Hello</span>
</div>
alguien
fuente
0

Sé que esta pregunta es antigua, pero me estoy rindiendo. Muy similar a la respuesta de bobince pero con un ejemplo de código de trabajo.

Haga de cada producto un bloque en línea. Centrar el contenido del contenedor. Hecho.

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>

Ver también: Centrar bloques en línea con ancho dinámico en CSS

Wray Bowling
fuente
¿Esta respuesta ya no proporciona la misma solución? stackoverflow.com/a/284064/547733
Maxime Rossini
1
tienes razón, madmox! Sin embargo, no es tan robusto. También me doy cuenta de que establecer la alineación de texto a izquierda o derecha significa que esto nunca funcionará en un sitio con traducciones que incluyen cambiar el orden de lectura de izquierda a derecha de derecha a izquierda. text-align es para alinear texto, no elementos. Idealmente en un futuro próximo, dependemos de la pantalla: flex para este tipo de cosas.
Wray Bowling
0

Esta es una forma de centrar cualquier cosa dentro de un div sin conocer el ancho interno de los elementos.

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

mi solución fue:

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

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

agregue este CSS a su clase product_container

    margin: 0px auto;
    padding: 0px;
    border:0;
    width: 700px;
Pena
fuente
La pregunta dice específicamente "sin ancho"
Dez Udezue