Абсолютное позиционирование, игнорируя отступы родителя


173

Как сделать так, чтобы элемент с абсолютным позиционированием соблюдал заполнение его родителя? Я хочу, чтобы внутренний div растягивался по ширине своего родителя и располагался внизу этого родителя, в основном нижний колонтитул. Но ребенок должен соблюдать отступление родителя, а он этого не делает. Ребенок прижимается прямо к краю родителя.

Итак, я хочу это:

введите описание изображения здесь

но я получаю это:

введите описание изображения здесь

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

Я могу сделать это с полем вокруг внутреннего div, но я бы предпочел не добавлять это.


5
Почему бы не изменить левый / правый / нижний угол внутреннего элемента div на style="background-color: gray; position: absolute; left: 10px; right: 10px; bottom: 10px;"?
j08691

12
Да, я думал об этом, но это быстро становится головной болью обслуживания, потому что у каждого ребенка должен быть свой собственный набор компенсаций, чтобы объяснить это. Если бы они просто соблюдали отступы родителя, вы могли бы просто установить его один раз в родителе и не беспокоиться обо всех дочерних элементах.
d512

Как указывалось выше, если вы используете значение отступа (относительного позиционирования) родителя в качестве дочернего элемента ( left:и right:абсолютного позиционирования), ваша проблема будет решена. Я добавляю это ч / б, это ответ, который, вероятно, будут искать другие с такой же проблемой.
rda3000

Есть похожая проблема здесь: jsfiddle.net/5n4By/6 . Нижний колонтитул соблюдает левый отступ своего родителя, но справа переполняется. Вы могли бы ожидать, что он будет соблюдать правильные отступы, чтобы оставаться последовательным ...
rafiki_rafi

Ответы:


186

Сначала посмотрим, почему это происходит.

Причина в том, что, как ни удивительно, когда у блока есть position: absoluteсодержащий его блок, это блок заполнения родительского элемента (то есть, блок вокруг его заполнения). Это удивительно, потому что обычно (то есть при использовании статического или относительного позиционирования) содержащее поле является родительским блоком содержимого .

Вот соответствующая часть спецификации CSS :

В случае, когда предок является встроенным элементом, содержащий блок является ограничивающим прямоугольником вокруг полей дополнения первого и последнего встроенных блоков, сгенерированных для этого элемента ... В противном случае содержащийся блок формируется краем заполнения предок.

Самый простой подход - как предлагается в ответе Винтера - использовать padding: inheritабсолютно позиционированный div. Тем не менее, это работает только в том случае, если вы не хотите, чтобы у абсолютно позиционированного divобъекта был какой-либо дополнительный отступ. Я думаю, что наиболее универсальные решения (в которых оба элемента могут иметь свои собственные независимые отступы):

  1. Добавьте дополнительный относительно позиционированный div(без отступов) вокруг абсолютно позиционированный div. Это новое divбудет уважать отступы его родителя, и тогда абсолютно позиционированное divзаполнит его.

    Недостатком, конечно, является то, что вы возитесь с HTML просто для презентационных целей.

  2. Повторите отступ (или добавьте к нему) для абсолютно позиционированного элемента.

    Недостатком здесь является то, что вы должны повторять значения в вашем CSS, что хрупко, если вы пишете CSS напрямую. Однако, если вы используете инструмент предварительной обработки, например, SASSили LESSвы можете избежать этой проблемы с помощью переменной. Это метод, который я лично использую.


Почему это по умолчанию для position: absolute? Удивительно, что вмещающий блок является полем заполнения, но, должно быть, для этого была причина, точно так же, как я уверен, что есть причина, по которой (без box-sizing) width& heightне включают отступ или границу.
Trysis

1
Просто дополнение: ничто из этого не зависит от box-sizingсвойства, на родителя или ребенка. Это связано с тем, что это влияет на размеры , как на ширину / высоту, но не на ячейку, в которой они содержатся, хотя я допускаю, что это будет иметь больше смысла, если это повлияет на оба.
Trysis

2
Это хорошая информация, но это НЕПРАВИЛЬНЫЙ ответ. Правильный ответ - ниже, чем у Винтера .... используйте padding: наследовать, и ваш элемент Absolute получит необходимый ему отступ. Не знаю, почему это имеет больше голосов, чем правильный ответ ...: P
NotaGuruAtAll

1
@NotaGuruAtAll: padding: inheritработает хорошо, если абсолютно позиционированный divне нуждается ни в каком собственном заполнении, и я добавил упоминание об этой технике. Это менее гибко, потому что вы не можете добавить дополнительный отступ к абсолютно позиционированному div(то есть вы не можете сказать padding: inherit + 5px). Вот почему я предпочитаю методы, которые я упоминаю здесь.
Кевин Кристофер Генри

