CSS: Як розташувати два елементи один на одному, не вказуючи висоту?


96

У мене є два DIV, які мені потрібно розташувати точно один над одним. Однак, коли я це роблю, форматування все псується, оскільки вміст DIV діє так, ніби немає висоти. Я думаю, що це очікувана поведінка, position:absoluteале мені потрібно знайти спосіб розташувати ці два елементи один на одному і розтягнути контейнер у міру розтягування вмісту:

Верхній лівий край .layer2повинен бути точно вирівняний до верхнього лівого краюlayer1

<!-- HTML -->
<div class="container_row">
    <div class="layer1">
        Lorem ipsum...
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>

/* CSS */
.container_row {}

.layer1 {
    position:absolute;
    z-index: 1;
}

.layer2 {
    position:absolute;
    z-index: 2;
}

1
position: absoluteтоді не зовсім правильний стиль.
BoltClock

так, position:absoluteне відчуває себе добре. Який би був правильний стиль?
Ендрю

Чи мають елементи .layer1and та .layer2відомий розмір?
му занадто коротке

Ні, вони також мають невідомий розмір.
Ендрю

Відповіді:


81

Перш за все, ви дійсно повинні включати позицію щодо абсолютно розташованих елементів, інакше ви зіткнетеся з дивною та заплутаною поведінкою; ви, ймовірно, хочете додати top: 0; left: 0до CSS для обох ваших абсолютно розташованих елементів. Ви також хочете мати position: relativeна, .container_rowякщо ви хочете, щоб абсолютно позиціоновані елементи розташовувались відносно їх батьків, а не до тіла документа :

Якщо елемент має 'position: absolute', що містить блок встановлюється найближчим предком з 'position' of 'absolute', 'relative' or 'fixed' ...

Ваша проблема полягає в тому, що position: absoluteвилучає елементи із звичайного потоку :

Він повністю виведений з нормального потоку (він не впливає на наступних братів і сестер). Абсолютно розташоване вікно встановлює новий блок, що містить для нормальних потоків дітей і абсолютно (але не фіксованих) позиціонованих нащадків. Однак вміст абсолютно розташованого елемента не обтікає жодних інших коробок.

Це означає, що абсолютно розташовані елементи взагалі не впливають на розмір батьківського елемента, а <div class="container_row">висота вашого першого буде нульовою.

Таким чином, ви не можете робити те, що намагаєтесь зробити з абсолютно розташованими елементами, якщо не знаєте, наскільки вони будуть високими (або, що еквівалентно, ви можете вказати їх висоту). Якщо ви можете вказати висоти, тоді ви можете поставити однакові висоти на, .container_rowі все вишикується; Ви також можете поставити margin-topна другому, .container_rowщоб залишити місце для абсолютно розташованих елементів. Наприклад:

http://jsfiddle.net/ambiguous/zVBDc/


Чудова відповідь, спасибі! Я думаю, мені, можливо, доведеться динамічно визначити висоту за допомогою JavaScript. Я просто сподівався, що до цього не доведеться дійти. = [
Ендрю

@Andrew: Так, ласкаво просимо до системи вертикального розміру / положення / вирівнювання CSS: якщо ви не знаєте конкретних розмірів речей, вам, як правило, не щастить. З горизонтальними матеріалами легше боротися, але більшість із них все ще пахне, ніби вони були розроблені "людьми з друком із фіксованим макетом", а не "людьми з динамічним макетом".
му занадто коротке

1
Не position: absoluteпотрібно. Будь ласка, перевірте: stackoverflow.com/a/51949049/1736186
замість цього

63

Насправді це можливо без положення absoluteта вказівки будь-якої висоти. Все, що вам потрібно зробити, - це використовувати display: gridбатьківський елемент і помістити нащадків у той самий рядок і стовпець.

Будь ласка, перевірте приклад нижче на основі вашого HTML. Я додав лише <span>деякі кольори, так що ви можете побачити результат.

Ви також можете легко змінити z-indexкожен з нащадкових елементів, щоб маніпулювати його видимістю (який повинен бути зверху).

.container_row{
  display: grid;
}

.layer1, .layer2{
  grid-column: 1;
  grid-row: 1;
}

.layer1 span{
  color: #fff;
  background: #000cf6;
}

.layer2{
  background: rgba(255, 0, 0, 0.4);
}
<div class="container_row">
    <div class="layer1">
        <span>Lorem ipsum...<br>Test test</span>
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>


11
Приємно. Але чесно кажучи, display: gridне існувало сім років тому :)
mu занадто короткий

