CSS animate remove from DOM - css

I have the following HTML structure:
<div class="products-container">
{foreach from=$cart.products item=product}
<div class="product" data-id-product="{$product.id_product}" data-id-product-attribute="{$product.id_product_attribute}">
...
</div>
</div>
Now I have a javascript that can remove any div .product.
Is there a way to fade the deleted div out of the DOM to the right and animate the other divs 'moving up to the free space'?

A simple example
let btt = document.querySelector('button');
let products_cnt = document.querySelector('.products');
let products = document.querySelectorAll('.product');
products[0].addEventListener('transitionend', function() {
[...products].forEach((p) => p.parentNode.removeChild(p))
});
btt.addEventListener('click', function() {
this.setAttribute('disabled', 'disabled');
products_cnt.classList.add('products--delete');
})
div {
border: 1px #9bc solid;
height: 60px;
width: 200px;
margin: 10px;
color: #69A;
font: 1em system-ui;
}
button {
margin-bottom: 3em;
cursor: pointer; }
.products {
overflow-x: hidden; }
.product {
font-weight: bold;
transition: transform 1.5s 0s, opacity 1.25s 0s;
transform: translateX(0);
opacity: 1;
}
.products--delete .product {
transform: translateX(100vw);
opacity: 0;
}
<button type="button">Remove product/s</button>
<section class="products">
<div>Not a product</div>
<div class="product">Product</div>
<div class="product">Product</div>
<div>Not a product</div>
<div class="product">Product</div>
<div>Not a product</div>
</section>
Explanation: when you click the button the class .products--delete is added to the .products_container element: this starts a CSS transition over the .product elements.
Finally, when the transitionend event occurs on a single product element just remove from the DOM all products.

You can use css transitions in your CSS. The part of removing may be different for you. Please click the product to remove it.
let productsRy = Array.from(document.querySelectorAll(".product"));
productsRy.forEach((p,i)=>{
p.style.top = i * (3 + 1) * 16 +"px";
p.addEventListener("click",()=>{
container.removeChild(p);
productsRy = Array.from(document.querySelectorAll(".product"));
productsRy.forEach((p1,i1)=>{p1.style.top = i1 * (3 + 1) * 16 +"px";})
})
})
.products-container{position:relative;}
.product{
position:absolute;
padding:1em;
margin:.5em;
height:3em;
outline:1px solid; width:200px;
height:auto;
transition: all 1s;
}
}
<div class="products-container" id="container">
<div class="product" data-id-product="a" data-id-product-attribute="a">
product a
</div>
<div class="product" data-id-product="b" data-id-product-attribute="b">
product b
</div>
<div class="product" data-id-product="c" data-id-product-attribute="c">
product c
</div>
</div>

CSS really doesn't have the ability to modify an object in the same manner as JavaScript. you can do this easily.
$(".product").fadeTo("slow", 0.00, function(){
$(this).slideUp("slow", function() {
$(this).remove();
});
});

Related

Transitioning element in Vue

