Position badge over corner of image automatically - javascript

I have a layout where images "float" within a certain area. The layout looks like this:
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:

It took some tryouts, but here it is: the size independent image badge positioner.
HTML:
<div class="tile">
<span class="photo">
<img src="/photos/10.jpg" alt="10" /><ins></ins>
</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!

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.

Use an element other than <div>, e.g. <span> and put it inside your <a> element after the <img> element. Then, give the <a> element position:relative; and the <span> gets position:absolute; top:0px; left:0px;. That is, if you don't mind the badge also being part of the same link - but it's the easiest way. Also, the reason for using <span> is to keep your HTML4 valid, <div> would still be HTML5 valid, however.

I did find one solution using jQuery. I don't prefer this because it noticably impacts page loading, but it is acceptable if nothing else will work. I'm more interested in NGLN's idea which seems promising but I haven't entirely figured out yet. However, since this thread has picked up a lot of traffic I thought I'd post one solution that I came up with for future readers to consider:
Given this markup:
<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">
<span class="transect-badge"></span>
</a>
<div class="location">Houston</div>
<div class="taxonomy"> T6 | Conduit | Infrastructure </div>
</div>
Same CSS as in question except:
span.transect-badge { display: block; height: 20px; width: 20px; position: absolute; background: url('/images/transect-badge.png'); }
Then this jQuery solves the problem:
$(function() {
$('img.canonical').load( function() {
var position = $(this).position();
$(this).next().css({ 'top': position.top+1, 'left': position.left+1 });
});
});
Like I said, though, this incurs noticeable run-time on the client end, so I'd prefer to use a non JS solution if I can. I'll continue to leave this question open while I test out and give feedback on the other solutions offered, with hopes of finding one of them workable without JS.

Related

need help removing an IMG and replacing it with text in its position with javascript

