I have an input field that I want to hide/show and doing so with a fade and slide transition. I've have two examples that I came up with but both have their drawbacks and I'd like to know if there is a more elegant solution.
I just need one of the two questions to be answered as both of them would solve my problem.
Question 1: Is there a way to trigger multiple transitions for one transition-directive?
Question 2: How to add a class that will trigger an ordinary css-transition after an if-statement put the element in the DOM?
Example 1
Svelte does not allow two transitions on the same element. So one solution is to nest two elements as shown below. Is there instead a way to write a custom transition using both fade and slide transition:myMultiTransition
?
{#if active === true}
<span transition:fade>
<span transition:slide>
<input type="text" />
</span>
</span>
{/if}
Example 2
In my other solution I just toggle an active class using a normal css transitions. The problem here is that the <input>
-field never leaves the DOM. It's 0px height but it seems wrong to leave it there.
How to cuccessfully show the input field with an {#if active === true}
and afterwards add a class that trigger the transition effect? Svelte seems to add the active-class that is supposed to trigger the transition before the element has entered the DOM.
I've tried to use await tick()
, onMount
, beforeUpdate
in various combination with no luck.
When adding the class with a delay with setTimeout it works - but I don't like this solution because it could fail if not the timing is exact and I won't want a delay before the transition start.
<span class:{active}>
<input type="text" />
</span>
<style>
.active {
// Normal transition: opacity 1s etc ...
}
</style>
REPL
https://svelte.dev/repl/89cb7d26d9484d0193b4bc6bf59518ef?version=3.38.3
You can create your own transition function:
<script>
import { cubicOut } from 'svelte/easing';
let visibleDoubleElements = false;
function slidefade(node, params) {
const existingTransform = getComputedStyle(node).transform.replace('none', '');
return {
delay: params.delay || 0,
duration: params.duration || 400,
easing: params.easing || cubicOut,
css: (t, u) => `transform-origin: top left; transform: ${existingTransform} scaleY(${t}); opacity: ${t};`
};
}
</script>
<label>
<input type="checkbox" bind:checked={visibleDoubleElements}>
Svelte transition
</label>
{#if visibleDoubleElements === true}
<input transition:slidefade type="text" placeholder="Double elements" />
{/if}
REPL: https://svelte.dev/repl/da8880947eff4f32b740a8742d9f817e?version=3.38.3