9

Before we start:
Please don't close this as a duplicate of another question. I just searched here on Stackoverflow without finding that exact case.

The closest is I believe this question. Still, the replies given there don't really work for me, I believe because the paragraph is set position: absolute;.

Thats the HTML:

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

And the 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;
}

Fiddle: http://jsfiddle.net/DpVjZ/

vertical-align: middle; just bumps the text a tiny bit away from the top, but not really in the middle.
Setting the span position: absolute; and then applying top: 50%; and then margin-top: -x%; won't work because the height of the span is not known as it is dynamic content.
Although the linked question states that this is bad practice, I also tried the display: table-cell approach without any result. Please help me.

Community
  • 1
  • 1
Sven
  • 12,997
  • 27
  • 90
  • 148
  • Why do you have a block-level element inside a list item? Do you not think that's why you're having problems? – Jezen Thomas Jan 21 '13 at 18:25
  • As far as I know, the only list elements that aren't allowed to contain block-level elements are `dt`. – Sven Jan 21 '13 at 18:27
  • You could of course just set the list item to `display:block;`. I think you're approaching the problem from the wrong end of the telescope. What are you trying to achieve? Visually, what is it supposed to look like? Is the text supposed to be on top of the image? – Jezen Thomas Jan 21 '13 at 18:29
  • @JezenThomas Yes, the text is supposed to be on top of the image, centered vertically and horizontally. Setting the list item to `display: block;` does nothing for me, could you please elaborate it a bit more? – Sven Jan 21 '13 at 18:34
  • The image and text are unknown sizes I assume? – user1934286 Jan 21 '13 at 18:45

3 Answers3

10

Without hard-coding an assumed height for the text or image, I (unfortunately) can't solve this in less than 3 layers:

  1. Establish absolute positioning
  2. Establish table layout
  3. Establish table-cell layout and vertical-align: middle

Combining 1 and 2 seems to prevent height: 100% from working for reasons unknown to me. I think the rejection of table-cell layout seems to be a misappropriation of the old "don't use tables for layouts" meme; CSS is for layout so this is not misusing the element semantics. (Although unfortunately it requires semantically meaningless divs.)

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

user1934286
  • 1,732
  • 3
  • 23
  • 42
svachalek
  • 1,166
  • 8
  • 18
  • +1 This is a bit complicated but does account for unknown widths and heights. I edited your post to text-align:center the p tag and updated the fiddle and cleaned up the code. – user1934286 Feb 08 '13 at 08:56
2

Get rid of the p tag. You already have it in a li anyway.

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>

Tested on window IE9 and Chrome.

Don't know if it was for the demo or not but if you want the red shade over the image make a class for a span tag then insert a new span with the class.

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>
user1934286
  • 1,732
  • 3
  • 23
  • 42
  • Thanks! I like the way your solution delivers a great result and is easy to understand, too. – Sven Jan 21 '13 at 19:51
  • 3
    The top: 46% is hard-coding a guess about the height of the span; it is not centered for an arbitrary span. – svachalek Jan 21 '13 at 20:21
  • @svachalek Yes, it is a one-line-of-text solution. Multi-line solutions are much more complicated. It is centered for an arbitrary image size. It will also work were the span and image are known. – user1934286 Jan 22 '13 at 04:25
0

Vertical aligning is a tricky thing in CSS, but not hard to accomplish when u are familiar with css tables.

<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 Top place this element on top another just make the #wrapper position: fixed; height: 100%; width: 100%; left: 0px; top: 0px; or withing an element use position: absolute;

Chris Visser
  • 1,607
  • 12
  • 24