CSS3 Animation - Change image on 'underside' of an animated element - css

I am using CSS3 animation to have a door element open on hover. If you take a look at the url below: http://www.superfreebingo.com/advent-lp/
When you hover over a box the css animation will begin showing you content beneath.
I would like to modify the 'underside' of the door that opens, you will notice at the moment you just see the front image in reverse..
Will it be a case of timing another animation on the background image itself to coincide with the point the door 'flips' over?

So what you are looking for is backface-visibilty. Set that to the .box img.
Now add an element below that image, here I just added a pseudo-element, positioned it absolute with z-index: -1;.
You could also just set a div or image as a child of .box, works just as well.
/* CSS needed for your affect */
.box img {
backface-visibility: hidden;
}
.box::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: #FF0;
z-index: -1;
}
/* Rest of the markup */
article {
display: inline-block;
width: 6em;
height: 6em;
margin: .5em;
perspective: 850px;
}
article:hover .box {
transition: .5s ease-in;
transform: rotateY(-97deg);
transform-origin: 0 50%;
perspective-origin: 0;
}
.box {
position: relative;
transition: all .3s;
transform-origin: 0 50%;
text-align: center;
background-size: cover;
box-shadow: 0 0 40px 0 rgba(0, 0, 0, .15);
transform-style: preserve-3d;
perspective: 850px;
cursor: pointer;
}
.box, .present {
width: 100%;
height: 100%;
}
.box img, .present img {
width: 100%;
height: 100%;
}
.present {
position: absolute;
z-index: -1;
top: 0;
left: 0;
box-shadow: 0 0 40px 0 rgba(0, 0, 0, .15), inset 0 0 30px 20px rgba(0, 0, 0, .4);
}
.present a {
display: block;
width: 100%;
height: 100%;
}
<article>
<div class="box">
<img src="http://i.stack.imgur.com/wheDD.jpg">
</div>
<div class="present">
<a href="#">
<img src="http://i.stack.imgur.com/EXU8x.jpg">
</a>
</div>
</article>

Related

::before and ::after elements overlapping each other ruining the background transparancy