Внизу є ще одна відповідь, написана @Cornelius. Він використовує flex, що на сьогодні має набагато кращу підтримку браузера.
Олег Черр,

20

Чудова відповідь, "mu занадто короткий". Я шукав саме те саме, і після прочитання Вашого допису знайшов рішення, яке відповідало моїй проблемі.

Я мав два елементи однакового розміру і хотів їх скласти. Оскільки кожен має однаковий розмір, що я міг зробити, це зробити

position: absolute;
top: 0px;
left: 0px;

лише на останньому елементі. Таким чином перший елемент вставляється правильно, «штовхаючи» батьківську висоту, а другий елемент розміщується зверху.

Сподіваюся, це допоможе іншим людям, які намагаються скласти 2+ елементи з однаковою (невідомою) висотою.


1
NB: За такого підходу вам все одно потрібно буде знати, який елемент є вищим, щоб можна position: abosluteбуло взяти інший .
Алек

10

Ось ще одне рішення з використанням display: flex замість position: absolute або display: grid.

.container_row{
  display: flex;
}

.layer1 {
  width: 100%;
  background-color: rgba(255,0,0,0.5);  // red
}

.layer2{
  width: 100%;
  margin-left: -100%;
  background-color: rgba(0,0,255,0.5);  // blue
}
<div class="container_row">
    <div class="layer1">
        <span>Lorem ipsum...</span>
    </div>
    <div class="layer2">
        More lorem ipsum...
    </div>
</div>
<div class="container_row">
    ...same HTML as above. This one should never overlap the .container_row above.
</div>


Чудове рішення. Дякую!
Олег Черр

5

Довелося встановлювати

Container_height = Element1_height = Element2_height

.Container {
    position: relative;
}

.ElementOne, .Container ,.ElementTwo{
    width: 283px;
    height: 71px;
}

.ElementOne {
    position:absolute;
}

.ElementTwo{
    position:absolute;
}

Використовуйте може використовувати z-index, щоб встановити, який з них буде зверху.


4

Ось деякі багаторазові css, які збережуть висоту кожного елемента без використання position: absolute:

.stack {
    display: grid;
}
.stack > * {
    grid-row: 1;
    grid-column: 1;
}

Перший елемент у вашому stack- фон, а другий - передній план.


2

Через абсолютне позиціонування вилучення елементів із положення документообігу: абсолют не є правильним інструментом для роботи. Залежно від точного макета, який ви хочете створити, вам вдасться використовувати негативні поля, позицію: відносна або, можливо, навіть трансформувати: перекласти. Покажіть нам зразок того, що ви хочете зробити, ми можемо допомогти вам краще.


1

Звичайно, проблема полягає у тому, щоб повернути свій зріст. Але як ви можете це зробити, якщо ви не знаєте висоту заздалегідь? Ну, якщо ви знаєте, яке співвідношення сторін ви хочете надати контейнеру (і підтримувати його реагування), ви можете повернути свій зріст, додавши відступ до іншої дочірньої частини контейнера, вираженого у відсотках.

Ви навіть можете додати манекен divв контейнер і встановити щось на зразок того, padding-top: 56.25%щоб надати фіктивному елементу висоту, яка пропорційна ширині контейнера. Це виштовхне контейнер і надасть йому пропорцію, у цьому випадку 16: 9 (56,25%).

Заповнення та поля використовують відсоток ширини, в цьому справді фокус.


0

Після довгих перевірок я переконався, що вихідне питання вже правильне; відсутні лише пара налаштувань:

  • container_rowповинні матиposition: relative;
  • діти (...), ПОВИННІ мати position: absolute; left:0;
  • щоб переконатися, що діти (...) вирівнюються точно один над одним, container_rowслід мати додатковий стиль:
    • height:x; line-height:x; vertical-align:middle;
    • text-align:center; також може допомогти.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.