Css вертикальное выравнивание с вложенными div

Этот вопрос возник в результате исправления, предложенного для этого связанного вопроса

У меня есть 3 вложенных div: внешний, внутренний и элемент.

<div class="outer">
  <div class="inner"><div class="item"></div></div>
</div>

Учитывая следующий базовый CSS:

.outer{
  width:50%;
  height:100px;
  border: 1px solid red;
  position:relative;
  overflow-x:hidden;
  box-sizing:border-box;
}
.inner{
  border:1px solid blue;
  height:100%;
  position: absolute;
  box-sizing: border-box;
  line-height:98px;
}
.item{
  width:100px;
  height:94px;
  background-color:yellow;
  display: inline-block;
  border:1px solid green;
  box-sizing:border-box;
  vertical-align:middle;
}

Задача состоит в том, чтобы центрировать элемент div по вертикали с равными (или отсутствующими) промежутками сверху/снизу и без появления вертикальных полос прокрутки.

Кодировать здесь

Обновлять:

Как указано ниже, я должен добавить, что несколько элементов разной высоты должны быть центрированы. На данный момент лучшим ответом является добавление отрицательного поля к каждому элементу, что приводит к следующему: http://codepen.io/anon/pen/dYWEYZ

Однако это плохо пахнет (для меня), так как требует смещения, которое зависит от 3 других свойств.


person Will Jenkins    schedule 07.10.2015    source источник
comment
здесь так много хакерского материала, почему бы просто не добавить еще: margin-top: -5px; к классу .item центрирует его. codepen.io/anon/pen/PPmgBR   -  person deebs    schedule 07.10.2015
comment
похоже, что с высотой строки 98 пикселей должно быть переполнение-x: скрыто, должно быть встроенное блокирование в классе .item. В любом случае, margin-top: -5px исправляет это, потому что он подстраивается под границу в 1 пиксель для внешней и внутренней (всего 4 пикселя) и разницу в высоте строки. Если вы сделаете границы по 2 пикселя снаружи и внутри (всего 8 пикселей), тогда верхняя граница станет -9 пикселей, и это нормально. Все дело в границах с учетом высоты строки.   -  person deebs    schedule 07.10.2015
comment
Ни одна из этих вещей не является хакерской, они требуются по дизайну. Это для карусели изображений, изображения имеют разную высоту и должны быть сложены вместе (требуется встроенный блок), скрытое переполнение состоит в том, чтобы показывать только некоторые изображения за раз, бла-бла-бла. Это все требуется.   -  person Will Jenkins    schedule 07.10.2015


Ответы (3)


Простое решение: http://codepen.io/anon/pen/jbmRjo.

чтобы добавить это в ваш класс .item:

margin-top: -5px;

Это из-за границ ваших внешних и внутренних классов, а также высоты строки внутреннего класса. Если вы сделаете границы 2px вместо 1px, тогда верхнее поле станет -9px. Если вы оставите границы в 1 пиксель и сделаете высоту строки 96 пикселей, верхнее поле станет -3 пикселя.

Так почему же вы не можете использовать отрицательную маржу?

person deebs    schedule 07.10.2015
comment
Это работает (codepen.io/anon/pen/dYWEYZ), но плохо пахнет. Тот факт, что мы должны учитывать 3 других измерения за пределами элемента, не очень хорош, но если ни у кого нет лучшего решения, я приму этот ответ... - person Will Jenkins; 07.10.2015
comment
Соглашусь, что немного воняет. Это, безусловно, интересный сценарий — вы над этим работаете или просто любопытны? - person deebs; 07.10.2015

Если вы используете flexbox, этого легко добиться:

.inner{
  border:1px solid blue;
  height:100%;
  position: absolute;
  box-sizing: border-box;
  line-height:98px;
  display:flex;
  align-items:center;
}
person Jesse    schedule 07.10.2015
comment
Я обнаружил непоследовательное поведение на мобильных устройствах с flexbox - person Will Jenkins; 07.10.2015

Вы можете использовать display: table-cell;, чтобы получить желаемое вертикальное центрирование:

.outer{
  width:50%;
  height:100px;
  border: 1px solid red;
  position:relative;
  overflow-x:hidden;
  box-sizing:border-box;
}
.inner{
  border:1px solid blue;
  height:100%;
  position: absolute;
  box-sizing: border-box;
  line-height:98px;
  display: table; //must change this as well
}
.item{
  width:100px;
  height:94px;
  background-color:yellow;
  border:1px solid green;
  box-sizing:border-box;
  vertical-align:middle;
  display:table-cell; //update display type
}
person Andrea    schedule 07.10.2015
comment
но если у меня есть элементы разной высоты, и я действительно хочу, чтобы они были центрированы, это не работает - person Will Jenkins; 07.10.2015
comment
Это предполагает, что средний ‹div› всегда будет составлять 100% от внешнего div. Внешние элементы и элементы могут быть гибкими по высоте. Это неправильно? - person Andrea; 07.10.2015
comment
Вот codepen с двумя элементами разной высоты: codepen.io/anon/pen/avWrzB - person Will Jenkins; 07.10.2015
comment
ах, попался. Не ожидал нескольких внутренних div - упс :) - person Andrea; 07.10.2015
comment
возможно, добавьте это ограничение к вашему вопросу и примеру: я не буду единственным человеком, который не расширит это должным образом! - person Andrea; 07.10.2015