1

This is driving me crazy and I don't think it is even possible at this point, but I would like to consult the Internet Gods before I give up.

Visual representation of what I want:

Visual representation of what I want

I want the text to align at the top-left of the container, and the image to align itself in the center of the space that is leftover after (if) the text wraps.

Please see demo

I'm using flexbox and margin: 0 auto to get the centering I want, and position: absolute on the h2 element works fine if the image is long, but looks terrible with tall image.

Is there some flexbox magic I can use to take into account the height of the dynamically loaded h2 element and make the image centered within the rest of the free space?

Constraints:

  • The parent container must be 200px by 200px.
  • Image can not be distorted (stretched).
andreas
  • 16,357
  • 12
  • 72
  • 76
Kevin LeStarge
  • 8,142
  • 4
  • 21
  • 34
  • Hi Kevin, maybe you already know this- you have issues to tackle here... the image will either be distorted / it will overflow the `container` as you would be [constraining both dimensions of the image here](http://stackoverflow.com/questions/39289576/css-image-resize-issue/39289947#39289947))... also it is difficult to center the image I guess... – kukkuz Sep 15 '16 at 01:59
  • @kukkuz I don't think I have a problem with distortion or overflow of the image. I am not constraining both dimensions in my demo example. The main question I have is if it is possible for the CSS to know the height of an element that has wrapped text causing height to increase. – Kevin LeStarge Sep 15 '16 at 02:51

3 Answers3

1

I was able to find my own solution by combining @Claudio's table idea and some position absolute magic.

Here is the solution demo with both tall and wide images: DEMO

HTML:

<div class="main-box">
  <table>
    <tr>
        <td class="box-title">
            <h2>
                My title here. :) add some more text
            </h2>
        </td>
    </tr>
    <tr>
        <td class="box-img">
            <img src="//i.imgur.com/NOzWHFF.png" alt="Google">
        </td>
    </tr>
  </table>
</div>
<div class="main-box">
  <table>
    <tr>
        <td class="box-title">
            <h2>
                My title here. :) add some more text
            </h2>
        </td>
    </tr>
    <tr>
        <td class="box-img">
            <img src="https://upload.wikimedia.org/wikipedia/commons/e/e0/Long_March_2D_launching_VRSS-1.jpg" alt="Google">
        </td>
    </tr>
  </table>
</div>

CSS:

*{
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.main-box{
    width: 200px;
    height: 200px;
    border: 2px solid #000;
    background-color: #FFF;
    position: relative;
}
.main-box table{
    width: 100%;
    height: 100%;
    border-spacing:0;
}
.main-box .box-title{
    background-color: rgba(0, 0, 0, 0.1);
    height: 1px;
}
.main-box .box-title h2{
    margin: 0;
    padding: 5px;
    font-family: Helvetica, Arial, sans-serif;
}
.main-box .box-img{
    text-align: center;
    vertical-align: middle;
    padding: 5px;
    position: relative;
}
.main-box .box-img img{
    max-width: 100%;
    max-height: 100%;
    margin: auto;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
}
Kevin LeStarge
  • 8,142
  • 4
  • 21
  • 34
  • You don't actually have to use `tables`, you can use `display: table-cell` and `table-row` in your CSS on elements such as divs... https://css-tricks.com/almanac/properties/d/display/ – random_user_name Sep 19 '16 at 21:51
0

It is not impossible, nothing is inpossible. :)

So, I was trying hard do something that work, and after spend much time thinking and testing... The solution!! Unfortunately, is using table (I'm sorry, but its the only way to do it only with HTML and CSS).

The base of the structure is simple. We have a main div with the dimentions that we want (200px X 200px). Inside it, we have a table with two lines (One to our title, and the other to our beautiful img)

After we style the structure, removing border-spacing... removing margin of h2 and things like that. We need (here is the trick) apply height: 1px; to our first line of the table (The line of the title).

Why height: 1px;?

Well, the table element applies its size following the content. We applying height: 1px;, the line will not get literally with 1px of height, it means that the line will take the less height as possible respecting the content. Doing so, the other line (the line of the image) will get all the leftover space to it, and after it's only apply vertical-align: middle; and text-align: center; in order to centering the image.

After all the explanation... the code:

https://jsfiddle.net/u61y62r8/

I hope it can help you. :)

Claudio Bonfati
  • 493
  • 3
  • 14
  • thank you for the table idea. It works great for for a horizontally long image, but the vertically tall image is not staying within the box: https://jsfiddle.net/u61y62r8/1/ Any ideas on how to solve this problem? – Kevin LeStarge Sep 15 '16 at 15:08
  • Just a tip: when you have a complement to an answer, you **must** comment it, and do **'make'** an another answer. – Claudio Bonfati Sep 28 '16 at 15:00
0

That should do the trick.

<div class="container">
  <div class="inner">
    <h2>This is a title</h2>
  </div>

  <div class="inner-2">
    <img src="https://thesingleplayermode.files.wordpress.com/2013/05/pokemon-banner.jpg">
  </div> 
</div>

CSS:

.inner { 
    width: 100%;
    height: 50px;
}

.inner-2 {
    height: calc(100% - 50px);
    display: flex;
    justify-content: center;
    align-items: center;
}

.img {
    max-width: 100%;
    max-height: 100%;
}
Moe H.
  • 11
  • 1
  • It is not a good way, because you are setting the height of box title, and It'll came dynamically, as you can read on this question's title. If the content came with a little bit more characters (and break into two lines), your code will not work. – Claudio Bonfati Sep 15 '16 at 10:14
  • Claudio is right, I don't want a fixed height of 50px. Thanks for the suggestion tho! – Kevin LeStarge Sep 15 '16 at 15:16