CSS - выравнивание текста по вертикали в абзаце с абсолютным позиционированием

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

Ближе всего я считаю этот вопрос. Тем не менее, приведенные там ответы меня не очень устраивают, я полагаю, потому что абзац установлен position: absolute;.

Это HTML:

<ul>
    <li><img src="http://www.placehold.it/300x200" /><p><span>Lorem Ipsum</span></p></li>
</ul>

И CSS:

li {
  position: relative;
  float: left;
  overflow: hidden;
}

img {
  width: 100%;
  vertical-align: middle;
}

p {
  background-color: rgba(255, 0, 0, .3);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

span {
    background-color: rgba(0, 255, 0, .3);
    vertical-align: middle;
}

Скрипт: http://jsfiddle.net/DpVjZ/

vertical-align: middle; просто смещает текст немного вверх, но не посередине.
Установка интервала position: absolute;, а затем применение top: 50%;, а затем margin-top: -x%; не сработает, поскольку высота интервала неизвестна сама по себе. динамическое содержимое.
Хотя в связанном вопросе говорится, что это плохая практика, я также попробовал подход display: table-cell без каких-либо результатов. Пожалуйста помогите.


person Sven    schedule 21.01.2013    source источник
comment
Почему у вас есть элемент уровня блока внутри элемента списка? Ты не думаешь, что поэтому у тебя проблемы?   -  person Jezen Thomas    schedule 21.01.2013
comment
Насколько мне известно, единственными элементами списка, которым не разрешено содержать элементы уровня блока, являются dt.   -  person Sven    schedule 21.01.2013
comment
Конечно, вы можете просто установить элемент списка на display:block;. Мне кажется, вы подходите к проблеме не с того конца телескопа. Чего вы пытаетесь достичь? Визуально, как это должно выглядеть? Текст должен быть поверх изображения?   -  person Jezen Thomas    schedule 21.01.2013
comment
@JezenThomas Да, текст должен быть поверх изображения, центрирован по вертикали и горизонтали. Установка элемента списка на display: block; ничего не дает для меня, не могли бы вы уточнить это немного подробнее?   -  person Sven    schedule 21.01.2013
comment
Изображение и текст неизвестных размеров, я полагаю?   -  person 1934286    schedule 21.01.2013


Ответы (3)


Избавьтесь от тега p. В любом случае, у вас уже есть это в ли.

css

li {
position: relative;
float: left;
overflow: hidden;
}

img {
width: 100%;
height: 100%;
}

span {
background-color: rgba(0, 255, 0, .3);
position: absolute;
text-align:center;
width: 100%;
top:46%;
}

HTML

<ul>
<li><span>Lorem Ipsum</span><img src="http://www.placehold.it/300x200" /></li>
</ul>

Протестировано в окне IE9 и Chrome.

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

span.text {
background-color: rgba(0, 255, 0, .3);
position: absolute;
text-align:center;
width: 100%;
top:46%;
}

span.redshade {
background-color: rgba(255, 0, 0, .3);
width: 100%;
height: 100%;

<ul>
<li><span class="redshade">&nbsp;</span><span class="text">Lorem Ipsum</span><img src="http://www.placehold.it/300x200" /></li>
</ul>
person 1934286    schedule 21.01.2013
comment
Спасибо! Мне нравится, как ваше решение дает отличный результат и легко для понимания. - person Sven; 21.01.2013
comment
Верх: 46% жестко запрограммировали предположение о высоте пролета; он не центрирован для произвольного диапазона. - person svachalek; 22.01.2013
comment
@svachalek Да, это решение для одной строки текста. Многострочные решения намного сложнее. Центрируется для произвольного размера изображения. Это также будет работать, если известны диапазон и изображение. - person 1934286; 22.01.2013
comment
@Sven Спасибо за выбор. - person 1934286; 22.01.2013

Без жесткого кодирования предполагаемой высоты текста или изображения я (к сожалению) не могу решить это менее чем за 3 слоя:

  1. Установить абсолютное позиционирование
  2. Установить схему таблицы
  3. Установите макет ячейки таблицы и выровняйте по вертикали: посередине

Сочетание 1 и 2, похоже, предотвращает работу height: 100% по неизвестным мне причинам. Я думаю, что отказ от макета таблицы-ячейки кажется незаконным присвоением старого мема «не используйте таблицы для макетов»; CSS предназначен для макета, так что это не неправильное использование семантики элемента. (Хотя, к сожалению, для этого требуются семантически бессмысленные элементы div.)

<ul>
<li>
    <img src="http://www.placehold.it/300x200" />
    <div class="absolute">
        <div class="table">
            <div class="middle">
                <p><span>Lorem Ipsum</span>
                </p>
            </div>
        </div>
    </div>
</li>
</ul>


li {
    position: relative;
    float: left;
    overflow: hidden;
}
img {
    width: 100%;
}
.absolute, .table, .middle {
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
.absolute {
    position: absolute;
}
.table {
    display: table;
}
.middle {
    display: table-cell;
    vertical-align: middle;
}
p {
    background-color: rgba(255, 0, 0, .3);
}
span {
    background-color: rgba(0, 255, 0, .3);
}

http://jsfiddle.net/svachalek/vTGxx/4/

person svachalek    schedule 21.01.2013
comment
+1 Это немного сложно, но учитывает неизвестную ширину и высоту. Я отредактировал ваше сообщение, выровняв текст: отцентрируйте тег p, обновил скрипку и очистил код. - person 1934286; 08.02.2013

Выравнивание по вертикали — сложная вещь в CSS, но ее несложно выполнить, если вы знакомы с таблицами CSS.

<style>
      html, body, #wrapper { height: 100%; }
      #wrapper { display: table; width: 100%; } /* Create space */
      #wrapper > * { display: table-cell; vertical-align: middle; } /* table-cells can be verticaly aligned! */
      #wrapper > * > .container { display: block; margin: auto; width: 600px; border: 1px solid #000000; } /* Horizontal align */
</style>

<div id="wrapper">
  <section id="main">
    <div class="container">
      <p>
        I'm centered in a fluid layout! :D
      </p>
    </div>
  </section>
</div>

EDIT Сверху поместите этот элемент поверх другого, просто установите #wrapper position: fixed; высота: 100%; ширина: 100%; слева: 0px; верх: 0px; или внутри элемента используйте position: absolute;

person Chris Visser    schedule 21.01.2013