Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Position badge over corner of image automatically

I have a layout where images "float" within a certain area. The layout looks like this:

Layout Example

The source like this:

<div class="free_tile">
  <a class="img_container canonical" href="/photos/10">
    <img class="canonical" src="http://s3.amazonaws.com/t4e-development/photos/1/10/andrew_burleson_10_tile.jpg?1303238025" alt="Andrew_burleson_10_tile">
    <!-- EDIT: I am aware that I can put the badge here. See the edit notes and image below. -->
  </a>
  <div class="location">Houston</div>
  <div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>

The CSS looks like this (in SCSS):

div.free_tile { width: 176px; height: 206px; float: left; margin: 0 20px 20px 0; position: relative;
  &.last { margin: 0 0 20px 0; }
  a.img_container { display: block; width: 176px; height: 158px; text-align: center; line-height: 156px; margin-bottom: 10px; }
  img { margin: 0; border: 1px solid $dark3; display: inline-block; vertical-align: middle; @include boxShadow;
    &.canonical { border: 1px solid $transect; }
  }
  .location, .taxonomy { width: 176px; }
  .location { font-weight: 700; }
  .taxonomy { line-height: 10px; font-size: 10px; text-transform: uppercase; height: 20px; overflow: hidden; }
}
div.transect_badge { height: 20px; width: 20px; background: url('/images/transect-badge.png'); }

So, basically the images are sitting vertically-aligned middle and text-aligned center, and they have a maximum width of 176 and max height of 158, but they're cropped to maintain the original aspect ratio so the actual top corner of each image falls differently depending on which image it is.

I have a badge that I'd like to put in the top corner of certain images (when the image is "canonical"). You see the style for this above (div.transect_badge).

The problem, of course, is I don't know where the top corner of the image will be so I can't hardcode the position via CSS.

I assume that I'll need to do this via jQuery or something. So, I started with a jQuery method to automatically append the badge div to any canonical images. That works fine, but I can't figure out how to position it over the top left corner.

How can this be done? (ideally using just HTML and CSS, but realistically using JS/jQuery)

--EDIT-- Here's the problem: The image is floating inside a container, so the corner of the image might fall anywhere inside the outer limits of the container. Here's an example of what happens if I try to use position:absolute; top:0; left:0 inside the same container the image is bound by: The problem

like image 408
Andrew Avatar asked May 21 '11 20:05

Andrew


2 Answers

It took some tryouts, but here it is: the size independent image badge positioner.

HTML:

<div class="tile">
    <span class="photo">
        <a href=""><img src="/photos/10.jpg" alt="10" /><ins></ins></a>
    </span>
    <p class="location">Houston</p>
    <p class="taxonomy">T6 | Conduit | Infrastructure</p>        
</div>

CSS:

.tile {
    float: left;
    width: 176px;
    height: 206px;
    margin: 0 20px 20px 0;
 }
.photo {
    display: block;
    width: 176px;
    height: 158px;
    text-align: center;
    line-height: 158px;
    margin-bottom: 10px;
}
a {
    display: inline-block;
    position: relative;
    line-height: 0;
}
img {
    border: none;
    vertical-align: middle;
}
ins {
    background: url('/images/badge.png') no-repeat 0 0;
    position: absolute;
    left: 0;
    top: 0;
    width: 20px;
    height: 20px;
}

Example:

In previous less successful attempts (see edit history), the problem was getting the image vertically centered ánd to get its parent the same size (in order to position the badge in the top-left of that parent). As inline element that parent doesn't care about the height of its contents and thus remains to small, but as block element it stretches to hís parent's size and thus got to high, see demonstration fiddle. The trick seems to be to give that parent a very small line-height (e.g. 0) and display it as an inline-block. That way the parent will grow according to its childs.

Tested in Opera 11, Chrome 11, IE8, IE9, FF4 and Safari 5 with all DTD's. IE7 fails, but a center-top alignment of the photo with badge at the right position isn't that bad at all. Works also for IE7 now because I deleted the spaces in the markup within the a tag. Haha, how weird!

like image 95
NGLN Avatar answered Oct 18 '22 22:10

NGLN


EDIT3: This solution is very similar to my original solution. I didn't really look at your code much so I should have noticed this earlier. Your a tag is already wrapping each image so you can just add the badge in there and position it absolute. The a tag doesn't need width/height. Also you must add the badge image at the beginning of your a tag.

Demo: http://jsfiddle.net/wdm954/czxj2/1/

div.free_tile {
    width: 176px;
    height: 206px;
    float: left;
}

a.img_container {
    display: block;
    margin-bottom: 10px;
}

span.transect_badge {
    display:block;
    position: absolute;
    height: 20px;
    width: 20px;
    background-image: url('/images/transect-badge.png');
}

HTML...

<a class="img_container canonical" href="/photos/10">
    <span class="transect_badge"></span>
    <img class="canonical" src="path/to/img" />
</a>

Other solutions...

In my code I'm using SPAN tags so simulate images, but it's the same idea. The badge image, when positioned absolute, will create the desired effect.

Demo: http://jsfiddle.net/wdm954/62faE/

EDIT: In the case that you need jQuery to position. This should work (where .box is your container and .corner is the badge image)...

$('.box').each(function() {
    $(this).find('.corner')
        .css('margin-top', ( $(this).width() - $(this).find('.img').width() ) / 2);
    $(this).find('.corner')
        .css('margin-left', ( $(this).height() - $(this).find('.img').height() ) / 2);
});

EDIT2: Another solution would be to wrap each image with a new container. You would have to move the code that you use to center each image to the class of the new wrapping container.

Demo: http://jsfiddle.net/wdm954/62faE/1/

$('.img').wrap('<span class="imgwrap" />');
$('.imgwrap').prepend('<span class="badge" />');

Technically you can just add something like this to your HTML though without using jQuery to insert it.

like image 26
wdm Avatar answered Oct 18 '22 21:10

wdm