Im working on a project and a part of it is making an image disapear on hover, and replace that with text in the same location! I have to do it through javascript.
im very new to front end web development so any help would be great!
.main-img1{
height: 400px;
width: 600px;
margin-top: 80px;
background-size: 600px 400px;
box-shadow: 10px 10px 5px rgb(24, 22, 22);
position: relative;
text-align: center;
font-size: 25px;
color: black;
border-radius: 50px;
}
.img1-text{
display: none;
position: absolute;
bottom: 8px;
left: 150px;
<section class="main-body">
<div>
<img class="main-img1" src="img/automotive.jpg">
<h1 class="img1-text" id="img1text"> Here are some samples of my automotive photography! I specialize in "Rolling Shots" which are caputring a vehicle in motion, while the background and foreground show the motion.</h1>
</div>
You can replace any element using the "magical" outerHTML like this...
First, I gave your image an ID to make javascript operations easier...
<img id="I" class="main-img1" src="img/automotive.jpg">
Now replace the image with a paragraph of text...
I.outerHTML='<p>Well what do you know!</p>';
For easy one-line HTML...
<img onmouseover="this.outerHTML='<p>Well what do you know!</p>';" class="main-img1" src="img/automotive.jpg">
First off, this is a very odd thing to do in Javascript. Usually hover states, appearing and disappearing, etc. are handled by CSS.
to do it in js you have to add a mouseover event listener to the image to execute a function to grab the element you want to disappear, add a css class to apply "display: none" to it, grab the element you want to appear and remove a class that adds "display: none" from it.
assuming you have a 'display-none' class on your text element that applies 'display: none' to it, you can do this:
const image = document.querySelector('.main-image1')
const text = document.querySelector('.img1-text')
image.addEventListener('mouseover', () => {
image.classList.add('display-none')
text.classList.remove('display-none')
}
if you were to do this with css its as simple as
.image {
z-index: 2;
}
.image:hover {
display: none;
}
.text {
z-index: 1;
}
that way the text is set behind the image and when you hover over the image it disappears. This also has the benefit of when you take your cursor off the image for the image to reappear where js will need to be told explicitly to do that.

Smart DOM Insertion (preserve styles of child element)

This is a very odd question, of which I am fairly confident I already know the answer, however, before I go ahead with the fix that I am trying to avoid, I thought it was worth asking others as you may see this from a different angle
I am currently writing a plugin that takes a certain element (can be any DOM node), and wraps it with a div. The purpose of the plugin is to add a 'blinds' effect to elements which can then be used to reveal the element on scroll.
Note: Wrapping with a div is absolutely essential to the functionality I am implementing.
My question, quite simply, is anybody aware of a smart way to preserve the styles from the element being wrapped and ensure it visually remains the same as it was before the div wrapping, and, whilst retaining the dimensions so another div can be inserted within the wrapper and be the same dimensions of it's sibling.
See this very basic example (before and after - notice the blue blind):
.test {
display: flex;
flex-flow: column;
height: 200px;
text-align: center;
}
.test:nth-child(1) {
background: #999;
}
.test:nth-child(2) {
background: #666;
}
.test > * {
flex: 0 1 auto;
}
.test h1 {
margin: auto 0 0;
color: #fff;
}
.test p {
margin: 0 0 auto;
color: #fff;
}
.test-wrapper {
position: relative;
width: max-content; /* Fix for example purposes */
margin: 0 auto; /* Fix for example purposes */
}
.test-wrapper .blind {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: blue;
opacity: 0.5;
}
<div class="test">
<h1>Before wrapper inserted</h1>
<p>Some description</p>
</div>
<div class="test">
<div class="test-wrapper">
<div class="blind"></div>
<h1>After wrapper inserted</h1>
</div>
<p>Some description</p>
</div>
Before answering, these are the solutions I am trying to avoid:
'copying' or 'moving' the styles (or certain styles) from the child to the parent as this is likely to cause a huge mess... Open to suggestions though
Defining styles for test-wrapper in the site's CSS as test-wrapper is a plugin specific element.
The obvious, and very easy, solution is to just define the styles for the wrapper instead of the child in my CSS (SCSS). I appreciate this may be the only way, but I ideally want to avoid this as what I am building is a plugin and I want the HTML/CSS to work with and without the element wrapper in place.

"float" a DIV to bottom of parent DIV not working. (Using Pos: rel, Bottom 0 etc)

Trying to get a DIV to "float" to the bottom of the div its in. I've got the position set to relative on the parent div and kid, and bottom to 0 on the kid; but it still just sits at the top in the middle.
Parent DIV:
.detailsContainer
{
width: 100%;
height: 30%;
overflow: hidden;
position: relative;
background-color: blue;
}
Kid DIV
.obutton
{
text-align: center;
font-weight: bold;
width: 80%;
height: 29px;
background:rgba(204,204,204,0);
position:relative;
bottom: 0;
display: inline-block;
color: #666;
}
Current actual setup:
<div class="detailsContainer">
<a href="javascript:unhide(\'BookDetails'.$row->BookID.'\');">
<div class="detailview"><b>Book Details<br></a></div>
<div id="BookDetails'.$row->BookID.'" class="hidden">
<table>
<tr><td>Total Stock </td><td>'.$row->TotalStock.'</td>
<td>Current Stock</td><td>'.$row->CurrentStock.'</td></tr>
<tr><td>Awards </td><td>'.$row->Awards.'</td>
<td>Film</td><td>'.$row->Film.'</td></tr>
</table>
</div>
';?>
<br><center><a href = "javascript:void(0)"
onclick = "document.getElementById('light').style.display='block';document.getElementById('fade').style.display='block'">
<div class= "obutton feature2">Reserve Book</div></a></center>
<div id="light2" class="white_content"></div>
<div id="fade" class="black_overlay"></div>
</div>
Its kind of a lot to post for this, but want to make sure nothing is interfering that you guys might spot. It jumps out of php near the bottom, I'll post the entire article if you think the issue might be else where.
I tried to make a jsfiddle of it, but there is so much php and variables that by time I gutted it, it'd just be 2 normal divs, having lost its uniqueness and the issue will probably have been deleted.
Thanks -Tom
.obutton position needs to be absolute... for bottom to work the way you're intending.

half transparent div above image

I have a PNG image of a character, and I want something like that:
http://www.swfcabin.com/open/1364482220.
If someone clicks on a part of the character's body, it'll be "selected".
The question is - how can I do that. I don't want to use more images (because I have multiple characters), I want to use CSS only.
I tried this: http://jsfiddle.net/eRVpL/, but the green background appear above the white background, and I want it to be only above the character.
The code:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png" />
<span></span>
</div>
<style>
.character { width: 210px;display: inline-block; vertical-align: middle; position: relative; }
.character > span {
display: block;
width: 200px;
height: 30%;
background: rgb(160, 255, 97);
opacity: .3;
position: absolute;
top: 0;
}
img {
max-width: 200px;
}
</style>
You can make this work with CSS masks, although they are currently only supported in WebKit browsers: http://caniuse.com/#feat=css-masks
http://jsfiddle.net/eRVpL/3/
HTML:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png">
<div class="green-mask"></div>
</div>
CSS:
.green-mask {
height: 200px;
width: 508px;
background: rgb(160, 255, 97);
opacity: .3;
position: absolute;
top: 0;
-webkit-mask-image: url(http://img194.imageshack.us/img194/3854/goldgladiator.png);
}
If you want to offset the elements like in the GIF you linked, put the colored background on children of the masked div:
http://jsfiddle.net/eRVpL/11/
HTML:
<div class="character">
<img src="http://img194.imageshack.us/img194/3854/goldgladiator.png">
<div class="green-mask">
<div class="filler"></div>
</div>
</div>
CSS:
.filler {
background-color: rgba(160, 255, 97, 0.3);
height: 200px;
margin-top: 200px;
width: 100%;
}
.green-mask {
position: absolute;
width: 508px;
top: 0;
-webkit-mask-image: url(http://img194.imageshack.us/img194/3854/goldgladiator.png);
}
And this one's just for fun: http://jsfiddle.net/eRVpL/23/ Try clicking the character. It uses checkboxes and labels with no JavaScript.
Currently there is no CSS-only means of accomplishing this. There is a specification for compositing and blending with CSS that's in the works, but it currently isn't being supported enough to be used in a product just yet. You can read-up on the spec here: http://www.w3.org/TR/compositing/
With this specification, we could set the blend-mode of your element to "screen", "overlay", or "lighten" which would make your character be green but the background would remain white. Unfortunately, this isn't possible just yet.
The best way would be, as jcubic said in one of your comments, "You need to use a mask, image that will be exactly the same but the character transparent".
Good luck!
Try using z-index for getting what you want. You'll be able to make the object appear to be hidden on a certain page until you bring it up with a mouse click or hover. You can also make a green image that's basically a silhouette and cut it up into three different portions, give them a little bit of exact positioning (each with their own division) and have a little z-index, then you've got yourself that. You might also want to cut up the actual character into three parts to make it easier.

Clicking on a div placed over an image in IE

I have an image which may have some divs over it (specifying certain selections within that image). These divs are supposed to be clickable. Something like that:
#divOuter { width: 500px; height: 500px; border: 2px solid #0000FF; position: relative; }
#divInner { width: 100px; height: 100px; border: 2px solid #00FF00; position: absolute; cursor: pointer; top: 20px; left: 20px; }
<div id="divOuter">
<img src="SomeImage.jpg" />
<div id="divInner"></div>
</div>
$("#divOuter").click(function() { alert("divOuter"); });
$("#divInner").click(function() { alert("divInner"); });
In chrome and FF it works as expected (pointer appears over the div, and clicking it alerts "divInner" and then "divOuter").
However, in IE8 it didn't - I got the same behavior only when hovering/clicking on the inner div borders. When clicking inside that div, only "divOuter" was alerted.
How can this be fixed?
Here's a hack: add an CHAR like "O" to the inner div, and then give it an enormous font size(depends on the area you want to span over):
#divInner { /* ... */; font-size: 1000px; color: transparent; }
(Also set "overflow: hidden" I think.)
IE likes there to be something there in the container for the click to affect. If it's just completely empty, it ignores clicks.
a fiddle: https://jsfiddle.net/cbnk8wrk/1/ (watch in IE!)
I had the same problem with an unordered list, see Getting unordered list in front of image slide-show in IE8, IE7 and probably IE6
The solution : give the div a background color and make it transparent with a filter.
Adding an 1x1 px transparent background gif to the div is also working.
#divInner { background: url(/images/transparent.gif); }

Categories

Resources