Posicionamiento absoluto ignorando el relleno del padre

173

¿Cómo hacer que un elemento posicionado en absoluto honre el relleno de su padre? Quiero que un div interno se extienda a lo ancho de su padre y se coloque en la parte inferior de ese padre, básicamente un pie de página. Pero el niño tiene que honrar el relleno del padre y no está haciendo eso. El niño se presiona contra el borde del padre.

Entonces quiero esto:

ingrese la descripción de la imagen aquí

pero estoy obteniendo esto:

ingrese la descripción de la imagen aquí

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
      <div style="background-color: gray; position: absolute; left: 0px; right: 0px; bottom: 0px;">css sux</div>
    </div>
  </body>
</html>

Puedo hacer que suceda con un margen alrededor del div interno, pero preferiría no tener que agregar eso.

d512
fuente
55
¿Por qué no cambiar el izquierdo / derecho / inferior del div interno a style="background-color: gray; position: absolute; left: 10px; right: 10px; bottom: 10px;"?
j08691
12
Sí, pensé en eso, pero rápidamente se convierte en un dolor de cabeza de mantenimiento porque cada niño tiene que tener su propio conjunto de compensaciones para tenerlo en cuenta. Si solo honraran el relleno de los padres, entonces podría configurarlo una vez en el padre y no preocuparse por todos los niños.
d512
Como se señaló anteriormente, si usa el valor del relleno del padre (en posición relativa) como left:y right:en el niño (en posición absoluta), su problema está resuelto. Estoy agregando este b / c que es la respuesta que otros con el mismo problema probablemente estén buscando.
rda3000
Tiene un problema similar aquí: jsfiddle.net/5n4By/6 . El pie de página honra el acolchado izquierdo de su padre, pero se desborda a la derecha. Es de esperar que honre el relleno correcto y se mantenga constante ...
rafiki_rafi

Respuestas:

186

Primero, veamos por qué sucede esto.

La razón es que, sorprendentemente, cuando un cuadro tiene position: absolutesu cuadro contenedor es el cuadro de relleno del padre (es decir, el cuadro alrededor de su relleno). Esto es sorprendente porque generalmente (es decir, cuando se usa un posicionamiento estático o relativo) el cuadro contenedor es el cuadro de contenido principal .

Aquí está la parte relevante de la especificación CSS :

En el caso de que el antepasado sea un elemento en línea, el bloque contenedor es el cuadro delimitador alrededor de los cuadros de relleno del primer y último cuadro en línea generado para ese elemento ... De lo contrario, el bloque contenedor está formado por el borde de relleno de El antepasado.

El enfoque más simple, como se sugiere en la respuesta de Winter, es utilizarlo padding: inheriten la posición absoluta div. Sin embargo, solo funciona si no desea que las personas absolutamente posicionadas divtengan su propio relleno adicional. Creo que las soluciones más generales (en que ambos elementos pueden tener su propio relleno independiente) son:

  1. Agregue una posición adicional relativamente div(sin relleno) alrededor de la posición absoluta div. Esa nueva divrespetará el relleno de su padre, y la posición absoluta divlo llenará.

    La desventaja, por supuesto, es que estás jugando con el HTML simplemente con fines de presentación.

  2. Repita el relleno (o agréguelo) en el elemento en posición absoluta.

    La desventaja aquí es que tienes que repetir los valores en tu CSS, lo cual es frágil si estás escribiendo el CSS directamente. Sin embargo, si está utilizando una herramienta de preprocesamiento como SASSo LESSpuede evitar ese problema utilizando una variable. Este es el método que uso personalmente.

Kevin Christopher Henry
fuente
¿Por qué es este el valor predeterminado position: absolute? Es sorprendente que el cuadro que contiene es el cuadro de relleno, pero debe haber una razón para ello, al igual que estoy seguro de que hay una razón por la cual (sin box-sizing) el width& heightno incluye el relleno o el borde.
trysis
1
Solo una adición: nada de esto se ve afectado por la box-sizingpropiedad, en el padre o hijo. Esto se debe a que afecta el tamaño , como en ancho / alto, pero no en el cuadro que lo contiene, aunque admito que tendría más sentido si afectara a ambos.
trysis
2
Esta es una buena información, pero es la respuesta INCORRECTA. La respuesta correcta es Winter a continuación ... use relleno: herede y su elemento Absolute obtendrá el relleno que necesita. No sé por qué esto tiene más votos a favor que la respuesta correcta ...: P
NotaGuruAtAll
1
@NotaGuruAtAll: padding: inheritfunciona bien si el absolutamente posicionado divno necesita ningún relleno propio, y he agregado una mención de esa técnica. Sin embargo, es menos flexible porque no se puede agregar ningún relleno adicional a la posición absoluta div(es decir, no se puede decir padding: inherit + 5px). Por eso prefiero las técnicas que menciono aquí.
Kevin Christopher Henry
1
El relleno heredado en el position:absoluteelemento hijo de hecho funciona si solo está buscando que el hijo respete el relleno del padre. Sin embargo, si está buscando agregar relleno adicional al niño, tendrá que mantener la proporción de rellenos bajo control en su código. No hay una forma limpia de hacerlo con solo CSS.
Dylan Pierce
51

