CSS animation : loading - css

I am currently learning HTML/CSS3 basics and I came to the transition/animation chapter. To test my understanding of the subject I threw myself a challenge : create a loading page made out of CSS-only animation.
The charging bar is made of 5 white rectangles with red borders, that go red every 0,1 to show that it is charging, and at the end of the loop go blanck again and repeat.
So I first tried to create an animation white first rectangle's background-color changed to red at 20% of the 0,5s animation and so on...
It failed, because I have no clue of how to change multiple element within the same animation.
Then I figured that it would be easier to make each rectangle from state "blanck" to state "red" even though it takes a lot more lines of code.
Only problem, as you can see with my code below, the first rectangle doesn't go red whereas the others do, and I can make it go backward at the end.
Could anyone give me a clue about how to make this transition works, then give me a hint/documentation about how to make it works with an animation ?
<!DOCTYPE html>
<html>
<head>
<title>Loading</title>
<link rel="stylesheet" type="text/css" href="loading.css">
</head>
<body>
<div class="big_div">
<div id="title"> <p class="main_title"> L O A D I N G</p> </div>
<div class="carre" id="premiers_carre"></div>
<div class="carre" id="deuxieme_carre"></div>
<div class="carre" id="troisieme_carre"></div>
<div class="carre" id="quatrieme_carre"></div>
<div class="carre" id="cinquieme_carre"></div>
</div>
</body>
</html>
p
{
font-family: "Press start 2P";
}
#title {
position: absolute;
left : 530px;
top : 280px ;
}
.big_div
{
width: 1250px;
height: 700px;
display :flex;
flex-direction : row;
justify-content: center;
align-items: center;
}
.carre
{
background-color: white;
border: 1px red solid;
width: 80px;
height: 10px;
margin-right: 5px;
}
#premier_carre
{
transition-property: background-color;
transition-delay: 0.1s;
}
#deuxieme_carre
{
transition-property: background-color;
transition-delay: 0.2s;
}
#troisieme_carre
{
transition-property: background-color;
transition-delay: 0.3s;
}
#quatrieme_carre
{
transition-property: background-color;
transition-delay: 0.4s;
}
#cinquieme_carre
{
transition-property: background-color;
transition-delay: 0.5s;
}
.big_div:hover #premier_carre
{
background-color: red;
}
.big_div:hover #deuxieme_carre
{
background-color: red;
}
.big_div:hover #troisieme_carre
{
background-color: red;
}
.big_div:hover #quatrieme_carre
{
background-color: red;
}
.big_div:hover #cinquieme_carre
{
background-color: red;
}

Bonjour ! You wrote id="premiers_carre" in your code and #premier_carre in your CSS. Simple as that.
Here is your code fixed and improved for a more DRY approach (you defined a class, so why not use it?):
p
{
font-family: "Press start 2P";
}
#title {
position: absolute;
left : 530px;
top : 280px ;
}
.big_div
{
width: 1250px;
height: 700px;
display :flex;
flex-direction : row;
justify-content: center;
align-items: center;
}
.carre
{
background-color: white;
border: 1px red solid;
width: 80px;
height: 10px;
margin-right: 5px;
transition-property: background-color;
}
#premier_carre
{
transition-delay: 0.1s;
}
#deuxieme_carre
{
transition-delay: 0.2s;
}
#troisieme_carre
{
transition-delay: 0.3s;
}
#quatrieme_carre
{
transition-delay: 0.4s;
}
#cinquieme_carre
{
transition-delay: 0.5s;
}
.big_div:hover .carre
{
background-color: red;
}
<!DOCTYPE html>
<html>
<head>
<title>Loading</title>
<link rel="stylesheet" type="text/css" href="loading.css">
</head>
<body>
<div class="big_div">
<div id="title"> <p class="main_title"> L O A D I N G</p> </div>
<div class="carre" id="premier_carre"></div>
<div class="carre" id="deuxieme_carre"></div>
<div class="carre" id="troisieme_carre"></div>
<div class="carre" id="quatrieme_carre"></div>
<div class="carre" id="cinquieme_carre"></div>
</div>
</body>
</html>

