ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
50.47k stars 13.53k forks source link

bug: swiper inside ion-content not recognizing dir="rtl" when rendered dynamically #29368

Closed Farbdose closed 2 weeks ago

Farbdose commented 3 weeks ago

Prerequisites

Ionic Framework Version

v7.x, v8.x

Current Behavior

When placing a swiperjs.com swiper inside an ion-content (and rendering it with a delay) the swiper doesn't recognize the surrounding dir="rtl". Only happens with ion-content.

I'm not sure if this is a swiperjs problem or an ionic problem.

Expected Behavior

rtl should propagate through ion-content regardless of when the component is rendered.

Steps to Reproduce

  1. create a div with dir="rtl"
  2. put a swiper inside an ion-content inside the div and render it a few ticks later using ngIf
  3. try swiping
  4. swiper doesn't swipe

See linked stackblitz, first swiper works on clean page load but breaks after stackblitz livereload, second swiper doesn't work at all, 3rd and 4th work.

Code Reproduction URL

https://stackblitz.com/edit/angular-ywh4p1-vza2cj?file=src%2Fapp%2Fapp.component.html

Ionic Info

@ionic/angular: 8.0.0 @ionic/core: 8.0.0

also present in at least 7.6.2 or earlier.

Additional Information

No response

liamdebeasi commented 3 weeks ago

Does this issue reproduce without Swiper? If it only reproduces with Swiper, then you should file a repo on the Swiper repo instead.

Farbdose commented 3 weeks ago

Yes and no, this is swiper specific but it only happens when I put the swiper in ionic.

I suspect it's actually some edge case interaction between ionic and the swiper but I created an issue with them as you asked https://github.com/nolimits4web/swiper/issues/7483

I was a bit hesitant to create a new bug there as I created a feature request asking for this exact thing a few days ago and got closed without any conversation with "we already do this" https://github.com/nolimits4web/swiper/issues/7479

liamdebeasi commented 2 weeks ago

Thanks for the additional information. I am able to reproduce this, but this does not appear to be an Ionic bug.

The main issue here is that Swiper calls getComputedStyle on the swiper-container element to query for the direction. This requires that the correct direction is set on that element at the time that code is run.

This code is run after the ancestor's Shadow DOM has been created, but before the slot has been added. In Chrome, this means that swiper-container will not inherit the correct direction until after the slot has been added. Since this code is run before that happens, the code I mentioned above reports that swiper-container has direction: ltr set.

This issue also reproduces with the dum-my component added in your sample. Your original code used ng-content which puts the swiper-container inside of the Shadow DOM. This is different from ion-content which projects swiper-container in a slot instead. By changing ng-content to slot in dum-my the issue will reproduce there as well.


As for why this is the case, it has to do with how CSS inheritance is defined:

For a [DOM] tree with shadows, inheritance operates on the flattened element tree. This means that slotted elements inherit from the slot they’re assigned to, rather than directly from their light tree parent.

This means that swiper-container should inherit from the slot element inside of ion-content not ion-content itself. Since slot has not been added yet, swiper-container does not have anything to inherit from, so it uses the default value for direction which is ltr.

Here's an example of this problem outside of Ionic: https://codepen.io/liamdebeasi/pen/rNbPKxN?editors=1010 I also checked the color property too to demonstrate that this issue is not specific to the direction property.

I am going to close this, but let me know if you have any questions.