Positionnement absolu ignorant le remplissage du parent

173

Comment faire en sorte qu'un élément positionné absolu honore le remplissage de son parent? Je veux qu'un div interne s'étende sur la largeur de son parent et soit positionné au bas de ce parent, essentiellement un pied de page. Mais l'enfant doit honorer le rembourrage du parent et il ne le fait pas. L'enfant est pressé contre le bord du parent.

Alors je veux ceci:

entrez la description de l'image ici

mais je comprends ceci:

entrez la description de l'image ici

<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>

Je peux y arriver avec une marge autour de la div interne, mais je préférerais ne pas avoir à ajouter cela.

d512
la source
5
Pourquoi ne pas changer la gauche / droite / bas du div interne en style="background-color: gray; position: absolute; left: 10px; right: 10px; bottom: 10px;"?
j08691
12
Oui, j'y ai pensé, mais cela devient rapidement un casse-tête de maintenance car chaque enfant doit avoir son propre jeu de compensations pour en tenir compte. S'ils respectent simplement le remplissage du parent, vous pouvez le définir une fois dans le parent et ne pas vous soucier de tous les enfants.
d512
Comme indiqué ci-dessus, si vous utilisez la valeur du remplissage du parent (positionné de manière relative) comme left:et right:sur l'enfant (positionné en absolu), votre problème est résolu. J'ajoute ce b / c c'est la réponse que d'autres avec le même problème sont susceptibles de rechercher.
rda3000
J'ai un problème similaire ici: jsfiddle.net/5n4By/6 . Le pied de page respecte le remplissage gauche de son parent, mais il déborde sur la droite. Vous vous attendriez à ce qu'il honore également le bon rembourrage pour rester cohérent ...
rafiki_rafi

Réponses:

186

Voyons d'abord pourquoi cela se produit.

La raison en est que, étonnamment, lorsqu'une boîte a position: absolute sa boîte contenant, c'est la boîte de remplissage du parent (c'est-à-dire la boîte autour de son remplissage). Cela est surprenant car généralement (c'est-à-dire lors de l'utilisation d'un positionnement statique ou relatif), la boîte contenant est la boîte de contenu du parent .

Voici la partie pertinente de la spécification CSS :

Dans le cas où l'ancêtre est un élément en ligne, le bloc contenant est le cadre de délimitation autour des boîtes de remplissage des première et dernière boîtes en ligne générées pour cet élément .... Sinon, le bloc conteneur est formé par le bord de remplissage de l'ancêtre.

L'approche la plus simple - comme suggéré dans la réponse de Winter - consiste à utiliser padding: inheritsur le positionné absolument div. Cela ne fonctionne, cependant, que si vous ne voulez pas que le positionné de manière absolue divait son propre rembourrage supplémentaire. Je pense que les solutions les plus générales (en ce que les deux éléments peuvent avoir leur propre rembourrage indépendant) sont:

  1. Ajoutez un supplément relativement positionné div(sans rembourrage) autour du positionné absolument div. Ce nouveaudiv respectera le remplissage de son parent, et le positionné absolument le divremplira alors.

    L'inconvénient, bien sûr, est que vous manipulez le HTML simplement à des fins de présentation.

  2. Répétez le remplissage (ou ajoutez-y) sur l'élément absolument positionné.

    L'inconvénient ici est que vous devez répéter les valeurs de votre CSS, ce qui est fragile si vous écrivez directement le CSS. Cependant, si vous utilisez un outil de prétraitement comme SASSou, LESSvous pouvez éviter ce problème en utilisant une variable. C'est la méthode que j'utilise personnellement.

Kevin Christopher Henry
la source
Pourquoi est-ce la valeur par défaut position: absolute? Il est surprenant que la boîte contenant soit la boîte de remplissage, mais il doit y avoir une raison à cela, tout comme je suis sûr qu'il y a une raison pour laquelle (sans box-sizing) le width& heightn'inclut pas le rembourrage ou la bordure.
trysis le
1
Juste un ajout: rien de tout cela n'est affecté par la box-sizingpropriété, sur le parent ou l'enfant. C'est parce que cela affecte le dimensionnement , comme en largeur / hauteur, mais pas la boîte contenant, bien que j'admets que cela aurait plus de sens si cela affectait les deux.
trysis le
2
C'est une bonne information, mais c'est la mauvaise réponse. La bonne réponse est Winter's ci-dessous ... utilisez le rembourrage: héritez et votre élément Absolute obtiendra le rembourrage dont il a besoin. Je ne sais pas pourquoi cela a plus de votes positifs que la bonne réponse ...: P
NotaGuruAtAll
1
@NotaGuruAtAll: padding: inheritfonctionne bien si le positionnement absolu divn'a pas besoin de rembourrage propre, et j'ai ajouté une mention de cette technique. C'est moins flexible, cependant, car vous ne pouvez pas ajouter de rembourrage supplémentaire à la position absolue div(c'est-à-dire que vous ne pouvez pas dire padding: inherit + 5px). C'est pourquoi je préfère les techniques que je mentionne ici.
Kevin Christopher Henry
1
Le remplissage hérité de l' position:absoluteélément enfant fonctionne en effet si vous recherchez simplement que l'enfant respecte le remplissage du parent. Cependant, si vous cherchez à ajouter un rembourrage supplémentaire à l'enfant, vous devrez garder le rapport de rembourrage en contrôle dans votre code. Pas de moyen propre de le faire avec juste CSS.
Dylan Pierce
51

