Text on Image Mouseover - CSS Positioning - css

I am using this fork code to display text on mouseover of an image.
http://codepen.io/anon/pen/hxqoe
HTML
<img src="http://placekitten.com/150" alt="some text" />
<img src="http://placekitten.com/150" alt="more text" />
<img src="http://placekitten.com/150" alt="third text" />
<div id="text"></div>
CSS
div {
display: none;
position: absolute;
}
img:hover + div {
display: block;
}
JQUERY
$('img').hover(function() {
$('div').html($(this).attr('alt')).fadeIn(200);
}, function() {
$('div').html('');
});
I am looking for the div text to be displayed inside each image instead of a stationary div.
Any ideas?

You actually don't need jQuery for this. It can easily be achieved with pure CSS.
In this example, I use the :after pseudo element to add the content from the alt attribute of the parent div. You can add whatever styling you want..
jsFiddle here - Updated to include a fade
HTML - pretty simple
<div alt="...">
<img src="..."/>
</div>
CSS
div {
position: relative;
display: inline-block;
}
div:after {
content: attr(alt);
height: 100%;
background: rgba(0, 0, 0, .5);
border: 10px solid red;
position: absolute;
top: 0px;
left: 0px;
display: inline-block;
box-sizing: border-box;
text-align: center;
color: white;
padding: 12px;
font-size: 20px;
opacity: 0;
transition: 1s all;
-webkit-transition: 1s all;
-moz-transition: 1s all;
}
div:hover:after {
opacity: 1;
}

Change your javascript to this:
$('img').hover(function() {
$('div').html($(this).attr('alt')).fadeIn(200);
$('div').css('left',$(this).offset().left + 'px');
$('div').css('top',$(this).offset().top + $(this).height() - 20 + 'px');
}, function() {
$('div').html('');
});
And that should do the trick.

I would wrap your images in some kind of wrapper and then use CSS for the hover effect (DEMO).
HTML:
<div class="img-wrapper">
<img src="http://placekitten.com/150" alt="some text 1" />
<div class="img-desc">some text 1</div>
</div>
CSS:
.img-wrapper {
position: relative;
display: inline;
}
.img-desc {
display: none;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
background: #FFF;
opacity: 0.6;
padding: 5px;
}
.img-wrapper:hover .img-desc{
display: block;
}
I added an alternative solution with additional css transition to the demo.
To get a transition just control the visibility with opacity:
.img-desc {
/*...*/
opacity: 0;
/*...*/
}
.img-wrapper:hover .img-desc{
opacity: 0.6;
transition: opacity 0.4s ease-in;
}

Related

css transition not working correctly in vuejs