1
Наследование заполнения для position:absoluteдочернего элемента действительно работает, если вы просто ищете, чтобы дочерний элемент соблюдал заполнение родительского элемента. Тем не менее, если вы хотите добавить дополнительные отступы для дочернего элемента, вам придется следить за соотношением заполнений в вашем коде. Нет чистого способа сделать это только с помощью CSS.
Дилан Пирс,

51

Одна вещь, которую вы можете попробовать использовать следующий CSS:

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

Это позволяет дочернему элементу наследовать заполнение от родителя, тогда дочерний элемент может быть расположен так, чтобы соответствовать родительскому видению и заполнению.

Также я использую box-sizing: border-box;для задействованных элементов.

Я не проверял это во всех браузерах, но, похоже, он работает в Chrome, Firefox и IE10.


Я объединил этот ответ и ответ @NewSpender. В моем конкретном случае div с абсолютным позиционированием игнорировал заполнение, но был ограничен его родительским элементом. Таким образом, абсолютное позиционирование div с белыми толстыми границами имитировало необходимое мне отступление. Обязательным условием является то, что ваш фон должен быть одного цвета.
Ожье

Но OP не хочет, чтобы ребенок наследовал отступы родителя. Он хочет, чтобы ребенок был смещен в соответствии с отступами родителей.
Майкл Гаммельт

30

Возможно, это не самое элегантное решение (семантически), но в некоторых случаях оно будет работать без каких-либо недостатков: вместо заполнения используйте прозрачную границу для родительского элемента. Абсолютно позиционированные дочерние элементы будут соблюдать границу, и она будет отображаться точно так же (за исключением того, что вы используете границу родительского элемента для стилизации).



6

Вот мой лучший выстрел в это. Я добавил еще один Div, сделал его красным и изменил рост вашего родителя на 200px, просто чтобы проверить это. Идея в том, что ребенок теперь становится внуком, а родитель становится прародителем. Таким образом, родитель уважает своего родителя. Надеюсь, вы поняли мою идею.

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

Редактировать:

Я думаю, что вы пытаетесь сделать, не может быть сделано. Абсолютная позиция означает, что вы собираетесь дать ему координаты, которые он должен соблюдать. Что делать, если родитель имеет отступ 5px. И вы абсолютно позиционируете ребенка сверху: -5px; слева: -5px . Как можно почитать родителя и тебя одновременно?

Мое решение

Если вы хотите, чтобы это чтило родителя, тогда не устанавливайте его абсолютно.


Спасибо, я ценю сообщение, но это все еще обходной путь для реальной проблемы. Что я действительно хочу знать, так это то, что вы можете заставить детей соблюдать отступы родительского элемента. Если окажется, что ответ «нет», я дам вам ответ.
d512

Если вы их абсолютно позиционируете, то они не будут соблюдать свой родительский элемент. Они будут чтить тебя. По той же причине, если вы не располагаете их абсолютно, то вы не сможете использовать такие вещи, как bottom: 10px, потому что они уважают свой родительский элемент. Но то, что вы хотите сделать, я предполагаю, создаст место для противоречия и, следовательно, оно будет отличаться в браузерах. Я думаю, что только обходной путь подойдет.
Коснитесь

3
Абсолютное позиционирование уважает родителя, это система координат, которую он использует. Когда вы говорите top 0px, это означает 0px от вершины родителя. Вопрос заключается в том, следует ли принимать во внимание родительские дополнения. Если у родительского отступа было 5px, и вы указали дочернему элементу top: -5px, он поместил бы его вровень с родителем, если было выполнено заполнение родителя, или на 5px выше родительского, если это не так.
d512

3

1.) вы не можете использовать большую рамку для родителя - в случае, если вы хотите иметь определенную рамку

2.) вы не можете добавить маржу - в случае, если ваш родительский элемент является частью какого-либо другого контейнера, и вы хотите, чтобы ваш родительский элемент взял полную ширина этого прародителя.

Единственное решение, которое должно быть применимо, - это обернуть ваших детей в другой контейнер, чтобы ваш родитель стал прародителем, а затем применить обивка для нового детского обертки / родителя. Или вы можете напрямую применить прокладку для детей.

В твоем случае:

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

1

Это легко сделать, используя дополнительный уровень 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>

Демо: https://jsfiddle.net/soxv3vr0/


0

добавить отступы: наследовать в вашей абсолютной позиции

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.