I'm somewhat new to Vue, and I'm working on trying to make a transition work. The outcome would look similar to the gif below. The element moving from right to left is one component in Vue, but the issue is I'm transitioning it from one Bootstrap column to another. From what I've seen online, there isn't an easy way to CSS transition while also changing the parent element, so what I've done is basically rendered the component twice, and delayed the second one. In the gif, you can see the point where it transitions and its a bit clunky.
I'm wondering if this is best practice, or if there's another, easier way to do this. Should I rework my whole structure to make them live under the same parent, and just change the position via CSS, or should I continue with what I've done and just work to smooth out the transition between the two elements?
<div class="d-flex align-items-center min-vh-100 hero">
<div class="container-fluid">
<div class="row hero-row d-flex">
<div class="col hero-left d-flex align-items-center">
<div class="w-100">
<transition appear name="fade-left" mode="out-in" >
<HeroNav v-if="$route.name!='Home'"/>
<h1 v-else>Hey, I'm George.</h1>
</transition>
</div>
</div>
<div class="col d-flex hero-right align-items-center">
<transition name="slide" mode="out-in">
<HeroNav v-if="$route.name=='Home'"/>
<div v-else>
</div>
</transition>
</div>
</div>
</div>
</div>
</template>
<script>
import HeroNav from '#/components/HeroNav.vue'
export default {
name: 'Hero',
components: { HeroNav }
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hero {
background: #24292E;
height: 100%;
}
.hero-row {
height: 30em;
}
.hero-left {
border-right: 1px solid #AEC6CF;
}
.hero-left .nav-text{
float: right;
margin-right: 3em;
z-index: 1;
}
.hero-right .nav-text{
margin-left: 3em;
}
h1 {
color: #CFAEB5;
font-family: 'Lato', sans-serif;
font-size: 4rem !important;
font-weight: 100 !important;
text-align: right;
}
h3 {
color: #ffffff;
}
.fade-enter-active,
.fade-leave-active {
transition: all .5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-left-enter-active,
.fade-left-leave-active {
transition: all 1s ease;
transition-delay: .15s;
}
.fade-left-enter-from,
.fade-left-leave-to {
opacity: 0;
}
.slide-enter-active,
.slide-leave-active {
transition: all 1.7s cubic-bezier(.17,.67,0,1);
}
.slide-leave-to {
transform: translateX(-29.4em);
opacity: 1;
}
</style>```

Vue add class before insert, leave it

I have a custom animation that the regular Vue transition doesn't quite cover. I have it implemented elsewhere with a conditional v-bind:class, but that doesn't work well for conditional v-if blocks or v-for groups.
I need to add a class ('open') one frame after the element is entered as with v-enter-to, but I need it to never be removed from the element.
I then need it removed removed when leaving to trigger the closing animation.
Am I using Vue Transition wrong and this is perfectly possible within transition, or is there a way to add/remove the class around the enter/leave functionality?
.accordion {
overflow: hidden;
> div {
margin-bottom: -1000px;
transition: margin-bottom .3s cubic-bezier(.5,0,.9,.8),visibility 0s .3s,max-height 0s .3s;
max-height: 0;
overflow: hidden;
}
&::after {
content: "";
height: 0;
transition: height .3s cubic-bezier(.67,.9,.76,.37);
max-height: 35px;
}
&.open {
max-height: 8000px;
> div {
transition: margin-bottom .3s cubic-bezier(.24,.98,.26,.99);
margin-bottom: 0;
max-height: 100000000px;
position: relative;
}
&::after {
height: 35px;
max-height: 0;
transition: height .3s cubic-bezier(.76,.37,.67,.9),max-height 0s .3s;
}
}
}
<transition name="accordion" :duration="300">
<div class="accordion" v-if="equipmentSelections.length === 0">
<div>
<p>Begin by selecting equipment from the list</p>
</div>
</div>
</transition>
<transition-group name="accordion" :duration="300">
<div v-for="equipment in equipmentSelections" v-bind:key="equipment.unitNumber" class="accordion">
<div>
<h3 v-on:click="updateSelections(equipment)">{{equipment.unitNumber}}</h3>
</div>
</div>
</transition-group>
You can get more power out of the vue transition component by using the javascript hooks.
For example:
Demo: https://codepen.io/KingKozo/pen/QWpBPza
HTML:
<div id="app">
<div>
<button type="button" #click="toggle">Toggle</button>
</div>
<transition name="label" v-on:enter="enter" v-on:before-leave="leave">
<div v-if="isOpen">Hi</div>
</transition>
</div>
CSS
.label-enter-active, .label-leave-active {
transition: opacity 1s;
}
.label-enter, .label-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
.staying-visible {
background-color: red;
color: white;
}
Javascript
const vm = new Vue({
el: '#app',
data: {
isOpen: false
},
methods: {
enter(el){
el.classList.add("staying-visible")
},
leave(el){
el.classList.remove("staying-visible")
},
toggle(){
this.isOpen = !this.isOpen
}
}
})
In the example I provided I add a brand new class, "staying-visible", to the element on enter and remove it later on. In the example provided, I remove the class on "before-leave" so as to make the change visible but for your specific use case it seems like you can also just remove it during the 'leave' hook.
To learn more about how to use the javascript transition hooks, check out the official documentation: https://v2.vuejs.org/v2/guide/transitions.html#JavaScript-Hooks

How the use the results of a CSS CALC() to update the left property value

I am trying to use, and then change, the left property value of my left-hand sidebar as though it were a memory variable unsuccessfully.
My basic algorithm is
left = (left * (-1) - 250)
Initial value of left is 0.
step #1: If left (value) is 0; then left should become -250.
step #2: If left (new value) is -250; left should then become 0.
step #3: go to step #1
Try this in a spreadsheet where left is the value of the preceding row. Your result rows should look like this:
-250
0
-250
I am effectively trying to toggle the left value from 0 to -250 then back to 0.
So that my left hand sidebar is either "on" or "off" canvas as determined by the left: value.
I have tried many variations of calc, including
#leftr: 0; is set at the beginning of of my CSS sheet.
#negtv: -1; also set at the beginning of my CSS sheet.
....
#leftr: -webkit-calc(~"((#leftr * #negtv) - 250)"); /* slide-in/out 0 or -250 */
left: #leftr;
I hope this is clearer than mud and that you guys can help me?
Thanks in advance
That is not possible with pure CSS, AFAIK.
Consider to use JavaScript for that. Here's example:
Script
$('.sidebar-toggle').click(function() {
var sidebar = $('.items');
sidebar.css('margin-left', 0);
if (!sidebar.hasClass('hidden'))
sidebar.addClass('hidden');
else
sidebar.removeClass('hidden');
});
$('.sidebar-slide').click(function() {
var sidebar = $('.items');
var hidden = sidebar.hasClass('hidden');
if (hidden) {
sidebar.css('margin-left', -sidebar.width()*2);
sidebar.removeClass('hidden');
sidebar.animate({'margin-left': 0});
} else {
sidebar.css('margin-left', 0);
sidebar.removeClass('hidden');
sidebar.animate({'margin-left': -sidebar.width()*2}, function() {
sidebar.addClass('hidden');
});
}
});
HTML/CSS
<style>
.nav {
}
.nav a {
cursor: pointer;
color: navy;
font-weight: bold;
}
.items {
position: absolute;
width: 100px;
border: 1px solid black;
}
.items.hidden {
display: none;
}
</style>
<div class="nav">
Sidebar:
<a class="sidebar-toggle">Toggle</a>
| <a class="sidebar-slide">Slide</a>
</div>
<br />
<div class="items">
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
<div class="item">item</div>
</div>
You can try it at jsFiddle.
If you want a sidebar that shows up when the user clicks something, without JavaScript, you can use the hidden checkbox trick.
.sidebar {
padding:8px;
position:absolute;
left:-250px; top:0;
width:234px; height:100%;
height:calc(100% - 16px); /* sorry */
background:#CCF;
transition:left 1s;
}
#showsidebar {display:none}
label[for='showsidebar'] { /* make it look like a link */
color:blue;
text-decoration:underline;
cursor:pointer;
}
#showsidebar:checked ~ .sidebar {
left:0;
}
<input type="checkbox" id="showsidebar">
<label for="showsidebar">show sidebar</label>
<section class="sidebar">
<label for="showsidebar">hide sidebar</label>
<h1>The sidebar!</h1>
<p>(contents of sidebar)</p>
</section>
<h1>The main site</h1>
<p>Blabla. Something Latin.</p>

How to transition 2 divs at the same time?

I'm trying to make an animated menu that when I hover over it , the background (or image) reduces and at the same time the text expands.
Thats my style sheet :
.menus {
float: left;
background-image: url(images/menus_bg.png);
width: 208px;
height: 283px;
}
.menusimg {
width: 208px;
height: 283px;
position: absolute;
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: center center;
background-image: url(images/menu1.png);
}
.menusimg:hover {
background-size: 80% 80%;
}
.menusimg, .menusimg:hover {
-webkit-transition: background-size 0.2s ease-in ;
}
.menustxtbox {
font-family: MP;
padding-top: 240px;
width: 208px;
height: 283px;
color: #4c4c4c;
font-size: large;
text-shadow: gray 0.1em 0.1em 0.2em;
}
.menustxtbox:hover {
padding-top: 235px;
font-size: x-large;
color: #4fa3f9;
}
.menustxtbox, .menutxtbox:hover {
-webkit-transition:font-size 0.1s linear;
-moz-transition:font-size 0.1s linear;
}
and the html :
<div class="menus">
<div class="menusimg">
</div>
<div class="menustxtbox">
Text
</div>
</div>
Any ideas? A simple Java script or anything that will solve this problem? :)
Thank you in advance ^^
I second what ntgCleaner said.
In addition you can use:
$('.menus').hover(function(){
$('.menusimg').addClass('active');
$('.menustxtbox').addClass('active');
}, function(){
$('.menusimg').removeClass('active');
$('.menustxtbox').removeClass('active');
});
And your css would have:
.menusimg.active, .menusimg.active{
-webkit-transition: background-size 0.2s ease-in ;
}
etc.
Well, without any code to see that you've done anything or tried anything with javascript, I would suggest this:
Change your CSS to make real sizes of font size first:
.menustxtbox {
font-size:40px;
}
then make some jquery
$('.menus').hover(function(){
$('.menusimg').animate({width: "100px"});
$('.menustxtbox').animate({fontSize: "90px"});
}, function(){
$('.menusimg').animate({width: "208px"});
$('.menustxtbox').animate({fontSize: "40px"});
});
Then delete your :hover css styles
And if you want to use hover, I would suggest looking into hoverintent
UPDATE for a comment below
To do this for each separate menu item, you will have to name things a certain way. Here's an example.
HTML
<div class="menu">
<div class="menuItem" id="menu1">
<div class="menusimg"></div>
<div class="menustxtbox"></div>
</div>
<div class="menuItem" id="menu2">
<div class="menusimg"></div>
<div class="menustxtbox"></div>
</div>
<div class="menuItem" id="menu3">
<div class="menusimg"></div>
<div class="menustxtbox"></div>
</div>
</div>
Then with jQuery, you will have to use $(this) and .children()
$('.menuItem').hover(function(){
$(this).children('.menusimg').animate({width: "100px"});
$(this).children('.menustxtbox').animate({fontSize: "90px"});
}, function(){
$(this).children('.menusimg').animate({width: "208px"});
$(this).children('.menustxtbox').animate({fontSize: "40px"});
});
When you use $(this), you will do whatever you want to the specific thing you are trying to use. Then you just go up or down from there using parent or children to do something to either of those.

On mouse over change transition

Here i am implementing an Image slider
My problem is when i hover my image slider i want to stop my css transition property.
I tried using addclass and removeclass but failed
Here is my code
HTML
<div id="container">
<img src="http://worksheetgenius.com/Next_button.jpg" width="106px;" id="right"/>
<img src="http://worksheetgenius.com/Previous_button.jpg" width="106px;" id="left"/>
<div id="slider">
<div id="slide1" class="slide transition">
<img src="http://s.cghub.com/files/Image/030001-031000/30883/37_max.jpg"/>
</div>
<div id="slide2" class="slide transition">
<img src="http://www.f-16.net/attachments/83_1093_207.jpg" />
</div>
<div id="slide3" class="slide transition">
<img src="http://www.sportbikes.net/forums/attachments/fz6/37654d1111746148-all-fz6-riders-show-us-your-bike-imag0005-edited-downscaled.jpg" />
</div>
<div id="slide4" class="slide transition">
<img src="http://3.bp.blogspot.com/-fpTz_1UegJM/TZ6eQWXTueI/AAAAAAAAASY/TsYJ5xZyixQ/s1600/banner_239.jpg" />
</div>
</div>
</div>
CSS
#slider
{
overflow:hidden;
height:363px;
position:absolute;
left:180px;
top:159px;
padding:0px;
margin:0px;
background: url("header_bg.jpg") repeat-x scroll 0 0 #FFFFFF;
width:1000px;
}
#slide1
{
position:absolute;
left:0px;
z-index:1;
}
.slide
{
position:absolute;
left:1000px;
}
.transition
{
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
.notransition
{
-webkit-transition: none;
transition: none;
}
#right
{
position:absolute;
top: 287.5px;
right: 127px;
z-index: 99;
}
#left
{
position:absolute;
top: 287.5px;
left: 127px;
z-index: 99;
}
Script
var t=setInterval(function(){$("#right").click()},5000);
$(document).ready(function()
{
var present=1;
var next=2;
var total_slide=document.getElementById("slider").childElementCount;
$("#right").click(function()
{
present_slide="#slide"+present;
next_slide="#slide"+next;
$(present_slide).css("left","1000px");
$(next_slide).css("left","0px");
present++;
next++;
if(present==(total_slide+1))
{
present=1;
next=2;
for(i=1;i<=total_slide;i++)
{
$("#slide"+i).css("left","1000px");
}
$("#slide1").css("left","0px");
}
});
$("#left").click(function()
{
if(present==1)
{
next_slide="#slide"+total_slide;
present_slide="#slide"+present;
$(present_slide).css("left","1000px");
$(next_slide).css("left","0px");
present=total_slide;
next=1;
}else
{
next_slide="#slide"+(present-1);
present_slide="#slide"+present;
$(present_slide).css("left","1000px");
$(next_slide).css("left","0px");
present--;
next--;
}
if(next==0)
{
present=(total_slide-1);
next=total_slide;
}
});
$(".slide").on('mouseenter',function()
{ $(this).removeClass('transition').addClass('notransition');});
$(".slide").on('mouseleave',function()
{$(this).removeClass('notransition').addClass('transition');});
});
In the above provided code i used to classes transition and no transition.
I also tried with CSS as follows
.slide:hover
{
-webkit-transition: none;
transition: none;
}
I was doing a similar idea and I ended up using this cycle plugin for jquery Malsup Cycle. I then used this piece of code but you can find all of the options at the link above.
$(document).ready(function(){
$('#slider').cycle({
fx: 'scrollLeft',
speed: 1000,
timeout: 5000,
pause: 1
});
});
Setting the pause flag to one gets your desired functionality where it will stop animating on hover. I hope this helps!
HTML
<div id = "slider">
<div>
Slide 1
</div>
<div>
Slide 2
</div>
<div>
Slide 3
</div>
<div>
Slide 4
</div>
</div>
You just need to link to the plugin in the html and this should provide the desired functionality as I see it. You can put whatever content you want in the divs. I used a picture of our clients' logos with a short description as a banner on our company's page.
EDIT: I changed the selector to match the id that you used. HTML added.

Resources