css transition for page transitioin not triggering - css

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>

Related

CSS card flip effect - how to make it flip in the same direction with every click?

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

I have one SVG that is rotate around a svg but is not fixed

<!--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>

Svg anomation rotate is not fixed [duplicate]

<!--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>

Making pure css image slider responsive

The following pure css slider is working well, but I need to make it responsive. I've tried replacing the pixel-based sizes with percentages and with vw, but it doesn't line up. I'd be grateful for any ideas.
Here's the html:
<section class="slideshow">
<div class="slideshow-container slide">
<img src="images/anim/home-animation1.jpg" alt="pills">
<img src="images/anim/home-animation2.jpg" alt="scientist">
<img src="images/anim/home-animation3.jpg" alt="chemical structure">
<img src="images/anim/proudmembermassbio.jpg" alt="proud member of MassBio"> </div>
</section>
And the css:
/*general styles*/
html { box-sizing: border-box; }
*, *:before, *:after { box-sizing: inherit; }
/* SLIDESHOW STYLES */
.slideshow-container {
width: 1400px; /* the entire "stage" */
font-size: 0;
transition: 1s ease;
height: 315px;
}
.slideshow-container:hover { animation-play-state: paused; }
.slideshow { /* the visible "stage" */
width: 350px;
margin: 1rem auto -1rem;
overflow: hidden;
border: solid 1px white;
}
img, .text-container {
width: 350px;
height: auto;
display: inline-block;
font-size: 16px;
text-align: center;
}
.text-container { /* for text slides */
height: 195px;
position: relative;
}
.slide { animation: slide 10s ease infinite; }
#keyframes slide {
0% { transform: translateX(0%); }
12.5% { transform: translateX(0%); }
25% { transform: translateX(-25%); }
37.5% { transform: translateX(-25%); }
50% { transform: translateX(-50%); }
62.5% { transform: translateX(-50%); }
75% { transform: translateX(-75%); }
87.5% { transform: translateX(-75%); }
99% { transform: translateX(-75%); }
100% { transform: translateX(0); }
}
.p {
margin-top: 140px;
text-align: center;
}
Maybe this is too late for the user that posted this question, but can be helpful for someone else that want a pure responsive CSS slider.
I have created a working example in this CodePen that is working as requested using percentages for widths and in the animation, and for this reason it is responsive and works really well in each resolutions.
All the main solution to have the responsiveness is here:
slider__container {
display: flex;
position: relative;
animation: 30s slide infinite;
font-size: 0;
width: 1000%; /* because I am using 10 slides */
}
The width should be calculated accordingly to how many slides are there in the slider: slides x 100% (slides times 100%, in my example 1000%).

Rotate multiple elements at the same time

I have list of items (li) that are stacked around in circle using transformation. Items have different angle depending on its initial position in the circle:
transform: rotate(0deg) translateY(-75px) rotate(-0deg)
transform: rotate(45deg) translateY(-75px) rotate(-45deg)
... etc
last negative rotate is to rotate ccw to keep element in up position.
translate Y is radius offset.
What I would like to accomplish is to rotate all items around for various number of degrees or let's say if one item gets clicked I would like all items to rotate so that clicked item will be on the top position (0deg).
What would be best way to do this? Looking for some clever ways.. All items should ofcourse rotate at the same time - like a dialer on the old phone.
With some jQuery, you can change the class of the container and assign the rotation value to the container :
fiddle
$('.one').click(function() {
$('#container').removeClass('second third fourth').addClass('first');
});
$('.two').click(function() {
$('#container').removeClass('first third fourth').addClass('second');
});
$('.three').click(function() {
$('#container').removeClass('first second fourth').addClass('third');
});
$('.four').click(function() {
$('#container').removeClass('first second third').addClass('fourth');
});
#container {
position: relative;
width: 30%;
padding-bottom: 30%;
margin: 10% auto;
transition: transform .5s ease-out;
}
.elt {
position: absolute;
padding: 2%;
background: teal;
cursor: pointer;
transition: transform .5s ease-out;
}
.one { top: 0; left: 47.5%; }
.two { top: 47.5%; right: 0; }
.three { bottom: 0; left: 47.5%; }
.four { top: 47.5%; left: 0; }
#container.first { transform: rotate(0deg); }
#container.first div { transform: rotate(0deg); }
#container.second { transform: rotate(-90deg); }
#container.second div { transform: rotate(90deg); }
#container.third { transform: rotate(180deg); }
#container.third div { transform: rotate(-180deg); }
#container.fourth { transform: rotate(90deg); }
#container.fourth div { transform: rotate(-90deg); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="elt one">1</div>
<div class="elt two">2</div>
<div class="elt three">3</div>
<div class="elt four">4</div>
</div>

Resources