Une chose que vous pouvez essayer est d'utiliser le css suivant:

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

Il permet à l'élément enfant d'hériter du remplissage du parent, puis l'enfant peut être positionné pour correspondre au widht et au remplissage des parents.

Aussi, j'utilise box-sizing: border-box; pour les éléments impliqués.

Je n'ai pas testé cela dans tous les navigateurs, mais cela semble fonctionner dans Chrome, Firefox et IE10.

Hiver
la source
J'ai combiné cette réponse et la réponse de @NewSpender. Dans mon cas particulier, le div positionné absolu a continué à ignorer le remplissage mais a été délimité par son élément parent. Donc, donner le div positionné absolu avec des bordures épaisses blanches imitait le rembourrage dont j'avais besoin. Une condition préalable est cependant que votre arrière-plan doit être de la même couleur.
Ogier Schelvis
Mais OP ne veut pas que l'enfant hérite du remplissage du parent. Il veut que l'enfant soit décalé en fonction du remplissage du parent.
Michael Gummelt
30

Eh bien, ce n'est peut-être pas la solution la plus élégante (sémantiquement), mais dans certains cas, cela fonctionnera sans aucun inconvénient: au lieu d'un remplissage, utilisez une bordure transparente sur l'élément parent. Les éléments enfants positionnés en absolu respecteront la bordure et le rendu sera exactement le même (sauf que vous utilisez la bordure de l'élément parent pour le style).

NouveauSpender
la source
6

Voici ma meilleure chance. J'ai ajouté une autre Div et l'ai rendue rouge et j'ai changé la taille de votre parent à 200px juste pour la tester. L'idée est que l'enfant devient maintenant le petit-enfant et le parent devient le grand-parent. Le parent respecte donc son parent. J'espère que vous avez mon idée.

<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>

Éditer:

Je pense que ce que vous essayez de faire ne peut pas être fait. La position absolue signifie que vous allez lui donner les coordonnées qu'elle doit honorer. Que faire si le parent a un remplissage de 5 px. Et vous positionnez absolument l'enfant en haut: -5px; à gauche: -5px . Comment est-il censé honorer le parent et vous en même temps ??

Ma solution

Si vous voulez qu'il honore le parent, ne le positionnez pas absolument.

Toucher
la source
Merci, j'apprécie le message, mais c'est toujours une solution de contournement pour le vrai problème. Ce que je veux vraiment savoir, c'est si vous pouvez faire en sorte que les enfants honorent le remplissage de l'élément parent. S'il s'avère que la réponse est non, je vous donnerai le représentant.
d512
Si vous les positionnez absolument, ils n'honoreront pas leur élément parent. Ils vous honoreront. Pour la même raison, si vous ne les positionnez pas absolument, vous ne pouvez pas vraiment utiliser des éléments comme bottom: 10px car ils honorent leur élément parent. Mais ce que vous voulez faire, je suppose, fera place à une contradiction et donc, cela différera selon les navigateurs. Je pense que seul un travail fera l'affaire.
Touchez le
3
Le positionnement absolu respecte le parent, c'est le système de coordonnées qu'il utilise. Lorsque vous dites top 0px, cela signifie 0px loin du haut du parent. La question est de savoir si elle doit ou non prendre en compte le rembourrage des parents. Si le parent avait un remplissage de 5px et que vous donniez à l'enfant top: -5px, cela le mettrait au ras du parent si le remplissage du parent était respecté, ou 5px au-dessus du parent si ce n'était pas le cas.
d512
3

1.) vous ne pouvez pas utiliser de grande bordure sur le parent - au cas où vous voudriez avoir une bordure spécifique

2.) vous ne pouvez pas ajouter de marge - au cas où votre parent fait partie d'un autre conteneur et que vous voulez que votre parent prenne le plein largeur de ce grand parent.

La seule solution qui devrait être applicable est d'emballer vos enfants dans un autre conteneur afin que votre parent devienne le grand-parent, puis d'appliquer un rembourrage au wrapper / parent des nouveaux enfants. Ou vous pouvez directement appliquer un rembourrage aux enfants.

Dans ton cas:

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

Aurait pu facilement le faire en utilisant un niveau supplémentaire 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>

Démo: https://jsfiddle.net/soxv3vr0/

Asankasri
la source
0

ajouter un remplissage: héritez de votre position absolue

.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î
la source