Una cosa que puedes probar es usar el siguiente CSS:

.child-element {
    padding-left: inherit;
    padding-right: inherit;
    position: absolute;
    left: 0;
    right: 0;
}

Permite que el elemento secundario herede el relleno del elemento primario, luego el elemento secundario se puede colocar para que coincida con el ancho y el relleno de los elementos principales.

Además, estoy usando box-sizing: border-box;los elementos involucrados.

No he probado esto en todos los navegadores, pero parece estar funcionando en Chrome, Firefox e IE10.

Invierno
fuente
Combiné esta respuesta y la respuesta de @NewSpender. En mi caso particular, el div en posición absoluta siguió ignorando el relleno pero estaba limitado por su elemento padre. Entonces, dar el div en posición absoluta con bordes gruesos blancos imitaba el relleno que necesitaba. Sin embargo, un requisito previo es que su fondo debe ser del mismo color.
Ogier Schelvis
Pero OP no quiere que el hijo herede el relleno de los padres. Él quiere que el niño sea compensado de acuerdo con el relleno de los padres.
Michael Gummelt
30

Bueno, esta puede no ser la solución más elegante (semánticamente), pero en algunos casos funcionará sin inconvenientes: en lugar de relleno, use un borde transparente en el elemento principal. Los elementos secundarios en posición absoluta respetarán el borde y se representarán exactamente de la misma manera (excepto que está usando el borde del elemento principal para el estilo).

NewSpender
fuente
6

Aquí está mi mejor oportunidad. Agregué otro Div y lo hice rojo y cambié la altura de tus padres a 200 px solo para probarlo. La idea es que el niño ahora se convierte en nieto y el padre se convierte en abuelo. Entonces el padre respeta a su padre. Espero que entiendas mi idea.

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 200px;">
     <div style="background-color: red;  position: relative; height: 100%;">    
        <div style="background-color: gray; position: absolute; left: 0px; right: 0px;bottom: 0px;">css sux</div>
     </div>
    </div>
  </body>
</html>

Editar:

Creo que lo que estás tratando de hacer no se puede hacer. La posición absoluta significa que le va a dar las coordenadas que debe cumplir. ¿Qué pasa si el padre tiene un relleno de 5px? Y absolutamente coloca al niño en la parte superior: -5px; izquierda: -5px . ¿Cómo se supone honrar a los padres y a ti al mismo tiempo?

Mi solución

Si quiere que honre al padre, no lo posicione absolutamente entonces.

Toque
fuente
Gracias, agradezco la publicación, pero sigue siendo una solución para el problema real. Lo que realmente quiero saber es si puedes hacer que los niños honren el relleno del elemento padre. Si resulta que la respuesta es no, te daré el representante.
d512
Si los posiciona absolutamente, no honrarán a su elemento padre. Te honrarán. Por la misma razón, si no los posiciona absolutamente, entonces no puede usar cosas como bottom: 10px porque honran a su elemento padre. Pero supongo que lo que desea hacer dará cabida a una contradicción y, por lo tanto, será diferente en los navegadores. Creo que solo funcionará una solución.
Toque
3
El posicionamiento absoluto honra al padre, ese es el sistema de coordenadas que utiliza. Cuando dices top 0px, eso significa 0px lejos de la parte superior del padre. La pregunta es si debe o no tener en cuenta el relleno de los padres. Si el padre tenía un relleno de 5px y le daba al niño la parte superior: -5px, lo pondría al ras con el padre si el relleno del padre era honrado, o 5px por encima del padre si no lo era.
d512
3

1.) no puede usar un borde grande en el padre - en caso de que quiera tener un borde específico

2.) no puede agregar margen - en caso de que su padre sea parte de otro contenedor y quiera que su padre tome el control completo ancho de ese abuelo.

La única solución que debería ser aplicable es envolver a sus hijos en otro contenedor para que sus padres se conviertan en abuelos y luego aplicar relleno al nuevo envoltorio / padre para niños nuevos. O puede aplicar directamente el relleno a los niños.

En tu caso:

.css-sux{
  padding: 0px 10px 10px 10px;
}
bhavya_w
fuente
1

Podría haberlo hecho fácilmente usando un nivel extra de Div.

<div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
  <div style="position: absolute; left: 0px; right: 0px; bottom: 10px; padding:0px 10px;">
    <div style="background-color: gray;">css sux</div>
  </div>
</div>

Demostración: https://jsfiddle.net/soxv3vr0/

asankasri
fuente
0

agregar relleno: herede en su posición absoluta

.box{
  background: red;
  position: relative;
  padding: 30px;
  width:500px;
  height:200px;
 box-sizing: border-box;
 

}
<div  class="box">

  <div style="position: absolute;left:0;top:0;padding: inherit">top left</div>
  <div style="position: absolute;right:0;top:0;padding: inherit">top right</div>
  <div style="text-align: center;padding: inherit">center</div>
  <div style="position: absolute;left:0;bottom:0;padding: inherit">bottom left</div>
  <div style="position: absolute;right:0;bottom:0;padding: inherit">bottom right</div>


</div>

ßãlãjî
fuente