I'm in a tricky situation -- I'm trying to build a sort of realistic flyer, with clickable paper strips at the bottom. Just for a visual reference, something like this: http://static.someecards.com/someecards/images/feed_assets/4d657f7fa4817.jpg
I built the body of the flyer with an empty div, and I absolutely positioned the "paper strips" at the bottom of this div. Then, since I'll want to add a "torn paper" border-image at the bottom of the flyer body, I gave the strips a negative z-index.
Then, in order to cover the torn-paper-border, I positioned an empty, transparent div on the top of them, with a solid-coloured pseudo element that will disappear once the CSS3 animation will be triggered (via JS).
<div class="flyer-body">
<div class="strip"></div> <!-- this will be animated via CSS3 -->
<div class="strip-wrapper"></div> <!-- this is a clone of the "strip" div, but transparent (made for z-index problems with animations). a click on this div will trigger the animation -->
</div><!-- end flyer-body -->
jsFiddle for reference: http://jsfiddle.net/XR7LT/
As you can see, I'm applying a fadeOut() effect to the pseudo element in order to disappear gently. The problem is, the fadeOut() only applies to the first pseudo element, while hiding the others without any effect.
Problem shows on both Chromium and FF browser, Ubuntu Linux 12.10.
Any ideas?
Thanks in advance.
Your CSS is not the same for all elements.
The transitions should not be in both .strappamiX and .strappamiX-wrap,
I removed them from wrap:
.strappami1 {
display: block;
width: 100px;
height: 250px;
background: red;
z-index: -23;
position: absolute;
bottom: -200px;
left: 103px;
transition: all 2s ease-in;
-moz-transition: all 2s ease-in;
-webkit-transition: all 2s ease-in;
-o-transition: all 2s ease-in;
}
.strappami1-wrap {
display: block;
position: absolute;
width: 100px;
height: 250px;
bottom: -200px;
left: 103px;
background: transparent;
}
Created a fork of your fiddle here:
http://jsfiddle.net/sn6ZT/1/
I got here after Roise, but you should be able to simplify your solution significantly by leveraging parent child relationships and adding multiple classes.
http://jsfiddle.net/XR7LT/4/
When you have 5 elements that should all have the same behavior, use the same class for all of them, and apply the code to all of them. Then you can add some additional classes to move the additional pieces over a bit.
SIMPLER HTML
<section class="flyer">
<div class="strappami-wrap w0">
<div class="cover"></div>
<div class="strappami"></div>
</div>
<div class="strappami-wrap w1">
<div class="cover"></div>
<div class="strappami"></div>
</div>
<div class="strappami-wrap w2">
<div class="cover"></div>
<div class="strappami"></div>
</div>
<div class="strappami-wrap w3">
<div class="cover"></div>
<div class="strappami"></div>
</div>
<div class="strappami-wrap w4">
<div class="cover"></div>
<div class="strappami"></div>
</div>
</section>
SIMPLER CSS
.flyer {
display: block;
width: 900px;
height: 220px;
background: yellow;
margin: 0 auto;
position: relative;
}
.strappami {
display: block;
width: 100px;
height: 250px;
background: red;
z-index: -23;
position: absolute;
left: 0;
transition: all 2s ease-in;
-moz-transition: all 2s ease-in;
-webkit-transition: all 2s ease-in;
-o-transition: all 2s ease-in;
}
.strappami-wrap {
display: block;
position: absolute;
width: 100px;
height: 250px;
background: transparent;
bottom: -200px;
left: 0px;
}
.strappami-wrap.w1 {
left: 110px
}
.strappami-wrap.w2 {
left: 220px
}
.strappami-wrap.w3 {
left: 330px
}
.strappami-wrap.w4 {
left: 440px
}
.strappami-wrap .cover {
content: '';
display: block;
position: absolute;
width: 100px;
height: 50px;
background: green;
top: 30px;
left: 0px;
}
.strapping {
bottom: -900px;
opacity: 1;
z-index: -200;
-webkit-transform: rotate(-5deg);
-moz-transform: rotate(-5deg);
}
.strapping-alt {
bottom: -800px;
opacity: 1;
z-index: -200;
-webkit-transform: rotate(3deg);
-moz-transform: rotate(3deg);
}
SIMPLER JS
$(document).ready(function() {
$(".strappami-wrap").on('click', function() {
var r = Math.floor(Math.random()*10);
if (r < 5){
$(this).find(".strappami").addClass('strapping');
} else {
$(this).find(".strappami").addClass('strapping-alt');
}
$(this).find(".cover").fadeOut();
});
});
Related
I am trying to place an image(which is a close button) on iframe at the top-right corner, the iframe and image are loaded from js function in angular, I have placed it correctly by some CSS but the issue is when the screen is responsive or on the tab or mobile view it doesn't appear in the correct place
Below is the Html code:
<div style="
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transition: all 0.3s ease-in-out 0s;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
">
<iframe style="
display: inherit;
z-index: 10001;
position: absolute;
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
top: 40px;
left: 50%;
margin-left: -200px;
background-color: rgb(255, 255, 255);
" src="test.html" id="iframe-overlay" title="iframe">
</iframe>
<img style="
transition: all 0.5s ease-in-out 0s;
opacity: 1;
float: left;
position: absolute;
top: 23% !important;
left: 48% !important;
transform: translate(-50%, -50%) !important;
z-index: 99999999;
margin-left: 192px;"
id="close-overlay"
" src="assets/images/pink_hair_sml.png" />
</div>
The image should be placed at the marked position even if the screen gets minimized or maximized the image should be placed at the same position.
here is how it should look
but when I reduce the screen to 75%
this is how it looks
I am able to fix it for each screen but still when the screen gets minimized or maximized position is not placed correctly
here is parent of the element
If you add a div that wraps the 2, you can position that using flex in relation to your to div like so:
<div style="
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transition: all 0.3s ease-in-out 0s;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
">
<div style="position: relative; max-width: 50%">
<iframe style="
display: inherit;
z-index: 10001;
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
background-color: rgb(255, 255, 255);
" src="test.html" id="iframe-overlay" title="iframe">
</iframe>
<img style="
transition: all 0.5s ease-in-out 0s;
opacity: 1;
float: left;
position: absolute;
top: 0px;
right: 0px;
transform: translate(-50%, -50%) !important;
z-index: 99999999;
id="close-overlay"
" src="assets/images/pink_hair_sml.png" />
</div>
</div>
Alternatively, positioning the wrapping element itself which means you don't have to add a new div, see below. The disadvantage of this is that there's then space not covered by the div itself and so whatever's underneath then shows through.
<div style="
position: fixed;
width: 50%;
height: 100%;
top: 0px;
left: 25%;
transition: all 0.3s ease-in-out 0s;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
">
<iframe style="
display: inherit;
z-index: 10001;
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
background-color: rgb(255, 255, 255);
width: 100%;
" src="test.html" id="iframe-overlay" title="iframe">
</iframe>
<img style="
transition: all 0.5s ease-in-out 0s;
opacity: 1;
float: left;
position: absolute;
top: 10px;
right: 10px;
z-index: 99999999;
id="close-overlay"
" src="assets/images/pink_hair_sml.png" />
</div>
The positioning of the two elements (iframe and img) is pretty straightforward as we know the width of the iframe (it is picking up the default which is set at 300px by browsers see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe ).
However it is rendered somewhat complex by the rather strange set of styles applied inline to the iframe and (worse) to the img where a couple are set !important and therefore not overwritable by our own CSS.
This snippet just gets rid of all the inline styling on those two elements using Javascript and starts again.
It positions each element independently. The iframe is centered and set at 40px from the top of its positioned parent. The img is positioned to just after the right hand edge of the iframe, and then transitioned back by half its width and height to get the overlap.
<!doctype html>
<html>
<head>
</head>
<body>
<div id="GlobalPayments-overlay-02d30efa" style="
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transition: all 0.3s ease-in-out 0s;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
">
<iframe style="
display: inherit;
z-index: 10001;
position: absolute;
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
top: 40px;
left: 50%;
margin-left: -200px;
background-color: rgb(255, 255, 255);
" src="test.html" id="iframe-overlay" title="iframe">
</iframe>
<img style="
transition: all 0.5s ease-in-out 0s;
opacity: 1;
float: left;
position: absolute;
top: 23% !important;
left: 48% !important;
transform: translate(-50%, -50%) !important;
z-index: 99999999;
margin-left: 192px;" id="close-overlay" " src="assets/images/pink_hair_sml.png " />
</div>
<style>
body {
width: 100vw;
}
#GlobalPayments-overlay-02d30efa {
--iframeW: 300px; /*the defaults set by browsers https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe*/
--iframeH: 150px;
}
#GlobalPayments-overlay-02d30efa iframe {
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
background-color: rgb(255, 255, 255);
top: 40px;
margin: 0;
padding: 0;
left: calc(50% - (var(--iframeW) / 2));
position: absolute;
}
#GlobalPayments-overlay-02d30efa img {
position: absolute;
top: 40px;
left: calc(50% + (var(--iframeW) / 2));
transform: translate(-50%, -50%);
margin: 0;
padding: 0;
width: 16px;
height: 16px;
}
</style>
<script>
const iframe = document.querySelector('iframe');
const img = document.querySelector('img');
iframe.style = '';
img.style = '';
</script>
</body>
After all your comments that finally explains that you cannot change the HTML code we start to understand what you need!
You have to override the inline CSS rules with the help of the !important operator. The big problem will be on the close image
because it already has some !important rules in the inline CSS, which is bad news for us... But you can use JavaScript to correct
the horrible HTML generated.
For the CSS itself, I prefer putting all items in position fixed and use % to position them.
The close image should not be set from the left but from the right. But as said before this will be tricky because the inline CSS already has some !important rules. But at least we can remove the float and left margin. Finally, after overriding during the battle, the simpliest was just to remove the inline style attribute with JS.
You'll have to find if you can hook somewhere in the JS library. If you cannot then you could run the JS every half a second until it finds the close image, like I did (but it's not a nice solution).
By the way, it would be good to set the image size in the CSS so that it displays at the correct place and size before the image itself is downloaded.
/*
In your case, you'll have to run this once the
iframe is visible. See if you can hook somewhere.
Look at the JS library you are using or if you can
then replace it by one not generating all this
horrible HTML with inline styles.
Here, just for the demo, I finally find a solution
to run it once the document is loaded and also each
time a change is detected, typically the case of the
user clicking on a button or link to display the
iframe overlay. This avoids the solution of a timer
running all the time.
*/
/**
* Correct the close button of the iframe displayed on overlay.
*/
function correctIframe() {
let closeImg = document.querySelector('#iframe-overlay ~ img:not(.cleaned)');
if (closeImg) {
closeImg.setAttribute('style', '');
closeImg.setAttribute('class', 'cleaned');
}
}
// Once the document is loaded we can try to see if there's
// already an iframe overlay to correct it.
document.addEventListener('DOMContentLoaded', correctIframe);
// Each time the document changes (typically if some JS does
// something such as triggering an Ajax call, loading new HTML,
// or simply displaying the iframe overlay) then we also have
// to correct it.
let domInsertionObserver = new MutationObserver((mutation) => {
correctIframe();
});
domInsertionObserver.observe(document, { childList: true });
#iframe-overlay {
z-index: 1000 !important;
position: fixed !important;
top: 10% !important;
left: 10% !important;
width: 80% !important;
height: 80% !important;
margin: 0 !important;
}
/* An image tag just after the iframe. */
#iframe-overlay ~ img {
visibility: hidden; /* To avoid seeing it at bad position. */
z-index: 1001 !important;
position: fixed !important;
/*
We cannot override the left attribute
because it has !important in the inline
rule! Bad! We cannot override the transform
either! Even worth! So JavaScript can only
save us by deleting the inline style attribute.
*/
top: 10% !important;
right: 10% !important;
/* Adjust to the image size to avoid image
being resized during the download step. */
width: 30px;
height: 30px;
/* Move half of the image size to right and down. */
transform: translate(50%, -50%) !important;
}
#iframe-overlay ~ img.cleaned {
visibility: visible;
}
<div style="
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
transition: all 0.3s ease-in-out 0s;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
">
<iframe style="
display: inherit;
z-index: 10001;
position: absolute;
transition: transform 0.5s ease-in-out 0s;
transform: scale(1);
opacity: 1;
top: 40px;
left: 50%;
margin-left: -200px;
background-color: rgb(255, 255, 255);
" src="test.html" id="iframe-overlay" title="iframe">
</iframe>
<img style="
transition: all 0.5s ease-in-out 0s;
opacity: 1;
float: left;
position: absolute;
top: 23% !important;
left: 48% !important;
transform: translate(-50%, -50%) !important;
z-index: 99999999;
margin-left: 192px;"
id="close-overlay"
" src="assets/images/pink_hair_sml.png" />
</div>
Please view this imageLike in the image, i have made a border which is supposed to move 20px up on scrolling above and 20px down on scrolling down. The same thing has been accomplished through hover, however i am not being able to do it upon scroll. Is it possible to change what happens upon hover to scroll?? The code can be found below;
#menu-container div{
height: 415px;
width: 52%;
border:1.5px solid black;
background:transparent;
left: 170px;
-webkit-transition: all 10s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.9s linear;
position: relative;
transition-delay: 0.2s;
margin-top: -120px;
}
#divi:hover{
background:transparent;
left: 220px;
/* top:35px;*/
padding-left: -20px;
}
.menu2:hover{
background:transparent;
left: 70px !important;
/* top:-80px;*/
padding-left: -200px;
}
<div id="menu-container" >
<div id="divi"> <div class="menu2" style="margin-top: 30px; margin-left: -115px; width:100%"></div></div>
</div>
<!-- <div class="menu2" style="margin-top: -399px; margin-left: 45px;"></div> </div> -->
<img class="ay" <a href="https://imgbb.com/"><img src="https://i.ibb.co/YTTxKc9/ab.png" width="275px" height="auto" style="margin-top: -400px; margin-left: 200px "> </img>
I made you an example from your code, I explained everything in the form of comments.
let cont = document.querySelector(".container")
const maxScrollTop = 395;
// onscroll property of html elements
cont.onscroll = () => {
// your two borders
let divi = document.querySelector("#divi");
let menu = document.querySelector(".menu2");
// the math, it semes complicated but not really
/* it just maps the scrollTop value between the values that we want (between 0 and 50 with the divi and between 50 and 200 with the menu) */
divi.style.left = `${50 - ((cont.scrollTop / maxScrollTop) * 50)}px`;
menu.style.left = `${50 + ((cont.scrollTop / maxScrollTop) * (200 - 50))}px`;
};
.container{
height: 200px;
overflow-y: scroll;
}
/* I made it a bit bigger for better presentation */
#menu-container div{
height: 560px;
width: 450px;
border: 1.5px solid black;
background: transparent;
left: 50px;
-webkit-transition: all 10s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.9s linear;
position: relative;
transition-delay: 0.2s;
margin-bottom: -160px;
}
/* this is your hover code */
/* #divi:hover{
background: transparent;
left: 220px;
/* top: 35px;
padding-left: -20px;
}
.menu2:hover{
background: transparent;
left: 70px !important;
/* top: -80px;
padding-left: -200px;
} */
<!-- we need the container so the this is what we scroll not the iframe in the snipet, which I don't know if we can reach -->
<div class="container">
<div id="menu-container" >
<div id="divi">
<div class="menu2" style="margin-top: 30px; margin-left: -115px; width:100%">
</div>
</div>
</div>
<img src="https://i.ibb.co/YTTxKc9/ab.png" width="450px" height="auto" style="margin-top: -400px; margin-left: 50px "/>
</div>
I made a div with 2 elements inside: an image and an another div (about). The image is hiding the about div.
Is that possible to make elements which are in the about div clickable when the image disappear with a hover property ?
Thanks in advance !
Also, here's my code but the elements aren't clickable
#logo {
opacity: 1;
visibility: visible;
margin-top: 12.5px;
-webkit-transition: opacity 600ms, visibility 600ms;
-o-transition: opacity 600ms, visibility 600ms;
-moz-transition: opacity 600ms, visibility 600ms;
transition: opacity 600ms, visibility 600ms;
}
.blue_border:hover #logo {
opacity: 0;
visibility: hidden;
}
.blue_border {
width: 625px;
height: 625px;
background-image: url("./border.png");
background-repeat: no-repeat;
background-position: 50%;
}
#about {
z-index: -1;
position: relative;
margin-top: -605px;
width: 600px;
height: 600px;
border-radius: 100%;
background-color: #25B8EE;
}
<div class="blue_border">
<img id="logo" src="./logo.png" />
<!-- Img is "on" the about div" -->
<div id="about">
I want to be clicked :-(
</div>
<div class="la-ball-scale-multiple">
<div></div>
<div></div>
<div></div>
</div>
</div>
I don't think I understand it completely, but you cannot click under another element but you can use CSS display: none attr or you do this in a fake way. You can listen to the top element for this and check other conditions on javascript.
As mentioned in the comments, you may can use the pointer-events: none on the overlay to cause it to not receive click events, and allow them to pass through.
function whoWasClicked(e) {
console.log(`${e.target.id} was clicked!`);
};
document.querySelector('#lowerElement').addEventListener('click', whoWasClicked);
document.querySelector('#upperElement').addEventListener('click', whoWasClicked);
#lowerElement {
background-color: rgb(128, 128, 128);
min-width: 25vw;
height: 100px;
text-align: center;
position: absolute;
top: 37vh;
left: 37vw;
z-index: 1;
}
#upperElement {
min-width: 25vw;
height: 100px;
text-align: center;
line-height: 50px;
position: absolute;
top: 37vh;
left: 37vw;
z-index: 2;
pointer-events: none;
}
<div id="lowerElement">Click Me</div>
<div id="upperElement">Overlay</div>
With my current code, I think the z-index: -1; in #about is the problem: #blue_border is an image background and it's upper my "about" div... So I'm trying to find a way to replace that background.
Edit:
Okay. I figured out that the element with z-index: -1; will never be clickable the way I want to.
So I decided to reverse everything: the logo has now the property z-index: -1; and the about div (which is upper now) is hidden until the hover trigger. I also changed my background image by a border.
My code now :
/*Under #about and visible*/
#logo {
z-index: -1;
}
.blue_border {
width: 600px;
height: 600px;
border: 15px solid #71d1f4;
border-radius: 100%;
/*background-image: url("./border.png");
background-repeat: no-repeat;*/
background-position: 50%;
}
/*Hidden first*/
#about {
opacity: 0;
visibility: hidden;
position: relative;
margin-top: -605px;
width: 600px;
height: 600px;
border-radius: 100%;
background-color: #25B8EE;
-webkit-transition: opacity 600ms, visibility 600ms;
-o-transition: opacity 600ms, visibility 600ms;
-moz-transition: opacity 600ms, visibility 600ms;
transition: opacity 600ms, visibility 600ms;
}
/*Unhidden on hover*/
.blue_border:hover #about
{
opacity: 1;
visibility: visible;
}
I didn't changed my html
Thanks anyway guys. It was my very first question and I'm glad that some of you already answered me !
HTML:
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
JS:
$('.button').on('mouseenter', function () {
$('.element').addClass('active');
}).on('mouseleave', function () {
$('.element').removeClass('active');
});
$('.element').on('mouseenter', function () {
$('.element').addClass('active');
}).on('mouseleave', function () {
$('.element').removeClass('active');
});
http://jsfiddle.net/e4p98cwb/1/
When you hover on the black element the blue one enters the screen. After that if you hover for a sec on empty space the blue one starts to escape the screen, but if you hover fast on the empty space that it occupied before two things might happen:
1. The blue one returns fully shown on screen
or
2. Jumps once or twice and proceeds to leave the screen
The same happens on hover and mouseover events as well. Why is this happening and is there a way around this behavior ?
The easiest way to get around any issues with JS is to just let CSS take care of it. If you add this to the :hover state it will work:
.button:hover + .element,
.element:hover {
-webkit-transform: translateX(0);
transform: translateX(0);
}
See below for an implementation. This saves you a ton of JS as well.
.wrap {
position: relative;
width: 600px;
height: 600px;
overflow: hidden;
border: 2px solid red;
}
.button{
width: 100px;
height: 50px;
display: block;
background: #333;
}
.element {
position: absolute;
top: 0;
right: 0;
z-index: 99999;
width: 500px;
height: 630px;
background: blue;
-webkit-transform: translateX(630px);
transform: translateX(630px);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.button:hover + .element,
.element:hover {
-webkit-transform: translateX(0);
transform: translateX(0);
}
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
Update
The reason this is happening is because the element itself is still occupying the same space. This has to do with translation not actually moving the element, but transforming it. Once you move your cursor off any of the activatable elements, it will retract, but as it's animating it still occupies that same space, making it possible to hover on that space and retrigger the animation. I believe it's because this transform is only fully applied after completing the animation. Let's test this theory:
.wrap {
position: relative;
width: 600px;
height: 600px;
overflow: hidden;
border: 2px solid red;
}
.button{
width: 100px;
height: 50px;
display: block;
background: #333;
}
.element {
position: absolute;
top: 0;
right: 0;
z-index: 99999;
width: 500px;
height: 630px;
background: blue;
right: -100%;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.button:hover + .element,
.element:hover {
right: 0;
}
<div class="wrap">
<span class="button"></span>
<div class="element"></div>
</div>
In this one we are simply using absolute positioning and the issue goes away, meaning that the tranform is actually causing the element to still occupy the same space. Until animation concludes.
Please note this is not a repeat question, i have looked into all possible questions in stackoverflow and i did not get an answer.
I am looking at the website http://riviera-black.cmsmasters.net/ and in this especially the section where it says "Recent Projects". When i hover over the image only the background <article> element changes in opacity but not the <figure> element inside. How is this done?
Please note i tried changing the opacity using jQuery for me it changes the opacity of all elements inside, for example in this case it changes opacity of <article> and <figure> element.
There are many ways to do this, perhaps the easiest is to use a wrapper element around the image with a padding, and then animate the background with CSS3 on :hover
<div class="image">
<img src="http://phaseoneimageprofessor.files.wordpress.com/2013/07/iqpw29_main_image_.jpg"/>
</div>
css
.image {
padding: 50px;
position: relative;
top: 100px;
left: 100px;
height: 200px;
width: 300px;
-webkit-transition: background 1s ease-out;
-moz-transition: all 0.3s ease-out;
-o-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.image:hover {
background: rgba(255,255,255,0.4);
}
.image img {
height: 200px;
width: 300px;
}
FIDDLE
They change opacity not in <article> element. They change pseudo element :before that IN <article> with CSS:
content: '';
background-color: rgba(0, 0, 0, 0);
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
opacity: .15;
that mean, that element places full width and height of parent <article> but not contains <article> children. :before and <figure> are in parallel.
They used a combination of the :before and :hover pseudo selectors. When someone hovers on the child element, the :before pseudo element's opacity is modified.
Example
HTML
<div class="parent">
<div class="child">Hover me!</div>
</div>
CSS
.parent { position: relative; }
.child:before {
content: '';
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: black;
opacity: .15;
}
.child:hover:before { opacity: .5; }
Working example