I am trying to animate the slide in/out of my flyout however it doesn't transition but appear and disappear in the same place.
in chrome devtools the animation works if I tick/untick right: 0;
How can I slide in/out the flyout correctly?
<template>
<portal to="modalPortal">
<div
v-if="isMoreOffersFlyoutActive"
:id="id"
class="flyOut"
#click.self="sendCloseModal(true)">
<div
:class="['flyOut__container', {'flyOut__container--active': isMoreOffersFlyoutActive}]">
<div class="flyOut__buttonContainer">
<button
id="storeInfoClose"
class="flyOut__button"
#click="sendCloseModal(false)">
<icon
:scale="closeButtonIconScale"
name="close"
color="white" />
</button>
</div>
<div class="flyOut__content">
<slot />
</div>
</div>
</div>
</portal>
</template>
.flyOut {
position: fixed;
top: 0;
left: 0;
z-index: z("overlay");
display: flex;
justify-content: flex-end;
width: 100%;
height: 100%;
overflow: auto;
background-color: $black-alpha;
&__container {
position: relative;
z-index: z("modal");
right: -50%;
width: 50%;
height: 100%;
background-color: $white;
box-shadow: -2px 0 15px 5px rgba(0,0,0,0.2);
transition: right ease 0.5s;
&--active {
right: 0;
transition: right ease 0.5s;
background: #ff00ff;
}
}
There isn't really an issue with Vue here. The problem stems from trying to animate a position between two different units (or in your case units and no units). Changing right: 0; to right: 10%; would probably work.
All that said, PLEASE don't animate CSS position. It's not performant and causes the browser to reflow & repaint stuff. The better solution is to use css translate(). Here's an example...
.wrapper {
/* need a positioned container for SO's editor */
position: fixed;
top:0; right:0; bottom:0; left:0;
overflow:hidden;
}
.action{
margin: 30px;
font-size: 18px;
font-weight: bold;
cursor:pointer;
font-family: sans-serif;
}
.moved{
position: absolute;
/* put the element where you want it */
top:0;
right:0;
bottom:0;
width: 150px;
background: #333;
padding: 20px;
color: #fff;
/* use transform to move to a new position (100% of element width) */
transform: translatex(100%);
transition: transform 0.5s cubic-bezier(.47,1.64,.41,.8);
}
.action:hover+.moved {
transform: translatex(0);
}
<div class="wrapper">
<div class="action">Hover Me</div>
<div class="moved">Transformed element</div>
</div>

Display text overlay and apply image transparency on hover

I'm trying to make an image semitransparent on hover and display text that is otherwise set to display: none. Currently if you hover over an image, it becomes semi-transparent (.single-image:hover works), but the text doesn't appear. When the text was not set to display: none, it is positioned over the image in the bottom left-hand corner. I thought that since it is over the image, the hover pseudo-class would take effect. I also tried setting the z-index of .attribution to 1 but that didn't do anything.
<div className="image-container">
<a href={image.links.html} target="_blank" rel="noopener noreferrer">
<img className="single-image" src={image.urls.regular} alt="" />
<p className="attribution">Unsplash</p>
</a>
</div>
.image-container {
display: inline-block;
position: relative;
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
bottom: 20px;
left: 20px;
}
.attribution:hover {
display: block;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
}
.single-image:hover {
opacity: 0.7;
transition: 0.5s;
}
You should move the hover function to the parent div.
Change .attribution:hover to .image-container:hover .attribution and .single-image:hover to .image-container:hover .single-image.
Strangely enough, in order for this to work, you also need to add border or background-color to your parent div. (Here is why)
I added a transparent color background-color: rgba(0, 0, 0, 0);.
.image-container {
display: inline-block;
position: relative;
background-color: rgba(0, 0, 0, 0);
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
bottom: 20px;
left: 20px;
}
.image-container:hover .attribution {
display: block;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
}
.image-container:hover .single-image {
opacity: 0.7;
transition: 0.5s;
}
<div class="image-container">
<a href="#" target="_blank" rel="noopener noreferrer">
<img class="single-image" src="https://upload.wikimedia.org/wikipedia/commons/2/22/Turkish_Van_Cat.jpg" alt="" />
<p class="attribution">Kitten!</p>
</a>
</div>
.cont {
position: relative;
height: 150px;
width: 150px;
margin: 1em auto;
background-color: red;
}
.layer {
position: relative;
height: 150px;
width: 150px;
color: Transparent;
}
.layer:hover { color: white; }
.cont:hover { background-color: blue;}
<div class="cont">
<div class="layer">My cool Text</div>
</div>
Why did you not set the color of the font to transparent? it's easyer. see my little example (2 minutes workaround...)
Add a bit of javascript to make the text appear aswell as the image fade.
as only one element can be in hover state even if there ontop of each other.
unless you mess around with js you might be able to 'hack' a double hover state.
try;
<div className="image-container">
<a href={image.links.html} target="_blank" rel="noopener noreferrer">
<img className="single-image" src={image.urls.regular} alt="" />
<p className="attribution">Unsplash</p>
</a>
</div>
.image-container {
display: inline-block;
text-align:center;
position: relative;
z-index:1;
}
/* Text */
.attribution {
display: none;
color: white;
position: absolute;
z-index:3;
bottom: 20px;
left: 20px;
}
.single-image {
margin: 7px;
height: 350px;
width: 350px;
object-fit: cover;
z-index:2;
}
.single-image:hover {
opacity: 0.7;
transition:opacity 0.5s ease-in-out;
will-change:opacity;
}
<script>
document.addEventListener(DOMContentLoaded,(e)=>{
const img = document.getElementsByClassName('single-image')[0];
const attrib = document.getElementsByClassName('attribution')[0];
img.addEventListener('mouseover',(e)=>{
img.style.opacity = '0.7';
attrib.style.display = 'block';
});
});
</script>

Unable to prevent :hover from repeatedly firing

I've got the following code. When the user hovers over the div, it should drop and stay that way until the user has hovered off of the div. When on the div, even if you move your mouse a bit, the hover action keeps firing.
html
<div class="whitelabelfeatures">
<div class="box1 requirements responsibilities">
<div class="responsibilitiesbox">
<div class="responsibility">
<div class="section1">
Pricing
</div>
<div class="section1a">
Pricing test
</div>
</div>
</div>
</div>
</div>
css
.box1.requirements.responsibilities {
height: 300px;
overflow: hidden;
}
.responsibility .section1 {
background-color: #c2bbb1;
height: 300px;
color: white;
font-weight: 700;
position: relative;
z-index: 2;
transition: all .3s ease;
}
.responsibility .section1:hover {
transform: translateY(300px);
}
.responsibility .section1a {
position: absolute;
z-index: 1;
top: 0;
}
codepen
https://codepen.io/jasonhoward64/pen/YzKNxVN
Thanks!
You can use javascript here. Please see below code.
var targetDiv = document.getElementsByClassName("section1")[0];
targetDiv.addEventListener('mouseenter', function(){
targetDiv.classList.add('section1mouseover');
});
var testDiv = document.getElementsByClassName("section1a")[0];
testDiv.addEventListener('mouseenter', function(){
targetDiv.classList.remove('section1mouseover');
});
.box1.requirements.responsibilities {
height: 300px;
overflow: hidden;
}
.responsibility .section1 {
background-color: #c2bbb1;
height: 300px;
color: white;
font-weight: 700;
position: relative;
z-index: 2;
transition: all .3s ease;
}
.section1mouseover {
transform: translateY(300px);
}
.responsibility .section1a {
position: absolute;
z-index: 1;
top: 0;
}
<div class="whitelabelfeatures">
<div class="box1 requirements responsibilities">
<div class="responsibilitiesbox">
<div class="responsibility">
<div class="section1">
Pricing
</div>
<div class="section1a">
Pricing test
</div>
</div>
</div>
</div>
</div>
The problem is that your :hover needs to be actuated higher in the DOM. With your current code, when you hover over the .section1 element, once the CSS transform takes place and translates the .section1 element vertically, the cursor is both "off" and "over" the transforming element, which causes the :hover to trigger on and off in response.
So in your codepen, on line 17, change your hover to the parent element and it should work.
Instead of:
.responsibility .section1:hover, try .responsibility:hover .section1

Transition from sentence to one word

What I am trying to achieve is to animate an element width few words in the way that hovered word leaves in the center of the element and the rest smoothly goes out of the bounds. I would also keep it as clear as possible in HTML and not to use fixed pixel amount of margins/widths to position elements.
The very lousy sketch of what I have on my mind is here:
* {
transition: all 1.5s;
}
div {
min-width: 150px;
width: 30%;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
}
div:hover {
background: white;
word-spacing: 300px;
}
a:hover::after,
a:hover::before {
content: ' ';
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
Each word on hover should go to center (possibly not with those 'jumps' visible now when other words disapear). Do you have any ideas? I'm pretty sure that the way I try to follow with word-spacing is wrong.
The issue is that when increasing word spacing the text goes to new line and create this jump thing. So you may add white-space: nowrap and you can also use padding-left to push text and make it in the center :
div {
min-width: 150px;
width: 180px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
div:hover {
word-spacing: 80px;
padding-left: 80px;
background: white;
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
Actually the word spacing is applied to the div so you cannot apply hover on word. It's also easier to apply this technique on the first word as the second one will be hide with overflow, but am not sure how you can do the same with the second word with the use of word-spacing.
Here is another idea on how you can do without word-spacing. I used some padding animation and also pseudo element to hide the first word when hovering the second one.
div {
min-width: 150px;
width: 180px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.afirst,
.asecond {
position:relative;
display: inline-block;
transition: all 0.5s;
}
.afirst:hover {
padding: 0 44%;
background: white;
}
.asecond:hover {
padding: 0 50% 0 0;
background: white;
}
.asecond:hover::before {
content:" ";
position:absolute;
left:-50%;
width:50%;
top:0;
bottom:0;
z-index:99;
background:#fff;
}
<div>
<a class="afirst" href="">First</a> & <a class="asecond" href="">Second</a>
</div>
I think you can generalize this solution by using :before element in the left and :after element in the right to hide everything else.
Here is an example with multiple word (but not giving center alignement correctly, still need improvement) :
div {
min-width: 150px;
height: 25px;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.word {
position: relative;
display: inline-block;
transition: all 0.5s;
}
.word:hover {
background: white;
padding: 0 40%;
}
.word:hover::before {
content: " ";
position: absolute;
left: -50%;
width: 50%;
top: 0;
bottom: 0;
z-index: 99;
background: #fff;
}
.word:hover::after {
content: " ";
position: absolute;
right: -50%;
width: 50%;
top: 0;
bottom: 0;
z-index: 99;
background: #fff;
}
<div>
<a class="word" href="">First</a> &
<a class="word" href="">Second</a> &
<a class="word" href="">third</a> &
<a class="word" href="">Fourth</a>
</div>
Another solution with perfect centering but less animation for the other words :
div {
position:relative;
height: 25px;
width:500px;
margin:0 auto;
line-height: 25px;
background: orange;
text-align: center;
overflow: hidden;
transition: all 0.5s;
box-sizing: border-box;
white-space: nowrap;
}
.word {
position: relative;
z-index:9;
display: inline-block;
transition: all 0.5s;
}
.word:hover {
position:absolute;
right:0;
left:0;
top:0;
bottom:0;
text-align:center;
background: white;
z-index:99;
}
<div>
<a class="word" href="">First</a> &
<a class="word" href="">Second</a> &
<a class="word" href="">third</a> &
<a class="word" href="">Fourth</a>
</div>
This version uses Flex Box, accommodates multiple items, and does not use fixed widths.
The trouble I kept having playing around with this was centering items without using fixed widths. Especially those that were later in line and trying to push items to the left.
Solution: flex box order.
You can set the order of flex items numerically, so simply setting it to -1 on hover puts the hovered item first in the list so you eliminate the issue of flexing items leftward.
The animation may not be as fluid as you're looking for because you can only transition order by integer. So it's immediately set along with the width, and then the other properties transition.
div.outer {
width: 50vw;
height: 30px;
background: orange;
text-align: center;
overflow: hidden;
position: relative;
padding: 0;
}
div.inner {
position: relative;
margin: 0 auto;
height: 30px;
width: 50vw;
display: flex;
justify-content: center;
align-items: center;
background: transparent;
flex-wrap: wrap;
}
span {
order: 1;
padding: 0 3px;
flex-shrink:1;
}
a {
z-index: 0;
order: 1;
height: 30px;
line-height: 30px;
flex-grow: 0;
flex-shrink: 1;
transition: background .5s, flex-grow .25s, flex-shrink .25s;
}
a:hover {
z-index: 10;
width: 50vw;
order: -1;
flex-grow: 1;
background: #eee;
}
<div class="outer">
<div class="inner">
First
<span>&</span>
Second
<span>&</span>
Third
</div>
</div>
This isn't perfect, but I think it comes pretty close to achieving what you were looking for. Using a little bit of jQuery was necessary for math (but not the animations themselves).
Hope this gets you further!
function reset() {
// reset all spans
$('.animate span').css('transform', '');
$('.animate span.active').removeClass('active');
}
$('.animate').on('mouseover', 'span:not(.active)', function() {
reset();
// set current hovered word to active
$(this).addClass('active');
// slide over previous/next words
$(this).prevAll().css('transform', 'translateX(-100vw)');
$(this).nextAll().css('transform', 'translateX(100vw)');
// determine offset for center of hovered word
var center = (window.innerWidth / 2) - ($(this).offset().left + ($(this).width() / 2));
// slide current word to center
$(this).css('transform', 'translateX(' + center + 'px)');
});
// when leaving animate section, reset
$('.animate').mouseleave(reset);
.animate {
background-color: orange;
color: white;
font-family: sans-serif;
text-align: center;
transition: .5s background-color, .5s color;
}
.animate:hover {
background-color: white;
color: orange;
}
span {
display: inline-block;
transition: 3s transform;
}
a {
color: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="animate">
<span>First</span> <span>&</span> <span>Second</span> <span>&</span> <span>Third</span> <span>and</span> <span>Fourth</span>
</div>

CSS - unable to apply style to one element when hover over another

I have a box with a background, which is dimmed when hovered on. There is also a text, which is uncolored (transparent color), I'm trying to set its color to white when parent element is hovered on.
I know this should work:
#someDiv:hover > .someClass {
color: white;
}
But in my code it doesn't. Can anyone point me to the mistake?
jsfiddle here.
HTML:
<div class="row">
<div class="box" style="background:url('http://images6.fanpop.com/image/photos/34000000/Sandor-Clegane-sandor-clegane-34035068-960-640.jpg')">
<div id="overlay"></div>
<div class="hashContainer"><span class="tru">123</span></div>
</div>
CSS:
.box {
display: inline-block;
width: 300px;
margin: 40px;
height: 300px;
background-size: cover;
z-index: -1;
}
.hashContainer {
pointer-events: none;
position: relative;
top: 22%;
}
#overlay {
height: 300px;
width: 300px;
position: absolute;
}
#overlay:after {
content: "";
display: block;
height: inherit;
width: inherit;
opacity: 0;
background: rgba(0, 0, 0, .5);
transition: all 1s;
top: 0;
left: 0;
position: absolute;
}
#overlay:hover:after {
opacity: 1;
}
.tru {
font-size: 70px;
color: transparent;
font-weight: 900;
transition: all 1s;
}
/* not working */
#overlay:hover > .tru {
color: white;
}
/* not working */
.box > .tru {
color: white;
}
In my case, I'm trying to apply color change to the tru class span, while box \ overlay divs are hovered.
The [#overlay] is a sibling of[+] [.hashcontainer and .hashcontainer] the parent of[>] [.tru]
CSS
#overlay:hover + .hashContainer > .tru {
color: white;
}
HTML
<div id="overlay"></div><!----------------[#overlay isn't a parent of .hashContainer but an actual sibling]-->
<div class="hashContainer"><!-------------[.hashContainer is the parent of .tru]-->
<span class="tru">123</span>
</div>
http://plnkr.co/edit/H2Up3Y2YD6fl5uiwQky4?p=preview
Consider the following HTML document:
<html>
<head>
<style>
.someClass:hover { //mention in this manner
background: blue;
}
</style>
</head>
<body>
<div id="id1" class="someClass" >
<h1 id="id2" > HELLO MAN </h1>
</div>
</body>
</html>
The above code works. Color changes to blue when you hover over <div>.

Resources