CSS - Toggle Multiple 3d Animations - javascript

I'm trying to have two 3d cards that trigger a flip with a toggle button. The problem is only the first cards button currently toggle's the 3d flipping animation, whereas the second cards button doesn't.
I'm following this tutorial, but he currently only uses one https://3dtransforms.desandro.com/card-flip
let flip = document.querySelector('.flip');
let card = document.querySelector('.card');
flip.addEventListener('click', function() {
card.classList.toggle('is-flipped');
});
/*The 3d Area Boundary*/
.container {
box-sizing: border-box;
width: 100%;
height: 170px;
padding: 0;
perspective: 800px;
}
/*The 3d Object - Flipping Card */
.card {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform-origin: center right;
transition: transform 1s;
}
/*Sets Card face 2d, absolute and invisible
when until flipped*/
.card-face {
position: absolute;
height: 100%;
width: 100%;
backface-visibility: hidden;
}
.front-card {}
.back-card {
transform: rotateY(180deg);
}
.card.is-flipped {
transform: rotateY(180deg);
transform: translateX(-100%) rotateY(-180deg);
}
<div class="container">
<div class="card">
<div class="card-face front-card">
<p>Some Text.</p>
<a class="uk-button uk-button-default" class="flip">Flip</a>
</div>
<div class="card-face back-card">
<p>Some MORE TEXT.</p>
<a class="uk-button uk-button-default" class="flip">Flip</a>
</div>
</div>
</div>

The problem is only the first cards button currently toggle's the 3d flipping animation, whereas the second cards button doesn't
No, your code is throwing the following error:
Uncaught TypeError: Cannot read property 'addEventListener' of null
Having same attribute multiple times in an elements (class in a element) will simply ignored all the attributes except the first one.
querySelector() returns only the first matched element. You have to target all the elements with class, you can do so using querySelectorAll(). Then loop through them to attach the event to all of them.
let flip = document.querySelectorAll('.flip');
let card = document.querySelector('.card');
flip.forEach(function(el){
el.addEventListener('click', function() {
card.classList.toggle('is-flipped');
});
});
/*The 3d Area Boundary*/
.container {
box-sizing: border-box;
width: 100%;
height: 170px;
padding: 0;
perspective: 800px;
}
/*The 3d Object - Flipping Card */
.card {
position: relative;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform-origin: center right;
transition: transform 1s;
}
/*Sets Card face 2d, absolute and invisible
when until flipped*/
.card-face {
position: absolute;
height: 100%;
width: 100%;
backface-visibility: hidden;
}
.front-card {}
.back-card {
transform: rotateY(180deg);
}
.card.is-flipped {
transform: rotateY(180deg);
transform: translateX(-100%) rotateY(-180deg);
}
<div class="container">
<div class="card">
<div class="card-face front-card">
<p>Some Text.</p>
<a class="uk-button uk-button-default flip">Flip</a>
</div>
<div class="card-face back-card">
<p>Some MORE TEXT.</p>
<a class="uk-button uk-button-default flip" >Flip</a>
</div>
</div>
</div>

Related

HTML - Second IMG hover issue

I have 2 semicircles stuck next to each other forming a circle. When I hover on the left semicircle, the right one lowers it's opacity (which is what is supposed to do) but when I hover on the right one, the opacity doesn't change at all.
HTML:
<div id="animation-components">
<img src="leftball.svg" alt="" class="animation-item-01">
<img src="rightball.svg" alt="" class="animation-item-02">
</div>
CSS:
#animation-components {}
.animation-item-01 {
display: inline;
position: relative;
margin-bottom: 240px;
margin-top: 100px;
transform: translate(631px,80px);
height: 320px;
transition: opacity ease 0.5s;
}
.animation-item-02 {
display: inline;
position: relative;
margin-bottom: 240px;
margin-top: 100px;
transform: translate(627px,80px);
height: 320px;
transition: opacity ease 0.5s;
}
.animation-item-01:hover + .animation-item-02{
opacity: 50%;
}
.animation-item-02:hover + .animation-item-01{
opacity: 50%;
}
What can I alter to make this work?
The issue is that you can only select the next sibling with the adjacent sibling selector.
.element-1 + .element-2 /* good */
.element-2 + .element-1 /* not so good */
Since .animation-item-02 comes after .animation-item-01, there is no way to select the previous .animation-item-01 from .animation-item-02
Doing the following will fix the issue:
#animation-components:hover > div {
opacity: 50%;
}
#animation-components > div:hover {
opacity: 100%;
}
CSS Combinators can't be used to apply styles to elements before target element.
The adjacent sibling selector (+) will aply to all adjacent elements, not to it's opposite elements.
CSS It's in the name: Cascading Style Sheets only supports styling in cascading direction, not up.
To achieve the desired, you can do the folowwing:
#animation-components:hover img {
opacity: .5;
}
#animation-components img:hover{
opacity: 1;
}
<div id="animation-components">
<img src="https://via.placeholder.com/150.png/ff0000" alt="" class="animation-item-01">
<img src="https://via.placeholder.com/150.png/ff0000" alt="" class="animation-item-02">
</div>
It might just be me but I find it heaps easier to throw in just a little bit of javascript and avoid messy css combinators. Heres my fix, script goes anywhere in your html file, I put it after the closing body tag.
<script>
function fadeOut(obj) {
document.getElementById(obj).style.animationName = "fadeOut";
}
function fadeIn(obj) {
document.getElementById(obj).style.animationName = "fadeIn";
}
</script>
#item1 {
display: inline;
position: relative;
margin-bottom: 240px;
margin-top: 100px;
transform: translate(631px,80px);
height: 320px;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
#item2 {
display: inline;
position: relative;
margin-bottom: 240px;
margin-top: 100px;
transform: translate(627px,80px);
height: 320px;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
#keyframes fadeOut {
0%{opacity: 1;}
100%{opacity: 0.5;}
}
#keyframes fadeIn {
0%{opacity: 0.5;}
100%{opacity: 1;}
}
<div id="animation-components">
<img src="leftball.svg" alt="" id="item1" onmouseover="fadeOut('item1')" onmouseout="fadeIn('item1')">
<img src="rightball.svg" alt="" id="item2" onmouseover="fadeOut('item2')" onmouseout="fadeIn('item2')">
</div>
Also its just a me thing, but you have class attributes where id attributes should be. If your applying seperate styles to two completely seperate elements its a good idea to use id, but if your applying same style to two elements