I have a simple div element that I wanna apply a background shape to it when the user hovers over it by using the ::before and ::after pseudo elements. I rotated these elements with rotateX(). How can I style it that the elements shouldn't overlap each other (or at least not ruin the background color) but it should look like a single shape?
Tried using % but didn't work.
Please help.
Thanks so much 🙏
div{
width:200px;
padding: 18px;
margin: 10px auto;
/* border: 1px solid black; */
text-align:center;
position: relative;
perspective: 100px;
z-index: 1;
}
div:hover{
color:#fff;
}
div:hover::before, div:hover::after{
content: "";
display: block;
background-color: #00000050;
width: 100%;
height: 50px;
position: absolute;
left: 0%;
z-index: -1;
}
div::before{
top:0;
transform: rotateX(-75deg);
}
div::after{
bottom:0;
transform: rotateX(75deg);
}
<div>Hello World</div>
If you make half of each pseudo element only have the color then when you rotate them the colors don't overlap.
A minor adjustment to the padding of the div was needed to get the two rotated 'halves' to meet correctly so this would have to be looked at if you ever went for a responsive rather than a fixed px unit solution.
This snippet removes the background-color from the pseudo elements, instead using a linear-gradient background-image going just half way up (or down) the pseudo element.
div {
width: 200px;
padding: 18px;
padding: 16px;
margin: 10px auto;
/* border: 1px solid black; */
text-align: center;
position: relative;
perspective: 100px;
z-index: 1;
}
div:hover {
color: #fff;
}
div:hover::before,
div:hover::after {
content: "";
display: block;
margin: 0;
padding: 0;
width: 100%;
height: 50px;
position: absolute;
left: 0%;
z-index: -1;
}
div::before {
top: 0;
transform: rotateX(-75deg);
background-image: linear-gradient(#00000050 0 50%, transparent 50% 100%);
}
div:hover::after {
bottom: 0;
transform: rotateX(75deg);
background-color: transparent;
background-image: linear-gradient(to top, #00000050 0 50%, transparent 50% 100%);
}
<div>Hello World</div>
A Haworth's answer covers using linear gradient stops to hide the color of half of each pseudo element.
Another approach you could take is to use only one of the pseudo elements with a polygon clip path to make your shape.
.container { display: flex; }
.hoverable { position: relative; margin: auto; padding: 10px 100px; }
.hoverable:hover::before {
content: "";
position: absolute;
inset: 0;
/* top: 0; left: 0; right: 0; bottom: 0; */
background-color: rgba(0, 0, 0, 0.25);
clip-path: polygon(0 0, 100% 0, 80% 50%, 100% 100%, 0 100%, 20% 50%);
}
<div class="container">
<div class="hoverable">Hello, World!</div>
</div>

CSS Header Border bottom

How do you achieve this kind thing on the bottom of a div in CSS?
I try
&:before {
content: '';
position: absolute;
z-index: 2;
width: 133.93px;
height: 93.63px;
border-radius: 5px;
border: 1px solid #ffffff;
box-shadow: 1px 1px 0 rgba(0,0,0,0.2);
background-image: $gradeint;
text-align: center;
transform-origin: center;
transform: rotateZ(45deg);
top: -10%;
right: 0;
}
but that not something I want
You can achieve something like the shape using the clip-path property. Here's an example.
The purple area actually covers the whole container, but the clip-path set on it clips it to the polygon defined by the points 0 0, 100% 0, 35% 60%, 0 0 where 0, 0 is the top-left corner of the container and 100%, 100% would be the bottom-right corner.
.container {
width: 300px;
height: 200px;
border: 1px solid black;
position: relative;
display: flex;
}
.accent {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
background-color: purple;
clip-path: polygon(0 0, 100% 0, 35% 60%, 0 0);
}
.image {
width: 125px;
height: 125px;
background-color: lightgray;
border-radius: 125px;
margin: auto;
z-index: 1;
}
<div class="container">
<div class="accent"></div>
<div class="image"></div>
</div>

How can I put pseudo element behind parent?

I looked for solutions and tried all the suggestions from this SO, but I failed all of that.
I wanna make a border as peseudo element behind parent.
.member__profile-container {
flex-basis: 50rem;
position: relative;
z-index: 4;
}
.member__profile {
padding-top: 150%;
background-image: url('../images/irene.jpg');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
box-shadow: 0 -1rem .5rem 1rem rgba(0,0,0,0.3);
margin-right: 4rem;
transform: rotate(-5deg) translateX(-10%);
animation: expand 1s ease .5s forwards;
}
.member__profile:before {
content: ' ';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
border: 10px solid white;
transform: rotate(-5deg) translateX(-10%);
animation: expand 1s ease .5s forwards;
}
<div class="member__profile-container">
<div class="member__profile"></div>
</div>
Result is like below, but border must be behind parent.
NOT WORKING EXAMPLE
To make it work I had to modify your html a bit. Because of the transformation in .member__profile a stacking context is created at this level and since the ::before element is a descendant of his element, z-index will only move the pseudo element inside .member__profile.
HTML
<div class="member__profile-container">
<div class="member__profile"></div>
<!-- moved the pseudo-element to a sibling element -->
<!-- removing 'the transform' inside .member__profile and
keeping the pseudo element would also work -->
<div class="member__undercover"></div>
</div>
CSS
.member__profile-container {
/* creating a stacking context on the parent */
position: relative;
z-index: 1;
flex-basis: 50rem;
/* added color to make position clearer */
background-color: green;
}
.member__profile {
position: relative;
padding-top: 150%;
background-image: url('../images/irene.jpg');
/* added color to make position clearer */
background-color: red;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
box-shadow: 0 -1rem .5rem 1rem rgba(0, 0, 0, 0.3);
margin-right: 4rem;
transform: rotate(-5deg) translateX(-10%);
z-index: 0;
}
.member__undercover {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
border: 10px solid white;
transform: rotate(-5deg) translateX(-10%);
/* added color to make position clearer */
background-color: blue;
z-index:-1;
}
By using "position: relative; z-index: 1;" on the container I create a stacking context on this level and can reorder freely it's children with z-index.
If you use z-index without creating a stacking context in the container then you will be using a stacking context somewhere else where one has been created in your document, or ultimately the body if none exist before.
If you want the border behind the container not the profile, you just need to move
"position: relative; z-index: 1;" up one parent (not copy it, move it).
To understand more about the stacking context : MDN, The stacking context
You need to apply a negative z-index value to the pseudo-element.
e.g. z-index: -6
Working Example:
div {
width: 100px;
height: 180px;
margin: 20px 60px;
background-color: rgb(255, 0, 0);
}
div::after {
content: '';
position: absolute;
top: -6px;
left: 2px;
z-index: -6;
width: 100px;
height: 180px;
margin: 20px 60px;
border: 6px solid rgb(0, 0, 0);
transform: rotate(-30deg);
}
<div></div>
Further Reading:
https://developer.mozilla.org/en-US/docs/Web/CSS/z-index
Try adding a negative z-index to your pseudo element.
Eg.
.yourclass:: pseudoelement {
z-index: -1;
}

Hover effect on background image

I've added a black transparency to appear when they hover on a background image on my site. I have a h2 tag which also appears on the hover but sits behind the dark transparency where as I want it on top of it! Is there a solution to this?
<div class="img-option">
<div class="content">
<h2>example<\h2>
<\div>
<\div>
CSS:
.img-option
Background image Position relative Background repeat no repeat Background Size cover .img-option:hover Filter: brightness (.6)
Thanks
.img-option {
background-image: url(https://static.vecteezy.com/system/resources/previews/000/106/719/original/vector-abstract-blue-wave-background.jpg);
position: absolute;
height: 200px;
width: 400px;
}
.img-option:after,
h2:before {
position: absolute;
transition: all 0.2s;
-webkit-transition: all 0.2s;
}
.img-option:after {
content: '';
opacity: 0;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.1);
width: 100%;
height: 100%;
}
h2:before {
content: attr(data-content);
top: 60%;
z-index: 1;
box-sizing: border-box;
-moz-box-sizing: border-box;
padding: 2% 3%;
border: solid #000000 1px;
background-color: #ffffff;
}
.img-option:hover:after {
opacity: 1;
}
<div class="img-option">
<div class="content">
<h2 data-content="example"></h2>
</div>
</div>
You would need to assign a z-index to your <h2> element.
z-index: 1;
You can find out more about the the z-index property here.
add .img-option:before element and add style position:absolute and adjust the height like below.
DEMO:-
.img-option {
overflow: hidden;
}
.img-option h2 {
margin: 0;
padding: 20px;
}
.img-option:before {
content: '\00a0';
font-size: 1.5em;
width: 100%;
z-index: 100;
padding: 20px;
overflow: hidden;
position: absolute;
opacity: 0;
overflow: visible;
box-sizing: border-box;
transition: all 0.4s ease-in-out;
position: absolute;
}
.img-option:hover:before {
opacity: 1;
background-color: rgba(0, 0, 0, 0.7);
}
<div class="img-option">
<div class="content">
<h2>example</h2>
</div>
</div>

"position: fixed" not woking when parent has the "transform" CSS property

In my project I have screen which should ease-in from right side of the screen so for that thing I have used transform: translateX(100%) and then changing that to transform: translateX(0%). it works fine I able to achieve the ease-in effect but in that screen I have action button which has css property of Position: Fixed;Bottom: 0px; but this is not working I mean its not sticking in the bottom of the screen.
Here is my JSfiddle : https://jsfiddle.net/sureshpattu/a1seze4x/
Html:
<header>
Heading
</header>
<div class="page__popup page__popup--ease-in-right page__action-btn--visible" style="height: 382px;">
<div class="container">
</div>
<button class="js-action-btn">
SELECT ROOMS
</button>
</div>
Css:
header {
background: #fff;
height: 60px;
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
z-index: 10;
box-shadow: 2px 2px 10px #000;
}
.container {
height: 382px;
}
.page__popup {
position: absolute;
top: 100vh;
z-index: 8;
display: block;
overflow-y: scroll;
max-height: 100vh;
width: 100%;
height: 0;
background: #ffffff;
.js-action-btn {
position: relative;
bottom: -50px;
transition: all 0.25s ease-in-out;
}
//Themes
&--ease-in-bottom {
&.visible {
transition: height 0.25s ease-in-out;
top: 54px;
right: 0;
bottom: 0;
left: 0;
}
}
&--ease-in-right {
transform: translateX(100%);
height: 100vh;
top: 60px;
&.visible {
transition: transform 0.25s ease-in-out;
transform: translateX(0);
}
}
}
.page__action-btn--visible {
.js-action-btn {
background: red;
width: 100%;
height: 30px;
position: fixed;
bottom: 0;
z-index: 10;
box-shadow: 0 7px 4px 10px rgba(0, 0, 0, .12);
}
}
This is not a bug.
Take a look at the spec: The Transform Rendering Model
Specifying a value other than ‘none’ for the ‘transform’ property
establishes a new local coordinate system at the element that it is
applied to.
So according to the spec: the element with fixed positioning will become relative to the element with the transform - not the viewport
As a workaround you could:
1) Use transitions (eg. on the left property) instead of transform (translateX)
2) Remove the position:fixed button from the container which uses transforms

Resources