Well, this is what I have so far for your question:
<!DOCTYPE html>
<html>
<head>
<link rel="fluid-icon" href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Light_Blue_Circle.svg/1200px-Light_Blue_Circle.svg.png" title="HTML">
<link rel="mask-icon" href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Light_Blue_Circle.svg/1200px-Light_Blue_Circle.svg.png" color="#0096ff">
<link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Light_Blue_Circle.svg/1200px-Light_Blue_Circle.svg.png">
<link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Light_Blue_Circle.svg/1200px-Light_Blue_Circle.svg.png"><style>#splash {
position: absolute; width: 100%; height: 100%; top: 0; left: 0;
display: flex; align-items: center; justify-content: center;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; color: #keyframes loadingColorChange;
}
.tw-loaded #splash, #splash-content { display: none; }
#splash[splash-theme="dark"] { background-color: #303030; color: #303030; }
#splash-spinner:after {
content: " "; display: block; width: 64px; height: 64px;
border-radius: 50%; border: 6px solid; border-color: currentColor transparent currentColor transparent;
animation: splash-spinner 1s linear infinite;
}
#keyframes splash-spinner {
0% { transform: rotate(0deg); }
50% { transform: rotate(180deg); }
100% { transform: rotate(360deg); }
}
body {
animation-name: bgColorChange;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-delay: none;
animation-name: loadingColorChange;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-delay: none;
}
#keyframes bgColorChange {
0% { background-color: #ea4335; }
12.5% { background-color: #fbbc05; }
25% { background-color: #34a853; }
37.5% { background-color: #4285f4; }
50% { background-color: #34a853; }
62.5% { background-color: #fbbc05; }
75% { background-color: #fbbc05; }
100% { background-color: #ea4335; }
}
#keyframes loadingColorChange {
0% { color: #4285f4; }
12.5% { color: #34a853; }
25% { color: #fbbc05; }
37.5% { color: #ea4335; }
50% { color: #fbbc05; }
62.5% { color: #34a853; }
100% { color: #4285f4; }
}
</style><link rel="dns-prefetch" href="https://trampoline.turbowarp.org/"><link rel="dns-prefetch" href="https://projects.scratch.mit.edu/"><link rel="dns-prefetch" href="https://assets.scratch.mit.edu/"></head><body><div id="splash" aria-hidden="true"><div id="splash-content"><div id="splash-spinner"></div></div></div><script>(function() {
document.querySelector('#splash-content').style.display = 'block';
try {var localTheme = localStorage.getItem('tw:theme');} catch (e) {}
if (localTheme ? localTheme === 'dark' : window.matchMedia('(prefers-color-scheme: dark)').matches) document.querySelector('#splash').setAttribute('splash-theme', 'dark');
})();</script><div id="app">Loading...</div><script src="https://turbowarp.org/js/vendors~addon-settings~credits~editor~embed~fullscreen~player.57d02a22479dd55504bc.js"></script><script src="https://turbowarp.org/js/vendors~editor~embed~fullscreen~player.2ebfbf3346f8d17ad60d.js"></script><script src="https://turbowarp.org/js/addon-settings~addons~editor~fullscreen~player.976423b27ac04efde22e.js"></script><script src="https://turbowarp.org/js/editor~embed~fullscreen~player.d227a5ae0c7b2012a7a2.js"></script><script src="https://turbowarp.org/js/player.1fd251802eabb68ba5fe.js"></script></body>
</body>
</html>
Also all credit to Github

Related

Using :nth-child selector with CSS grid gives unexpected behaviour [duplicate]

This question already has answers here:
Can I combine :nth-child() or :nth-of-type() with an arbitrary selector?
(8 answers)
nth-of-type vs nth-child
(7 answers)
Closed 3 years ago.
I am using a CSS grid for positioning elements and having a fadeIn effect. But after placing text, below the images and using :nth-child() CSS property to select each h4 tag, Leads to 4th and 5th images not getting displayed(as their opacity is not changed). I guess, nth-child selects 1st 5 elements in the grid, irrespective of whether it is h4 or not.
Kindly suggest where I am wrong.
Here's a link to JSFiddle:- https://jsfiddle.net/aew2tjhr/1/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha256-L/W5Wfqfa0sdBNIKN9cG6QA5F2qx4qICmU2VgLruv9Y=" crossorigin="anonymous" />
<style>
.container {
margin-top: 500px;
}
.working-process {
background-color: #000;
}
.working-process h2 {
color: #fff;
margin-bottom: 4rem;
}
.emphasize {
color: #ff7810;
}
.single-work {
display: grid;
grid-template-columns: repeat(5, 200px);
grid-template-rows: 150px;
grid-auto-rows: 150px;
justify-content: center;
}
.single-work h4 {
color: #000;
grid-row: 2/3;
}
.single-work-icon {
position: relative;
height: 120px;
width: 120px;
border: 1px solid #ff7810;
background-color: #e49152;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
flex-basis: 120px;
margin-right: 4rem;
}
.single-work-icon:not(:nth-child(5))::after {
content: " ";
position: absolute;
top: 50%;
left: 50%;
border-right: 70px solid #fff;
width: 70px;
height: 2px;
}
.single-work,
.single-work>.single-work-icon {
opacity: 0;
}
.single-work.show {
animation: showWorks 1s ease-in-out 0.5s forwards;
}
.single-work.show>.single-work-icon:nth-child(1) {
animation: showWorks 1s ease-in-out 0.5s forwards;
}
.single-work.show>.single-work-icon:nth-child(2) {
animation: showWorks 1s ease-in-out 1.5s forwards;
}
.single-work.show>.single-work-icon:nth-child(3) {
animation: showWorks 1s ease-in-out 2.5s forwards;
}
.single-work.show>.single-work-icon:nth-child(4) {
animation: showWorks 1s ease-in-out 3.5s forwards;
}
.single-work.show>.single-work-icon:nth-child(5) {
animation: showWorks 1s ease-in-out 4.5s forwards;
}
.single-work.show .single-work-icon:nth-child(1)::after {
animation: slideInRight 2s ease-in-out 0s forwards;
}
.single-work.show .single-work-icon:nth-child(2)::after {
animation: slideInRight 1s ease-in-out 2s forwards;
}
.single-work.show .single-work-icon:nth-child(3)::after {
animation: slideInRight 1s ease-in-out 3s forwards;
}
.single-work.show .single-work-icon:nth-child(4)::after {
animation: slideInRight 1s ease-in-out 4s forwards;
}
#keyframes showWorks {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes showArrows {
0% {
opacity: 0;
transform: translateX(0);
}
100% {
opacity: 1;
transform: translateX(100%);
}
}
#keyframes slideInRight {
0% {
left: 50%;
}
100% {
left: 100%;
}
}
</style>
</head>
<body>
<section class="pos-r working-process">
<div class="container">
<h2 class="text-center">How <span class="emphasize">Digital Marketing Agency</span> work</h2>
<div class="row">
<div class="col-lg-12 col-md-12 ml-auto md-mt-5">
<div class="single-work">
<div class="single-work-icon">
<img src="img/working_process/research.png" alt="Research" />
</div>
<h4>Research</h4>
<div class="single-work-icon">
<img src="img/working_process/design.png" alt="Design" />
</div>
<h4>Design</h4>
<div class="single-work-icon">
<img src="img/working_process/Implement.png" alt="Implement" />
</div>
<h4>Implement</h4>
<div class="single-work-icon">
<img src="img/working_process/measure.png" alt="Measure" />
</div>
<h4>Measure</h4>
<div class="single-work-icon">
<img src="img/working_process/result.png" alt="Result" />
</div>
<h4>Result</h4>
</div>
</div>
</div>
</div>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script>
function isInViewport(element) {
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
// console.log(elementTop, elementBottom, viewportTop, viewportBottom);
return elementBottom > viewportTop && elementTop < viewportBottom;
}
$(window).on("resize scroll", function () {
if (isInViewport(document.querySelector(".working-process"))) {
document.querySelector(".single-work").classList.add("show");
} else {
if (
document.querySelector(".single-work").classList.contains("show")
) {
document.querySelector(".single-work").classList.remove("show");
}
}
});
</script>
</body>
</html>

How can I animate several elements on the same orbital path in sequence?

I want to create an animation showing a few circles moving one after another in orbit. Currently, I created three circles but they appear on separate lines and thus move in a circular movement, but as a line. How can I change the code to achieve the movement that I want? Here's a codepen with the current status.
Here's the code that I use:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Lato', sans-serif;
font-size: 18px;
line-height: 1.6;
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
}
.loader {
height: 50px;
animation: rotate 6s linear infinite;
}
.circle {
display: inline-block;
background-color: purple;
height: 40px;
width: 40px;
border-radius: 50%;
transform: scale(0);
animation: grow 1.5s linear infinite;
margin: -20p;
}
.circle:nth-child(2) {
background-color: palevioletred;
transform: scale(0);
animation-delay: 0.20s;
}
#keyframes rotate {
to {
transform: rotate(360deg)
}
}
#keyframes grow {
50% {
transform: scale(1);
}
}
<div class="loader">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
I'm creating full-size "plates" which I can set to an initial rotation point. The circles end up as pseudo-elements on the plates (to avoid extra markup). Modify the initial rotation values to bring the circles closer together.
.loader {
width: 100px;
height: 100px;
animation: rotate 6s linear infinite;
position: relative;
}
.plate {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.plate:nth-child(2) {
transform: rotate(120deg);
}
.plate:nth-child(3) {
transform: rotate(240deg);
}
.plate:before {
content: '';
position: absolute;
background-color: red;
height: 40px;
width: 40px;
border-radius: 50%;
transform: scale(0);
animation: grow 1.5s linear infinite;
}
.plate:nth-child(2):before {
background: green;
}
.plate:nth-child(3):before {
background: blue;
}
#keyframes rotate {
to {
transform: rotate(360deg);
}
}
#keyframes grow {
50% {
transform: scale(1);
}
}
* {
box-sizing: bordr-box;
margin: 0;
padding: 0;
}
body {
font-family: "Lato", sans-serif;
font-size: 18px;
line-height: 1.6;
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
}
<body>
<div class="loader">
<div class="plate"></div>
<div class="plate"></div>
<div class="plate"></div>
</div>
</body>
#isherwood provided a great solution that's easily workable in most modern browsers. But let's say you want more complex motion, like an elliptical orbit.
SVG Animation
You could build the whole thing into an SVG since that supports lots of cool animation while being quite performant. But building SVGs and animating them from scratch is kinda complicated. Luckily, there are tools to help. Here's a few examples: Snapsvg (code library), SVGGator (Web-based animation tool) or Bodymovin (After Effects workflow).
But let's say you want to stick with what can be done in HTML/CSS.
CSS Motion Path
Sadly support is, not great as of Summer 2019 but it will likely be improving. If your audience is using the right browsers (Chrome, Opera, Edge or Chromium based mobile browsers). It's actually pretty easy to use but there are some gotchas. For example, it appears that only the path() property works right now. So you can't use shape keywords like circle() or ellipse() though they're in the spec.
main {
position: relative;
margin: 20px;
}
main,svg {
width: 100px;
height: 100px;
}
path {
stroke-width: 1px;
}
svg {
position:absolute;
opacity: 0.5;
}
#c1 {
stroke: red;
}
#c2 {
stroke: blue;
}
#c3 {
stroke: green;
}
div[class*="c"] {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
box-shadow: 5px 5px 10px 0 rgba(0,0,0,0.3);
}
.c1 {
background-color: red;
offset-path: path('M50,2 C78.2166667,2 98,22.2364005 98,50.5 C98,78.7635995 75.5694444,99 50,99 C24.4305556,99 2,76.5476997 2,50.5 C2,24.4523003 21.7833333,2 50,2 Z');
animation: moveme 5s ease-in-out infinite;
}
.c2 {
background-color: blue;
offset-path: path('M55,13 C80.2774306,13 98,30.9415509 98,56 C98,81.0584491 77.9059606,99 55,99 C32.0940394,99 12,79.0938368 12,56 C12,32.9061632 29.7225694,13 55,13 Z');
animation: moveme 5.25s linear infinite;
}
.c3{
background-color: green;
offset-path: path('M36.0041619,30.5873511 C61.3414991,12.7718541 90.4202796,4.99194919 98.2799065,16.2635432 C106.139533,27.5351371 85.805943,52.9370587 62.845696,69.0811471 C39.885449,85.2252355 7.31148243,93.0730731 1.30061213,84.4528052 C-4.71025818,75.8325372 10.6668246,48.4028481 36.0041619,30.5873511 Z');
animation: moveme 5.5s linear infinite;
}
#keyframes moveme {
100% {
motion-offset: 100%;
offset-distance: 100%;
}
}
<main>
<!-- paths for example -->
<svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="orbit" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M50,2 C78.2166667,2 98,22.2364005 98,50.5 C98,78.7635995 75.5694444,99 50,99 C24.4305556,99 2,76.5476997 2,50.5 C2,24.4523003 21.7833333,2 50,2 Z" id="c1"></path>
<path d="M55,13 C80.2774306,13 98,30.9415509 98,56 C98,81.0584491 77.9059606,99 55,99 C32.0940394,99 12,79.0938368 12,56 C12,32.9061632 29.7225694,13 55,13 Z" id="c2"></path>
<path d="M36.0041619,30.5873511 C61.3414991,12.7718541 90.4202796,4.99194919 98.2799065,16.2635432 C106.139533,27.5351371 85.805943,52.9370587 62.845696,69.0811471 C39.885449,85.2252355 7.31148243,93.0730731 1.30061213,84.4528052 C-4.71025818,75.8325372 10.6668246,48.4028481 36.0041619,30.5873511 Z" id="c3"></path>
</g>
</svg>
<div class="c1"></div>
<div class="c2"></div>
<div class="c3"></div>
</main>

CSS - How to reverse the Animation on removal

I have a page in my website where I display to panels, side by side. I'm displaying these 2 panels in 2 views: Horizontal and Vertical. I have a button that switches between these 2 views. I'm trying to add some CSS animation on the transition between the two views. However my animation work only in one direction (from Vertical to Horizontal), the reverse animation appear in the wrong order.
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: width, height;
-webkit-transition-duration: 2s, 2s;
-webkit-transition-delay: 0s, 2s;
-webkit-transition-timing-function: ease;
display: inline-block;
width: 50%;
height: 100%;
}
.vertical-box
{
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.addClass("vertical-box");
}
else
{
boxes.removeClass("vertical-box");
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
-webkit-transition-property: height, width; /* swapped */
-webkit-transition-duration: 0.5s, 0.5s;
-webkit-transition-delay: 0s, 0.5s;
-webkit-transition-timing-function: ease;
display: block; /* TRY THIS */
float: left; /* AND THIS */
width: 50%;
height: 100%;
}
.vertical-box
{
-webkit-transition-property: width, height; /* added */
width: 100%;
height: 50%;
}
.a { background-color: darkred; }
.b { background-color: darkorchid; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>
Explained
Added transition-property: width, height; to .vertical-box
Desired behavior: expand width, shink height; expand height shrink width.
.box has transition-property first height then width
.vertical-box overwrites and flippes transition-property: first width, then height
You might think this is the wrong order, but as soon as you click the class is applied immideately, but the transition takes time. So you transition from .box to .vertical-box with the transition-property of .vertical-box and vise versa.
EDIT Answer using animation (little hacky, since i found no way to reset current keyframe)
var isVertical = false;
var boxes = $(".box");
function toggleViews()
{
isVertical = !isVertical;
if (isVertical)
{
boxes.removeClass("vertical-box-reverse");
window.requestAnimationFrame(function() { // apply to forget animation state
window.requestAnimationFrame(function() { // re-apply animation
boxes.addClass("vertical-box");
});
});
}
else
{
boxes.removeClass("vertical-box");
window.requestAnimationFrame(function() { // apply to forget animation state
boxes.addClass("vertical-box-before-reverse"); // apply to set animation end-like state
window.requestAnimationFrame(function() { // re-apply animation
boxes.removeClass("vertical-box-before-reverse");
boxes.addClass("vertical-box-reverse");
});
});
}
}
.container
{
display: block;
width: 400px;
height: 150px;
border: 2px solid black;
overflow: hidden;
}
.box
{
display: block;
float: left;
width: 50%;
height: 100%;
}
.a.vertical-box { animation: boxAnimationA 1s normal forwards; }
.b.vertical-box { animation: boxAnimationB 1s normal forwards; }
.a.vertical-box-reverse { animation: boxAnimationA 1s ease-in reverse forwards; }
.b.vertical-box-reverse { animation: boxAnimationB 1s ease-in reverse forwards; }
.vertical-box-before-reverse { width: 100%; height: 50%; }
.a { background-color: darkred; }
.b { background-color: darkorchid; }
/* Keyframes */
#keyframes boxAnimationA {
0% { width: 50%; }
50% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
#keyframes boxAnimationB {
0% { width: 50%; }
50% { width: 0%; height: 100%; }
51% { width: 100%; height: 100%; }
100% { width: 100%; height: 50%; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<button onclick="toggleViews()">toggle</button>
<div class="container">
<div class="a box">A</div><div class="b box">B</div>
</div>
</body>
</html>

CSS classes conflicting

I am trying to animate a card flipping face up and then fading out. I do this by adding a class 'flipped' on click and a second 'vanish' after a timeout of 2 seconds. However, as soon as the 'vanish' class is added, the card flips back face down. I don't understand why, as the 'flipped' class is still applied.
Here is my mark up:
<div class="grid-space">
<div class="card">
<div class="front-face">
<img src="https://res.cloudinary.com/lwcqviihu/image/upload/v1512898858/Animals/Sloth_svg.svg"/>
<p>sloth</p>
</div>
<div class="back-face"></div>
</div>
</div>
The CSS (flipped and vanish classes marked)
body {
background: #333;
}
.grid-space {
perspective: 1000;
width: 200px;
margin: auto;
}
.grid-space:hover {
transform: scale(1.02);
transition: 0.3s ease-in-out;
}
.card {
position: relative;
padding-bottom: 100%;
display: flex;
border-radius: 1vw;
transition: transform 0.4s ease-in-out, opacity 2s ease-in-out;
transform-style: preserve-3d;
cursor: pointer;
}
.card p {
color: inherit;
}
/*****These are the classes applied to do the animation***********/
.flipped {
transform: rotateY(180deg);
}
.vanish {
opacity: 0;
}
/*****END**********************************************************/
.front-face, .back-face {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
border-radius: 1vw;
text-align: center;
box-sizing: border-box;
}
.front-face {
transform: rotateY(180deg);
color: #EDCB7A;
background: #487360;
border-style: solid;
border-width: 2px;
}
.back-face {
/* background: #C7C6C4;
border: 1px solid #EBD787; */
background: #3A295C;
border: 1px #EBD787 solid;
z-index: 10;
}
.front-face > p {
font-size: 3vmin;
margin: 0;
position: absolute;
bottom: 5%;
width: 100%;
text-align: center;
}
.front-face > img {
width: 90%;
margin-top: 5%;
}
And finally, the javascript:
window.onload = function() {
var card = document.getElementsByClassName('card')[0];
card.addEventListener('click', function() {
this.className += " flipped";
window.setTimeout(vanish, 2000);
});
function vanish() {
card.className += " vanish";
}
};
You can see the whole thing 'working' here: https://codepen.io/timsig/pen/MVavXv
Many thanks for any help.
There seems to be something odd hiding the revealed face when applying opacity to the parent.
I sinceriously don't know why that happens (if anyone has a clue, I'd really, really like to know), but an alternate approach would be to modify the faces instead of the card itself when you apply the .vanish class
.vanish > .back-face{
visibility:hidden;
}
.vanish > .front-face{
opacity:0
}
.front-face{
transition:opacity 2s ease-in-out;
}
and of course, taking out the rule that applies opacity 0 to the .card
/*.vanish {
opacity: 0;
}*/
I think I know why it's happening. When .card's opacity is being set to 0 because of .vanish, it's setting the opacity of its default state since the opacity style is being set on .card itself.
I fixed it by moving the opacity styles to .front-face since that's the side you want to fade out.
.card {
transition: transform 0.4s ease-in-out;
}
.vanish .front-face {
opacity: 0;
}
.front-face {
transition: opacity 2s ease-in-out;
}

How can I "tranform:translate" relative to a previous translate?

I have the following working code which I am attempting to simplify:
[tt] {
position: relative;
}
[tt]::after {
bottom: 100%;
content: attr(tt);
padding: 5px;
background: #333;
color: #fff;
}
[tt]::before,
[tt]::after {
position: absolute;
/* Middle 3 */
left: 50%;
transform: translate(-50%, 50%);
}
/* First 3 */
[tt]:nth-child(-n+3)::before,
[tt]:nth-child(-n+3)::after {
transform: translate(0 , 50%);
}
/* Last 3 */
[tt]:nth-last-child(-n+3)::before,
[tt]:nth-last-child(-n+3)::after {
transform: translate(-100%, 50%);
}
/* add animation */
[tt]:hover::before,
[tt]:hover::after {
animation: tt-move1 100ms ease-out forwards;
display: block;
}
[tt]:nth-child(-n+3):hover::before,
[tt]:nth-child(-n+3):hover::after {
animation: tt-move2 100ms ease-out forwards;
}
[tt]:nth-last-child(-n+3):hover::before,
[tt]:nth-last-child(-n+3):hover::after {
animation: tt-move3 100ms ease-out forwards;
}
#keyframes tt-move1 {
to {
transform: translate(-50%, 0);
}
}
#keyframes tt-move2 {
to {
transform: translate(0, 0);
}
}
#keyframes tt-move3 {
to {
transform: translate(-100%, 0);
}
}
/*For working demo*/
div {
/*won't work unless set relative, Something that happens in [tt]*/
top:100px;
margin: 10px;
float:left;
width: 20px;
height: 20px;
border: black solid 3px;
}
<div tt="tt1"></div>
<div tt="tt2"></div>
<div tt="tt3"></div>
<div tt="tt4"></div>
<div tt="tt5"></div>
<div tt="tt6"></div>
<div tt="tt7"></div>
<div tt="tt8"></div>
<div tt="tt9"></div>
The above code has a specific animation for each different type of element, something which seems unnecessary. To my knowledge, I am simply applying the same transform to each element (moving the element up along the y-axis) so I expected that the following should also work:
[tt] {
position: relative;
}
[tt]::after {
bottom: 100%;
content: attr(tt);
padding: 5px;
background: #333;
color: #fff;
}
[tt]::before,
[tt]::after {
position: absolute;
/* Middle 3 */
left: 50%;
transform: translate(-50%, 50%);
}
/* First 3 */
[tt]:nth-child(-n+3)::before,
[tt]:nth-child(-n+3)::after {
transform: translate(0 , 50%);
}
/* Last 3 */
[tt]:nth-last-child(-n+3)::before,
[tt]:nth-last-child(-n+3)::after {
transform: translate(-100%, 50%);
}
/*****************Changed code*******************/
/* add animation */
[tt]:hover::before,
[tt]:hover::after {
animation: tt-move 100ms ease-out forwards;
display: block;
}
#keyframes tt-move {
to {
transform: translateY(0);
}
}
/*///////////////Changed code/////////////////*/
/*For working demo*/
div {
/*won't work unless set relative, Something that happens in [tt]*/
top:100px;
margin: 10px;
float:left;
width: 20px;
height: 20px;
border: black solid 3px;
}
<div tt="tt1"></div>
<div tt="tt2"></div>
<div tt="tt3"></div>
<div tt="tt4"></div>
<div tt="tt5"></div>
<div tt="tt6"></div>
<div tt="tt7"></div>
<div tt="tt8"></div>
<div tt="tt9"></div>
After some research, I now understand that transform: translateY(Δy); is the same as saying transform: translate(0,Δy); which is causing the unexpected result. Unfortunately that was the only method I have been able to find that looks like it is supposed to do what I wanted.
I am looking for a method to transform:translate that allows the x-axis of a previous transform:translate to stay the same, while only changing the y-axis.
Is there a different way to accomplish this simplification? Or am I stuck using the repetitious code from above?
When you animate transform you have to add any already set values or else they will temporary be overwritten.
In this case you could animate the bottom instead, which will give the output you want.
[tt] {
position: relative;
}
[tt]::after {
bottom: 100%;
content: attr(tt);
padding: 5px;
background: #333;
color: #fff;
}
[tt]::before,
[tt]::after {
position: absolute;
/* Middle 3 */
left: 50%;
transform: translate(-50%, 50%);
}
/* First 3 */
[tt]:nth-child(-n+3)::before,
[tt]:nth-child(-n+3)::after {
transform: translate(0 , 50%);
}
/* Last 3 */
[tt]:nth-last-child(-n+3)::before,
[tt]:nth-last-child(-n+3)::after {
transform: translate(-100%, 50%);
}
/*****************Changed code*******************/
/* add animation */
[tt]:hover::before,
[tt]:hover::after {
animation: tt-move 100ms ease-out forwards;
}
#keyframes tt-move {
to {
bottom: 170%;
}
}
/*///////////////Changed code/////////////////*/
/*For working demo*/
div {
/*won't work unless set relative, Something that happens in [tt]*/
top:100px;
margin: 10px;
float:left;
width: 20px;
height: 20px;
border: black solid 3px;
}
<div tt="tt1"></div>
<div tt="tt2"></div>
<div tt="tt3"></div>
<div tt="tt4"></div>
<div tt="tt5"></div>
<div tt="tt6"></div>
<div tt="tt7"></div>
<div tt="tt8"></div>
<div tt="tt9"></div>

Resources