How to view/hide div only in that id

I am trying to make a div where it is assigned by an id.
My goal is to make that div have two sides: the front and the back (assigned by class)
* the front is shown as default, while the back will only be shown upon user click
My question is, when trying to make a lot of this div, how can I achieve this kind of scenario, where it will only show/hide those classes only in that particular id?
<div id="user01" onclick="userId(this)">
<div class="front">
<img src="../media/media/alumni/sdc/01.jpg"> User name on front
</div>
<div class="back">
other info on back
</div>
</div>
**user01 is assigned per each user (ex.: the first user is 01, while the second is 02, and so on...)
thanks :)
Use a css class on top of your id:
<div id="user01" class="user">
Then, in your Javascript, use document.querySelectorAll along with that class:
let users = document.querySelectorAll('.user')
Now you can iterate over this DOM node collection that is returned by document.querySelectorAll and add an event listener to each one:
Array.prototype.forEach.call(users, function(user) {
user.addEventListener('click', function(event) {
/* your code to be executed on click
each user is available here as 'this' */
// example:
this.classList.toggle('active')
})
})
As mplungjan pointed out, Edge and IE don't support forEach on Node collections, so Array.prototype.forEach.call(users, function(user) ... comes in as a replacement for users.forEach(function(user) { ....
As a last step, add the CSS that flips your stuff:
.user .front {
transition: opacity .3s ease;
opacity: 1;
}
.user.active .front {
opacity: 0;
}
.user .back {
transition: opacity .3s ease;
opacity: 0;
}
.user.active .back {
opacity: 1;
}
let users = document.querySelectorAll('.user')
Array.prototype.forEach.call(users, function(user) {
user.addEventListener('click', function(event) {
/* your code to be executed on click
each user is available here as 'this' */
// example:
this.classList.toggle('active')
})
})
.user {
display: inline-block;
height: 200px;
width: 200px;
position: relative; /* this allows absolute position of children */
}
.user:hover {
cursor: pointer;
}
.user .front,
.user .back {
transition: opacity .3s ease;
color: white;
position: absolute; /* position both "sides" on top of each other */
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.user .front img,
.user .back img {
position: absolute;
z-index: 0;
}
.user .front span,
.user .back span {
background-color: rgba(0,0,0,.3);
box-shadow: 0 0 10px rgba(0,0,0,.3), 0 0 2px rgba(0,0,0,.3);
border-radius: 10px;
display: block;
left: 50%;
padding: 10px 5px;
position: absolute;
text-align: center;
top: 50%;
transform: translate(-50%, -50%);
z-index: 1;
}
.front {
opacity: 1;
}
.user.active .front {
opacity: 0;
}
.back {
background-color: #333;
opacity: 0;
}
.user.active .back {
opacity: 1;
}
<div class="user" id="user01">
<div class="front">
<img src="https://lorempixel.com/output/business-q-c-200-200-8.jpg"><span>User 1 name on front</span>
</div>
<div class="back">
other info on back for User 1
</div>
</div>
<div class="user" id="user02">
<div class="front">
<img src="https://lorempixel.com/output/business-q-c-200-200-2.jpg"><span>User 2 name on front</span>
</div>
<div class="back">
other info on back for User 2
</div>
</div>

CSS continuous rotation without setTimeout

So I've managed to create a rotation that only rotates in one direction by using a setTimeout. I was wondering if I could still achieve this without using it. The main issue I have is that if I click fast enough, it will still spin the other way.
So overall, is there a way to make it spin in one direction regardless of how fast I click.
function clicked()
{
element = $("#spin");
if ($(element).hasClass("rotate2"))
{
$(element).removeClass("rotate rotate2");
setTimeout( () => $(element).addClass("rotate"), 1);
}
else if($(element).hasClass("rotate"))
{
$(element).addClass("rotate2");
}
else
{
$(element).addClass("rotate");
}
}
div.horizontal {
position: absolute;
width: 100%;
height: 5px;
background-color: red;
top: 50%;
transform: translateY(-50%);
}
div.horizontal.rotate {
transform: translateY(-50%) rotate(-180deg);
transition: transform 0.5s;
}
div.horizontal.rotate2 {
transform: translateY(-50%) rotate(-360deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width: 50px; height: 50px; position: relative;">
<div id="spin" class="horizontal">
</div>
</div>
<button onclick="clicked()">Rotate</button>
You can just use a single class for the transition, and remove the class on transitionend
var $button = $('#button'),
$spin = $('#spin');
$(document).on('click', $button, function() {
$spin.addClass('rotate').on('transitionend',function() {
$(this).removeClass('rotate');
});
})
div.horizontal {
position: absolute;
width: 100%;
height: 5px;
background-color: red;
top: 50%;
}
div.horizontal.rotate {
transform: rotate(-180deg);
transition: transform .5s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="width: 50px; height: 50px; position: relative;">
<div id="spin" class="horizontal">
</div>
</div>
<button id="button">Rotate</button>

automatic cookie bar pure css works fine but need delay

I added this pure css cookie bar to my website and all works fine, the only problem is that when you enter in the site, you can see FIRST the cookie bar, AND the cookie bar go up and go down at the end.
How can see my cookie bar only go down when i enter in my site, i thought to change de thenimation delay, add set time out .... but nothing change !!
here is the original codepen and you can see what i want to change in it
www.codepen.io/natewiley/pen/uGtcD
HERE IS MY CODE
<input class="checkbox-cb" id="checkbox-cb" type="checkbox" />
<div class="cookie-bar">
<div class="message">
This website uses cookies to give you an incredible experience. By using
this website you agree to the
<div class="buttoncookies-container">
<a style="letter-spacing: 1px;" class="buttoncookies" id="modalcookieslinken" onclick="toggleOverlay()">terms</a>
</div>
</div>
<div class="mobile">
This website uses cookies,
<div class="buttoncookies-container">
<a style="letter-spacing: 1px;" class="buttoncookies" id="modalcookiesshortlink" onclick="toggleOverlay()">
learn more
</a>
</div>
</div>
<label for="checkbox-cb" class="close-cb">X</label>
</div>
</div>
HERE IS MY CSS
.cookie-bar { z-index:9996; position: fixed; width: 100%; top: 0; right: 0; left: 0; height: auto; padding: 20px; line-height:20px; text-align: center; background: #d2c6af; transition: .8s; animation: slideIn .8s; animation-delay: .8s; display: inline-block; }
.mobile { display: none; }
#keyframes slideIn { 0% { transform: translateY(-1000px); } 100% { transform: translateY(0); } }
.close-cb { border: none; background: none; position: absolute; display: inline-block; right: 20px; top: 10px; cursor: pointer; }
.close-cb:hover { color:#fff;; }
.checkbox-cb { display: none;}
#checkbox-cb:checked + .cookie-bar { transform: translateY(-1000px); }
Removing the line in css
animation-delay: .8s;
will give you the result
Make the animation last longer.
animation: slideIn 4s;
Plus add some trick to animation flow:
0% {
transform: translateY(-50px);
}
50% {
transform: translateY(-50px);
}
100% {
transform: translateY(0);
}

The easiest way to change text with flip effect

I am looking for simple way to flip text.
For example I have currently "Hello" text in tag, and I need to flip it to "world", only once , I don't need to flip it back to "Hello", even if sometimes need I don't really need to save previous state. Just pass new text string and it should flip older to newer one.
I know that there are a lot of libraries like https://github.com/daynin/wodry , but for this I need to provide span inside it with specific style, and hardcode all possible flip text strings. I don't need specific part of the text, I need to flip it all at once.
Please suggest the best way to implement this.
Without using span, here is an example of what you are trying to achieve
- from Hello to word, without going back ( you can adjust it later to your needs: height, colour, width and the other attributes)
HTML:
<div class="flip">
<div class="item">
<div class="face front">Hello</div>
<div class="face back">word</div>
</div>
</div>
CSS:
.flip {
-webkit-perspective: 300;
width: 400px;
height: 200px;
}
.flip .item.flipped {
-webkit-transform: rotatex(-180deg);
}
.flip .item {
width: 100%;
height: 100%;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
}
.flip .item .face {
width: 100%;
height: 100%;
position: absolute;
-webkit-backface-visibility: hidden ;
z-index: 2;
text-align: center;
line-height: 200px;
}
.flip .item .front {
position: absolute;
z-index: 1;
background: black;
color: white;
cursor: pointer;
}
.flip .item .back {
-webkit-transform: rotatex(-180deg);
background-color: green;
color: black;
}
and a little JS to make it functional:
$('.flip').click(function () {
$(this).find('.item').addClass('flipped');
});
fiddle url: http://jsfiddle.net/GDdtS/9909/

Categories