Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uneasy bouncing in transition:slide #12003

Open
qupig opened this issue Jun 11, 2024 · 12 comments
Open

Uneasy bouncing in transition:slide #12003

qupig opened this issue Jun 11, 2024 · 12 comments

Comments

@qupig
Copy link

qupig commented Jun 11, 2024

Describe the bug

Check the REPL. This issues can be reproduced in Svelte4/5.

source code
<script>
	import { slide } from 'svelte/transition';
	let visible1 = true;
	let visible2 = true;
	let visible3 = true;
</script>

<label>
	<input type="checkbox" bind:checked={visible1} />
	bounce on "in"
</label>
<label>
	<input type="checkbox" bind:checked={visible2} />
	bounce on "out"
</label>
<label>
	<input type="checkbox" bind:checked={visible3} />
	Normal and smooth
</label>

<div class="div1">
	{#if visible1}
		<div transition:slide style="background-color: orangered;">
			<p>slide in and out 1-1</p>
			<p>slide in and out 1-2</p>
		</div>
	{/if}
	<p>slide in and out 1-3</p>
	<p>slide in and out 1-4</p>
</div>

<div class="div2">
	{#if visible2}
		<p transition:slide style="background-color: orangered;">slide in and out 2-1</p>
	{/if}
	<p>slide in and out 2-2</p>
	<p>slide in and out 2-3</p>
</div>

<div class="div3">
	{#if visible3}
		<div transition:slide style="background-color: orangered;">
			<p>slide in and out 3-1</p>
			<p>slide in and out 3-2</p>
		</div>
	{/if}
	<p>slide in and out 3-3</p>
	<p>slide in and out 3-4</p>
</div>

<style>
	.div3 {
		display: flex;
		flex-direction: column;
	}
</style>
demo video
bounce.mp4

Reproduction

REPL

Logs

No response

System Info

Svelte compiler version 4.2.18
Svelte compiler version 5.0.0-next.153

Severity

annoyance

@Neptunium1129

This comment was marked as spam.

@henrikvilhelmberglund
Copy link

henrikvilhelmberglund commented Jun 12, 2024

There needs to be an offset so the slide ends up at the correct position.

`${primary_property}: ${t * primary_property_value}px;`
changing this line to ${primary_property}: ${t * primary_property_value t * 16}px; with a hardcoded offset value fixes the issue for the top transition but I'm not too sure how to get the actual value needed. It's still a bit ugly too with the background but not sure if it's fixable.

Someone mentioned in an old issue that jquery had a version of this that works so maybe checking that out could help: #2957

Hopefully someone smarter than me can fix this. Here's the transition before and after adding the offset:

Before

before

After

after

Edit: after playing around and looking at 7nik's example below I have no idea anymore, it doesn't seem like a single offset at least. Adding an offset with the margin of the child element makes the child text stay in place but the background of the transitioning element looks wrong. Ideally the text should stay in place and the background should transition smoothly too.

@7nik
Copy link

7nik commented Jun 12, 2024

Basically, it's caused by margin collapsing, but its rules are complicated. Moreover, margin collapsing may involve more than two elements, which may be non-adjacent siblings or non-direct parent-child, and all of it leads to a wide variety of tricky cases.

I tried to fix the first example, but you can see that inner content still jumps.

@7nik
Copy link

7nik commented Jun 13, 2024

I tried to do it, but I don't know how reliable it is. Plus, it ignores writing-mode and white-space. Likely something else isn't taken into account.

@henrikvilhelmberglund
Copy link

I tried to do it, but I don't know how reliable it is. Plus, it ignores writing-mode and white-space. Likely something else isn't taken into account.

It looks good but isn't reversible in the in-out direction, eg. when you enable->disable or spam click it gets a bit glitchy.

@7nik
Copy link

7nik commented Jun 13, 2024

Updated version (v4).
I'll blame Svelte's transition API for being limiting. I find Vue's transition API much better.

@henrikvilhelmberglund
Copy link

Updated version (v3). I'll blame Svelte's transition API for being limiting. I find Vue's transition API much better.

Is there anything specific that's missing or could be improved? Looks good now except if you double click from enabled->disabled->enabled it disappears instead of showing.

@7nik
Copy link

7nik commented Jun 14, 2024

Is there anything specific that's missing or could be improved?

Some CSS like white-space: preserve and clear: both may still break things. In some edge cases, the condition of margin collapsibility or finding an adjacent margin may be wrong. I read specs, but it's hard to comprehend them.

if you double click from enabled->disabled->enabled it disappears instead of showing

Looks like a bug in all transitions.

@qupig
Copy link
Author

qupig commented Jun 15, 2024

In fact, even using Flexbox, you will encounter bouncing when there is a gap:

source code
<script>
	import { slide } from 'svelte/transition';
	let visible = true;
</script>

<label>
	<input type="checkbox" bind:checked={visible} />
	bounce on "both" when flex-box has gap
</label>

<div class="div3">
	<p>slide in and out 3-1</p>
	{#if visible}
		<div transition:slide style="background-color: orangered;">
			<p>slide in and out 3-2</p>
		</div>
	{/if}
	<p>slide in and out 3-3</p>
	<p>slide in and out 3-4</p>
</div>

<style>
	.div3 {
		display: flex;
		flex-direction: column;
		gap: 5rem;
	}
</style>

REPL

It would be worse if there was a height or max-height there:

REPL

For example in a scroll-box:

REPL or REPL

@qupig
Copy link
Author

qupig commented Jun 15, 2024

Additional, I have to correct that the distinction in my original REPL as bounce on “in” / bounce on “out” was wrong.

In fact if you look at the video frame by frame, you will find that it actually exists in both directions, it is just more prominent in one direction due to visual effects.

@7nik
Copy link

7nik commented Jun 15, 2024

I believe this entire issue will be classified as "won't fix" — margin collapse is a really complex topic (my incomplete solution is already bigger 5-6 times, and yesterday I looked at clear and found a case that can be resolved only by animating multiple elements, which is impossible with css fn, only with tick fn). Plus, the user's CSS can interfere with the animation styles, which can barely be anything.
Here is another example of messing with transition.

In all these cases, there are only two solutions:

  1. change your CSS and/or DOM to remove the CSS interference;
  2. write your own transition function that takes into account your case.

Writing a universal transition function isn't worth it — the code quickly becomes too large and heavy, while the goal of the built-in transition function is just covering common cases.

@qupig
Copy link
Author

qupig commented Jun 15, 2024

@7nik Pretty much agree with what you said.

But really, I think these examples are basic use cases, not complex situations.

This makes the built-in transition function probably almost worthless. (cause it's easy for people to hit the wall)

And it's necessary to explicitly mention these limitations and workarounds in the documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants