I distributed some images on the z-axis, then used the mouse as a (fake) 3D camera so that perspective changes while you move the mouse cursor and it works perfectly in Chrome but the button shows up behind all the images in Safari browser so you can't see it. I tried using z-index but it did not work.
<div class="cd-background-wrapper">
<figure class="cd-floating-background">
<img src="img/cd-img-1.jpg" alt="image-1">
<img src="img/cd-img-2.png" alt="image-2">
<img src="img/cd-img-3.png" alt="image-3">
</figure>
<a class="follow fade-in three" id="fade-btn" href="#"><img
class="follow-btn" src="/static/assets/images/Follow.gif"/></a>
</div>
Here is my css:
.cd-floating-background {
position: absolute;
right: 0;
}
.cd-background-wrapper {
width: 100%;
height: 100vh;
overflow: hidden;
background-size: cover;
position: relative;
}
.cd-floating-background {
transform-style: preserve-3d;
}
.cd-floating-background img:first-child {
transform: translateZ(50px);
}
.cd-floating-background img:nth-child(2) {
transform: translateZ(290px);
}
.cd-floating-background img:nth-child(3) {
transform: translateZ(400px);
}
.follow::before,
.follow::after {
position: absolute;
content: "";
transition: all 0.5s;
}
.follow {
position: absolute;
top: 93%;
left: 51%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
Use z-index to change z-axis position. Set it to any number greater than 1 (1 is default value) and set position property.
.follow {
z-index: 2;
position: relative;
}
z index property will help you.
Related
I'm trying to create a css animation that flips a card on click. I've followed the answer posted in this question, but I'd like to know if there's a way to perform the same animation when the class is added and removed.
In this case the card flips in one direction when clicked, and in the opposite direction when clicked again (as the css class is toggled). How could I make it so that the card flips in the same direction every time it is clicked?
Some code from the JSFiddle:
$('.flip-container .flipper').click(function() {
$(this).closest('.flip-container').toggleClass('hover');
$(this).css('transform, rotateY(180deg)');
});
/* flip the pane when hovered */
.flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container,
.front,
.back {
width: 250px;
height: 250px;
}
/* flip speed */
.flipper {
transition: 0.8s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front,
.back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
background-color: #fff;
}
.artist-1 {
background: url(http://img.bleacherreport.net/img/images/photos/003/556/940/edab30087cea36c0ca206fc61a4b10fa_crop_north.jpg?w=630&h=420&q=75) center center no-repeat;
background-size: cover;
}
It has to be done via script (check this SO question). So by editing the example you followed, we can do it this way:
$('.flip-container').each(function(i) {
var thisFlipper = $(this).find('.flipper');
var rotate = 0;
thisFlipper.on('click', function(e) {
rotate += 180;
thisFlipper.css({'transform': 'rotateY('+rotate+'deg)'});
});
});
.flip-container {
perspective: 800px;
}
.flip-container,
.front,
.back {
width: 250px;
height: 250px;
}
/* flip speed */
.flipper {
transition: 0.8s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front,
.back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
}
/* back, initially hidden pane */
.back {
background-color: #ff0000;
transform: rotateY(180deg);
}
.artist-1 {
background: url(http://img.bleacherreport.net/img/images/photos/003/556/940/edab30087cea36c0ca206fc61a4b10fa_crop_north.jpg?w=630&h=420&q=75) center center no-repeat;
background-size: cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flip-container">
<div class="flipper">
<div class="front artist-1">
</div>
<div class="back">
<p>You won</p>
</div>
</div>
</div>
Updated JSFiddle
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
transform: translate(45px,-75px);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
The problem is what when i zoon out/in or resize the brower .pic2
is moving not stay fixed on his original point
Your idea is right yet both SVG images will adjust to the proportion of the available space (do you have only viewBox defined in them, removing the height and width attributes?). So the second image (pic2) will always "bounce" when resizing (but how many web users really do that?).
Maybe define styles for both SVGs in their DIV parent (or "container" element if you wish) by using vw and vh units - instead of pixels, possibly percentages as well - and this will at least give you more predictable result:
<style>
body {
border: 0;
margin: 0;
}
.pic1 {
position: absolute;
width: 100%;
border: 0;
margin: 0;
}
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
z-index: -1;
transform: translate(2.5vw,88vh);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
</style>
<body>
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
</body>
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
transform: translate(45px,-75px);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
The problem is what when i zoon out/in or resize the brower .pic2
is moving not stay fixed on his original point
Your idea is right yet both SVG images will adjust to the proportion of the available space (do you have only viewBox defined in them, removing the height and width attributes?). So the second image (pic2) will always "bounce" when resizing (but how many web users really do that?).
Maybe define styles for both SVGs in their DIV parent (or "container" element if you wish) by using vw and vh units - instead of pixels, possibly percentages as well - and this will at least give you more predictable result:
<style>
body {
border: 0;
margin: 0;
}
.pic1 {
position: absolute;
width: 100%;
border: 0;
margin: 0;
}
.pic1 img{/*Bg Photo*/
width: 100%;
height: auto;
top: 0;
left: 0;
}
.pic2{
position: absolute;
z-index: -1;
transform: translate(2.5vw,88vh);
}
.pic2 img{
transform-origin:center;
width: 50px;
height: 50px;
animation: rotation 2s infinite linear;
}
#keyframes rotation {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
</style>
<body>
<!--BG Photo-->
<div class="pic1"><img src="1.svg"></div>
<!--SVG that will rotate-->
<div class="pic2"><img src="img/vec/gz4.svg" alt=""></div>
</body>
I have a page transition I'm trying to work into my site. I have 2 50% height, 100% width elements, one placed before and after the body (with pseudo-selectors). I would like the 2 elements to slide to the middle of the screen, covering the background content. The transition is triggered when the "is-changing" class is added to the body, via Javascript.
document.getElementById("btn").addEventListener("click", fakeReq);
function fakeReq() {
let body = document.body;
body.classList.add("is-changing");
console.log("class added");
setTimeout(function() {
body.classList.remove("is-changing");
console.log("class removed");
}, 5000);
}
body {
height: 100vh;
width: 100%;
background-color: grey;
}
main {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
}
body::after, body::before {
height: 50vh;
width: 100%;
position: fixed;
left: 0;
background-color: blue;
z-index: 10;
}
body::before {
top: 0;
transform: translateY(-100%);
}
body::after {
bottom: 0;
transform: translateY(100%);
}
body.is-changing::after, body.is-changing::before {
transform: translateY(0);
}
.loading-bar {
position: fixed;
height: 2px;
width: 90%;
}
.loading-bar::before {
position: absolute;
background-color: aqua;
left: 0;
top: 0;
height: 100%;
width: 100%;
transform: scaleX(0);
transform-origin: left center;
}
.is-changing .loading-bar::before {
transform: scaleX(1);
}
<body>
<main>
<div class="index main-content">
<h1>Home Page</h1>
<button id="btn">html request</button>
</div>
</main>
</body>
It looks to me like you're running into two issues.
The first issue is that you forgot to include the content attribute in your pseudo elements (often this will be empty, like content: ""). Without this attribute, your pseudo elements will not exist in the DOM. Running your code snippet and inspecting it confirms this, since the pseudo elements are nowhere to be found.
Second, you're creating multiple pseudo elements. body::before is it's own pseudo element, and body.is-changing::before is a separate pseudo element. If you are hoping to create a constant set of elements that act as "doors" for a loading display, you may want to consider creating two real elements that sit in position: fixed above and below the viewport, and then slide in or out when a class is added. Perhaps these could be div.upper-door and div.lower-door.
Also, it looks to me like you're in need of a transition for your transform, or else the pseudo elements will just "snap" back and forth. You can take control of the position of your elements at different points during this transition by using a css animation. Your JavaScript would largely remain the same, except for targeting the .upper-door and .lower-door divs using document.querySelector(), or simply using IDs rather than classes and targeting with getElementById(), if that makes more sense for you. Your css might look like this:
div.upper-door {
top: 0;
transform: translateY(-100%);
}
div.upper-door.is-changing {
animation-duration: 5s;
animation-name: upper-door-closeopen;
}
div.lower-door {
bottom: 0;
transform: translateY(100%);
}
div.lower-door.is-changing {
animation-duration: 5s;
animation-name: lower-door-closeopen;
}
#keyframes upper-door-closeopen {
0% {
transform: translateY(-100%);
}
25% {
transform: translateY(0);
}
75% {
transform: translateY(0);
}
100% {
transform: translateY(-100%);
}
}
#keyframes lower-door-closeopen {
0% {
transform: translateY(100%);
}
25% {
transform: translateY(0);
}
75% {
transform: translateY(0);
}
100% {
transform: translateY(100%);
}
}
The css animation will be triggered when .is-changing is added to the element. As you experiment, you may find different permutations of this solution (such as using event listeners if a button click is triggering the loading screen) to be ideal.
There is a great resource on MDN for css animations if you would like more information.
You missed to add the content property on the pseudo-elements which is mandatory to make them available on the page. You also missed to add the transition property on the pseudo-elements to achieve your animation of sliding up/down.
Here's a snippet containing a working demo, I only used the code that is related to your issue:
document.getElementById("btn").addEventListener("click", fakeReq);
function fakeReq() {
let body = document.body;
body.classList.add("is-changing");
console.log("class added");
setTimeout(function() {
body.classList.remove("is-changing");
console.log("class removed");
}, 5000);
}
body {
height: 100vh;
width: 100%;
background-color: grey;
position: relative; /* not really related to your issue but, to make sure that the body's pseudo-elements are positioned relative to the body */
}
main {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
}
body::after, body::before {
content: ""; /* make the pseudo-elements available */
height: 50vh;
width: 100%;
position: fixed;
left: 0;
background-color: blue;
z-index: 10;
transition: all .8s ease-out; /* allow the animation, change this rule per your requirements */
}
body::before {
top: 0;
transform: translateY(-100%);
}
body::after {
bottom: 0;
transform: translateY(100%);
}
body.is-changing::after, body.is-changing::before {
transform: translateY(0);
}
<body>
<main>
<div class="index main-content">
<h1>Home Page</h1>
<button id="btn">html request</button>
</div>
</main>
</body>
Learn more about after pseudo-element.
Learn more about before pseudo-element.
You can use the following
document.getElementById("btn").addEventListener("click", fakeReq);
function fakeReq() {
let body = document.body;
body.classList.add("is-changing");
console.log("class added");
setTimeout(function() {
body.classList.remove("is-changing");
console.log("class removed");
}, 5000);
}
body {
height: 100vh;
width: 100%;
background-color: grey;
}
main {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
}
body::after, body::before {
content:'';
height: 50vh;
width: 100%;
position: fixed;
left: 0;
background-color: blue;
z-index: 10;
}
body::before {
content:'';
top: 0;
transform: translateY(-100%);
transition: .5s all;
}
body::after {
content:'';
bottom: 0;
transform: translateY(100%);
}
body.is-changing::after, body.is-changing::before {
content:'';
transform: translateY(0);
}
.loading-bar {
position: fixed;
height: 2px;
width: 90%;
}
.loading-bar::before {
content:'';
position: absolute;
background-color: aqua;
left: 0;
top: 0;
height: 100%;
width: 100%;
transform: scaleX(0);
transform-origin: left center;
}
.is-changing,.loading-bar::before {
transform: scaleX(1);
}
<body>
<main>
<div class="index main-content">
<h1>Home Page</h1>
<button id="btn">html request</button>
</div>
</main>
</body>
Here is a simple horizontal flip animation - http://jsfiddle.net/vntajmgh/2/
and I see 2 issues:
Open the url in chrome. Hover over the red div. The flip is ok, but the background color for the back div(blue) is not applied.
Open the url in firefox. The flip is like stuck. I can see the blue colored back div sometimes.
I guess it's 'stuck' here because the height is 100vh, which when reduced works fine, but should it not work with the full height too?
.flip-container {
width: 150px;
height: 100vh;
perspective: 800px;
color: #fff;
position: relative;
}
.flipper {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: transform linear 0.6s;
}
.flipper div {
margin: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flipper .front {
background: red;
}
.flipper div:after {
content:"";
display: block;
position: absolute;
top: 0;
left: 0;
background-image: url("http://www.transparenttextures.com/patterns/3px-tile.png");
width: 100%;
height: 100%;
opacity: 0.5;
z-index: 1;
}
.flipper .back {
background: blue;
transform: rotateY(180deg);
}
.flipper:hover {
transform: rotateY(180deg);
}
<div class="flip-container">
<div class="flipper">
<div id="1front" class="front">1-front</div>
<div id="1back" class="back">1-back</div>
</div>
</div>
UPDATE:
Here is the working fiddle - http://jsfiddle.net/gf3g8sz1/1/
Add an overflow hidden to the parent div(flip-container). When we are using 100vh(view port height) with rotate transform property, its actually taking more height than the view port has. so hide it by using overflow hidden.
css
.flip-container {
overflow:hidden;
}
To get the same hover effect in both browser you have to modify the hover CSS.
DEMO
removing:
backface-visibility: hidden;
will make the back color visible
The problem in Chrome is caused by the pseudo element. I have changed the way to get the image blended with red without an pseduo element, and now it works OK.
The problem in FF is caused by the reduced-disappeared size of the element that receives the hover. I have changed the hover so that it is triggered by the container, and now it works also ok.
It is always a good idea to avoid using hover on transformed elements, they usually give some kind of problems
.flip-container {
width: 150px;
height: 100vh;
perspective: 800px;
color: #fff;
position: relative;
}
.flipper {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;
transition: transform linear 0.6s;
}
.flipper div {
margin: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flipper .front {
background: red;
background-image: linear-gradient(rgba(255,0,0,0.5),rgba(255,0,0,0.5)), url("http://www.transparenttextures.com/patterns/3px-tile.png");
}
.flipper .back {
background: blue;
transform: rotateY(180deg);
}
.flip-container:hover .flipper {
transform: rotateY(180deg);
}
<div class="flip-container">
<div class="flipper">
<div id="1front" class="front">1-front</div>
<div id="1back" class="back">1-back</div>
</div>
</div>