I have two images inside a div. Same width/height and an effect on hover to display the secondary element. However, the secondary image is displaying before the first one, what is not the expected behavior.
The CSS:
.div-container {
position: relative;
}
.div-container img.primary {
position: relative;
}
.div-container img.secondary {
position: absolute;
top: 0;
left: 0;
transition: opacity 1s ease-in-out;
}
.div-container img.secondary:hover {
opacity: 0;
}
The HTML:
<div class="div-container">
<img class="primary">
<img class="secondary">
</div>
The question: I want to display the primary image first.
Example: http://jsfiddle.net/A6y7Y/
You can either use z-index and change the values on the :hover effect or just easily switch the images. But what you should be looking for here is putting them on a single file and controlling the position of the background image with CSS like a Sprite. Here is a good example
Swap the css style of the primary and secondary css style and add z-index to the primary as 1 should resolve the issue
HTML
`<div class="div-container">
<div class="primary">Layer1</div>
<div class="secondary">Layer2</div>
</div>`
CSS
`.div-container {
position: relative;
}
.div-container div{
width:100px;`enter code here`
height:100px;
border:1px solid red;
}
.div-container .secondary {
position: relative;
background-color: blue;
}
.div-container .primary {
position: absolute;
top: 0;
left: 0;
transition: opacity 1s ease-in-out;
background-color: #ccc;
z-index:1;
}
.div-container .primary:hover {
opacity: 0;
}`
I solved the problem.
For some reason, setting opacity: 0 to the hovered image, made it appear first.
All I did was set the secondary image to opacity: 0 and the container div on hover with opacity: 1 (instead of the hovered image). I also included a z-index to both images with the secondary image with a higher index. Below the code I'm using, hope it could help someone in the future.
.div-container {
position: relative;
}
.div-container img.primary {
position: relative;
z-index: 5;
}
.div-container img.secondary {
position: absolute;
top: 0;
left: 0;
opacity: 0;
z-index: 6;
transition: opacity 1s ease-in-out;
}
.div-container:hover img.secondary {
opacity: 1;
}
Related
so I am trying to add a loader to a webpage and it wont hide the all elements, although on a page it does at another html it doesnt , it's about a logo which z-index is set to 1 but the loader its set to 99999, I've tried to change the z-index of the logo to 0 but it still shows up, SO studying more the only difference is that on a page the logo is anchor and on another its not , and where its declared as anchor it wont hide on loading animation.
<div class="white-logo"><img src="img/logo_black.png" alt="logo_white"></div>
.loader_bg{
position: fixed;
z-index: 999999;
background: #fff;
width: 100%;
height: 100%;
}
.loader{
border: 0 soild transparent;
border-radius: 50%;
width: 150px;
height: 150px;
position: absolute;
top: calc(50vh - 200px);
left: calc(50vw - 75px);
text-align: center;
}
.loader:before, .loader:after{
content: '';
border: 1em solid #BDBDBD;
border-radius: 50%;
width: inherit;
height: inherit;
position: absolute;
top: 0;
left: 0;
animation: loader 2s linear infinite;
opacity: 0;
}
.loader:before{
animation-delay: .5s;
}
#keyframes loader{
0%{
transform: scale(0);
opacity: 0;
}
50%{
opacity: 1;
}
100%{
transform: scale(1);
opacity: 0;
}
}
.white-logo > a > img {
display: run-in;
width: 5%;
margin-left: 10%;
margin-top: -8.5%;
position: absolute;
z-index: 1;
}
I added some screenshots to understand the problem with the difference , I think is from anchor but I dont know what to do
Here are the photos and the difference
I am not certain if this is what you want (I assume the animation should display over the .loader_bg) so I just set the .loader_bg to have a negative z-index.
.loader_bg {
z-index: -1;
}
I have taken the liberty of making a jsfiddle with the relevant code in, but you will need to update if this is not the desired effect, adding an example would help, but you can also edit the fiddle and iterate over it.
EDIT
Sorry I see the issue now, I added some text to the anchor.
Change your .loader_bg with these properties:
.loader_bg {
z-index:0;
top: 0;
}
Solved, seemed I had two files with the css animation, one for the text and one for the circles, I put all of them in one file and it worked, thank you!
I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples, and translate being based on percentage/pixels etc...
The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the margin value.
Can anybody think of a way in which I can use scale, and also maintain the alignment?
Update
I want to avoid inverse/reverse scaling at all costs as it renders badly in the browser in most cases. With that in mind, I don't think this is actually possible but will leave the question open in case anyone is aware of some CSS magic.
See the following snippet as an example:
.tile {
position: relative;
width: 500px;
height: 100px;
padding: 40px;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
color: white;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
Try scaling .tile itself and reverse-scaling its children:
.tile {
position: relative;
width: 500px;
padding: 40px;
background: #000;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>* {
color: white;
transition: transform .3s ease-out;
}
.tile>.button {
position: absolute;
right: 0;
top: 0;
background: red;
padding: 10px 15px;
color: white;
transform-origin: 100% 0;
}
.tile:hover {
transform: scale(.9);
}
.tile:hover>* {
transform: scale(1.1);
}
<div class="tile">
<section>
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
</section>
<div class="button">Align Me</div>
</div>
Another idea is animating top and right of .button:
html,
body {
width: 75%;
margin: 0;
padding: 0
}
* {
box-sizing: border-box
}
.tile {
position: relative;
width: 100%;
padding: 40px;
color: white;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>.button {
position: absolute;
right: 0;
top: 0;
background: red;
padding: 10px 15px;
color: white;
transition: .3s ease-out;
}
.tile:hover>.button {
top: 5%;
right: 5%
}
<div class="tile">
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
<div class="button">Align Me</div>
</div>
The next idea is using a bit more complex code, but doing animation of transform property only:
html,
body {
width: 75%;
}
* {
box-sizing: border-box
}
.tile {
position: relative;
width: 100%;
padding: 40px;
color: white;
}
.tile:hover:before {
transform: scale(.9);
}
.tile:before,
.tile>.button {
content: '';
position: absolute;
top: 0;
left: 0;
z-index: -1;
width:100%; height:100%;
background: #000;
transition: transform .3s ease-out;
}
h1 {
text-align: center;
}
.tile>.button {
z-index: 1;
display: flex;
align-items: flex-start;
margin: 0 -100% -100% 0;
background: transparent;
transition: .3s ease-out;
pointer-events: none;
}
.tile>.button div {
padding: 10px 15px;
background: red;
cursor: pointer;
pointer-events: all;
}
.tile>.button:before {
content: '';
flex: 1 0;
}
.tile:hover>.button {
transform: translate3d(-5%, 5%, 0);
}
<div class="tile">
<h1>Hello World</h1>
<p>I have an element that requires the background to be scaled, without scaling the elements within the parent. I have achieved this by using a pseudo element to define the background, and then on hover I simply scale the pseudo element. So far, so good...
The problem is, I need some of the elements to stay inline with the scaled background, despite not scaling themselves. My original plan was to simply translate them, but I quickly realised that is not possible due to scale being based on multiples,
and translate being based on percentage/pixels etc... The obvious solution is to scrap scale and instead use margin to shrink the absolutely positioned pseudo element. However, my reservation with this is that it is bad practice to transition the
margin value. Can anybody think of a way in which I can use scale, and also maintain the alignment?</p>
<div class="button">
<div>Align Me</div>
</div>
</div>
If you are scaling by p then you are reducing the size and the new width will become width*(1 - p). Same logic for the height. You can consider the use of calc() and easily define the translate using this formula.
We divide by 2 because we reduce from both side and we will translate from 1 side
.tile {
position: relative;
width: 540px;
height: 200px;
display:flex;
align-items:center;
justify-content:center;
}
.tile:hover:before {
transform: scale(0.9);
}
.tile:hover .button{
transform: translate(calc(-540px*0.1/2),calc(200px*0.1/2));
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s;
}
h1 {
text-align: center;
color: white;
margin:0;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
transition: transform .3s ;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
You can consider CSS variables to easily change the scale value:
.tile {
position: relative;
width: 540px;
height: 200px;
display:flex;
align-items:center;
justify-content:center;
--s:0.9;
}
.tile:hover:before {
transform: scale(var(--s));
}
.tile:hover .button{
transform: translate(calc(-540px*(1 - var(--s))/2),calc(200px*(1 - var(--s))/2));
}
.tile:before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #000;
z-index: -1;
transition: transform .3s;
}
h1 {
text-align: center;
color: white;
margin:0;
}
.tile > .button {
position: absolute;
right: 0;
top: 0;
display: inline-block;
background: red;
padding: 10px 15px;
color: white;
transition: transform .3s ;
}
<div class="tile">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
<div class="tile" style="--s:0.5">
<h1>Hello World</h1>
<div class="button">Align Me</div>
</div>
Right now I have an image that has another image absolutely positioned on top of the first one. Both images are inside an a tag.
I am trying to get it so that when I hover on any part of the first image, both the first image goes from .5 opacity to full, and the 2nd image goes from 0 opacity to full.
I've been able to make the hover work for the image but the 2nd image only activates it's opacity when I hover directly on it, rather than highlighting both when I'm on either of them.
<div class="of-volume image-column">
<a href="http://www.greatlengthshair.co.uk/hair-extensions/">
<img src="img/artistry-1-bg.jpg" alt="artisans of volume link" class="image-link">
<img src="img/artistry-1-icon.png" alt="" class="artisan-icon">
</a>
</div>
/*//////////////////////////////////////
IMAGE NAV
//////////////////////////////////////*/
.image-column {
background-color: black;
float: left;
width: 33.3333%;
position: relative;
margin-bottom: -3px;
}
.image-column a {
opacity: .5;
}
.image-column a:hover {
opacity: 1;
}
.artisan-icon {
position: absolute;
margin-right: auto;
margin-left: auto;
right: 0;
left: 0;
bottom: 25px;
}
You have mixed up most of your CSS rules. Just attach the desired effects to the correct hover state:
.image-link { opacity: 0.5; }
.artisan-icon { opacity: 0; }
a:hover .image-link { opacity: 1; }
a:hover .artistan-icon { opacity: 1; }
I put both absolute images inside a relative div, then did set the :hover selector on this container.
body {
width: 100%;
height: 100%;
margin: 0px;
}
#container {
position:relative;
width:100%;
height:200px;
}
img {
position:absolute;
top: 0px;
left:0px;
width:100%;
height:200px;
-webkit-transition: opacity 1s; /* Safari */
transition: opacity 1s;
}
#pic1 {
opacity:0.0;
}
#pic2 {
opacity:0.5;
}
#container:hover #pic1, #container:hover #pic2 {
opacity: 1;
}
<div id=container>
<img id=pic1 class=picture src="http://i.imgur.com/tMVGqP6.jpg" alt=img>
<img id=pic2 class=picture src="http://i.imgur.com/Goy7oBy.gif" alt=img>
</div>
<div class="wrapper">
<div class="avatar"></div>
<div class="desc an-all"></div>
</div>
<div class="wrapper">
<div class="avatar"></div>
<div class="desc an-all"></div>
</div>
.wrapper{
position: relative;
width: 250px;
height: 150px;
cursor: pointer;
}
.wrapper:hover .desc{
opacity: 1;
}
.avatar{
width: 70px;
height: 70px;
background: green;
position: relative;
z-index: 30;
}
.desc{
position: absolute;
top: 50px;
left: 0;
height: 250px;
width: 100%;
background: red;
opacity: 0;
z-index: 20;
}
.an-all{
-webkit-transition: all 0.3s linear;
-moz-transition: all 0.3s linear;
transition: all 0.3s linear;
}
I can't figure out why is this happening. I thought that a position element inside a parent with position relative only apply inside parent and outside is a different world.
Why when I hover the green box of the first wrapper div the red one don't overlay the second's wrapper div green box ? I want the red box to be under the green one when I hover
http://codepen.io/laxmana/pen/txKbF
See if you like this example:JSFiddle
It uses your same working code, but the wrapper divs are placed within a relative parent, and each are given their own z-index. This is how you can layer one on top of another. In a real world example, the divs may not be together (like a tooltip), and then you wouldn't need the additional parent. The parent is useful when the divs are together, and on the same level. Play around with the JSFiddle, and try different options with content.
In the original example, the reason the green divs were always on top, regardless of their html order, is because the red divs are absolutely positioned, and the 2 wrapper elements are on the same level within the parent.
.wrapper {
position: relative;
width: 250px;
height: 150px;
cursor: pointer;
}
.wrapper:hover .desc {
opacity: 1;
}
.relative-container {
position:relative;
}
.top {
z-index:10;
}
.bottom {
z-index:9;
}
.avatar {
width: 70px;
height: 70px;
background: green;
position: relative;
z-index: 30;
}
.desc {
position: absolute;
top: 50px;
left: 0;
height: 250px;
width: 100%;
background: red;
opacity: 0;
z-index: 20;
}
.an-all {
-webkit-transition: all 0.3s linear;
-moz-transition: all 0.3s linear;
transition: all 0.3s linear;
}
Update
Here is an example with multiple display:inline-block divs. The trick is for the z-index to work, the divs need to be siblings/on the same level as each other (this works for other elements too). The first div in the row that needs to go on top gets the highest z-index, while the last div gets the lowest z-index.
JSFiddle Example
Here is a great resource explaining the details on the z-index https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
Note: In the second JSFiddle I used display:none on the red ".desc" dropdowns, and made them visible only when moused over by adding display:block; to ".wrapper:hover .desc". In your original code even though you don't see the red divs, when you hover over their invisible area it triggers them to show. By using display:none, they are truly not displayed in the page and therefore can't trigger the hover state. The trick is that display:block overwrites the display:none in the hover class, so they will show when the green buttons are hovered over.
This hides the red divs:
.desc {
display:none;
This shows the red divs only when the green divs are hovered over:
.wrapper:hover .desc {
display:block;
Your z-index needs to change. Right now, both red boxes have an index lower than the green, which is why it appears beneath the second green box.
Update
Based on your comment, you want to have the green box both underlay the avatar class and overlay the same class below the wrapper. Because you're using classes alone, you can't have both actions. You could space the wrappers differently so you have the description still underlay the avatar and not overlap lower elements.
CSS
.wrapper{
position: relative;
width: 250px;
height: auto; /* Set this to auto to keep elements separate from one another */
cursor: pointer;
}
.wrapper:hover .desc {
opacity: 1;
}
.avatar{
width: 70px;
height: 70px;
background: green;
position: relative;
z-index: 30;
}
.desc{
position: relative; /* Keep it inside the document flow */
top:-20px; /* sets the overlap from the avatar class */
left: 0;
height: 250px;
width: 100%;
background: red;
opacity: 0;
z-index: 20; /* Displays below the avatar */
}
.an-all{
-webkit-transition: all 0.3s linear;
-moz-transition: all 0.3s linear;
transition: all 0.3s linear;
}
Working pen
What I am trying to do is, when the user hover on the image the image should reposition along the x-axis and it should reveal the .content. i have set z-index: 10 to image and z-index: 1 to .content to make .content to be underneath the image. but .content still remains on top of the image. Please help me..
Here is my code:
html
<div class="holder">
<img src="http://placehold.it/350x150" />
<div class="content">
<h3>hello there</h3>
view more
<div/>
</div>
css
.holder {
margin-top: 130px;
position: relative;
}
img {
display: block;
transition: -webkit-transform 0.5s;
transition: -moz-transform 0.5s;
z-index: 10;
}
.content {
background: blue;
height: 100%;
color: white;
z-index: 1;
position: absolute;
top: auto;
bottom: 0;
}
a {
color: white;
background: red;
padding: 10px;
}
.holder:hover img {
-webkit-transform: translateX(90px);
-moz-transform: translateX(90px);
}
Here I corrected issue of my code thanks to Jones G. Drange. As he pointed out in his comment
"z-index can only be modified in elements with a position other than static. Your img has position: static by default"
jsfiddle
img {
position: relative;
}