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

Safari Issue - Html component - visual height offset on certain screen resolutions. #720

Open
Sepi-Florez opened this issue Jan 13, 2022 · 25 comments
Labels
bug Something isn't working

Comments

@Sepi-Florez
Copy link

Sepi-Florez commented Jan 13, 2022

  • three version: 0.136.0
  • @react-three/fiber version: 7.0.24
  • @react-three/drei version: 8.4.0

Problem description:

Sometimes an Html component with the transform prop will be visually misplaced (downwards).

This problem can be experienced when the following statements are true:

  • You are using the Safari browser (I used version 15.1).
  • You are using a certain resolution. I experienced the problem on 1920 x 1080, but not on 2560 x 1440.
  • The three js canvas height is equal to an odd number.

Relevant code:

I have reproduced the issue in the following example. When adjusting the height of the viewport, you can see that the html element will jump up and down. When the element is misplaced you can also see that the position of the button in the bottom right corner is still at the correct position by hovering somewhat above the button.

Suggested solution:

I suspect that Safari is messing up an calculation that is used to position the Html element. I'm not sure which calculation that is, but maybe there is a way to prevent that from happening.

@Sepi-Florez Sepi-Florez added the bug Something isn't working label Jan 13, 2022
@Jouska
Copy link

Jouska commented Jun 18, 2022

  • three version: 0.136.0
  • @react-three/fiber version: 7.0.24
  • @react-three/drei version: 8.4.0

Problem description:

Sometimes an Html component with the transform prop will be visually misplaced (downwards).

This problem can be experienced when the following statements are true:

  • You are using the Safari browser (I used version 15.1).
  • You are using a certain resolution. I experienced the problem on 1920 x 1080, but not on 2560 x 1440.
  • The three js canvas height is equal to an odd number.

Relevant code:

I have reproduced the issue in the following example. When adjusting the height of the viewport, you can see that the html element will jump up and down. When the element is misplaced you can also see that the position of the button in the bottom right corner is still at the correct position by hovering somewhat above the button.

Suggested solution:

I suspect that Safari is messing up an calculation that is used to position the Html element. I'm not sure which calculation that is, but maybe there is a way to prevent that from happening.

Just wanted to hop on to say I'm struggling with the same issue on all iOS 15 browser apps. Any Drei HTML element with transform prop added will be positioned below where it should be, but positions fine and as expected on all desktop browsers across the board.
Have noticed I can improve on iOS Safari by enabling CSS 3D Transform Interoperability in experimental features.

Re-created it with a stripped back test, just in case my project was adding something strange, but re-creates the exact positioning glitch with:

<Canvas> <OrbitControls /> <group position={[0, 0, 0]}> <Plane scale={(1, 1, 1)}> <meshBasicMaterial color='black' /> </Plane> <Html transform> <p style={{ color: 'white' }}>test</p> </Html> </group> </Canvas>

*@react-three/drei: "9.3.4",
*@react-three/fiber: "8.0.10",
*three: "0.139.2"

@edbrdi
Copy link

edbrdi commented Sep 11, 2022

Same problem here on iOS but seems to impact only the iPhone mini 12/13, iPhone 8 Plus & iPhone 11 Pro Max.
There is a displacement between the displayed html elements and the interaction zone. So even if I shift the view to display it as it should be you can't click on anything.

You can see it for example on this demo: https://9keg6.csb.app/ (https://codesandbox.io/s/9keg6)
image

I also have the same kind of issue as mentioned by Sepi-Florez on Firefox depending on the browser width/height.

@ThatLukaszGuy
Copy link

Experiencing the same thing apple devices with iOS 15 (ipad and iphone 13 pro max). The issue hasn't been resolved yet and there isn't really much info about it on the web

@roman-march
Copy link

I have the same problem on iOS :(

@Vochsel
Copy link

Vochsel commented Oct 19, 2022

Having the same problem here on Chrome, windows, desktop. Seems to be related to a flex div above (next to) to the canvas div... Doing some non-normal positioning of the canvas, so perhaps something is getting lost. Oddly not a problem with Orthographic camera...

Can't seem to replicate my problem yet unfortunately.

@kangjungsuck
Copy link

Got same issue in chrome too.

@gnoem
Copy link

gnoem commented Mar 28, 2023

i have the same issue with mobile chrome and safari on iOS 16.3.1 (iphone 12), i suspect it has something to do with the device pixel ratio being relatively high (>2). using macOS safari's dev tools/mobile device emulator, I'm able to reproduce the bug on every emulated device option by setting the DPR to 3x:

screenshot of safari dev tools

the DPR on my iphone 12 is 3, which might explain why the issue is happening there. haven't gotten the chance to test on other devices but it would be sick if this could get fixed at some point ☹️

@ryumy97
Copy link

ryumy97 commented Jun 7, 2023

I had the same issue with mobile safari on Iphone X and Iphone 14 pro, I am no expert but playing around with some values and was able to close some gaps.

Reduced fov value puts reduced css property perspective and translateZ value.
Which gave less displacement shifts but gave much more rotation on the html element.

so I am guessing if can have some sort of multiplier on rotation part on the matrix, we will be able to get the result that we want?

@roeku
Copy link

roeku commented Jun 21, 2023

Experiencing similar issue where a Html component with transform prop is positioned lower on mobile than in desktop.

Any update on this bug?

@shot-codes
Copy link

I have this issue with Safari on MacOS. I was looking for a hack-fix and learned a couple of things I thought I would share. Looking at Image 1 below, you can see safari on the left and chrome on the right. The deep red is an HTML element, and the grey square is a PlaneGeometry. You can there are two things going on, there is a slight offset in the position, as well as a difference in scale. In Image 2 I account for the scale by increasing the size of the html by 1.335.

In Image 3, you can see the same 2 elements, replicated 400 units with a roughly a 20 unit step. Here it is apparent there is also a, what I will call, scaling issue in regards to not only the size of the elements themselves, but the positions applied to them. I address this in Image 4 by applying the same 1.335 factor to both the x and z coordinates of the HTML elements.

Video 1 showcases a bigger problem. Despite accounting for these scaling issues, whenever you pan the camera, it appears as if that changes the position of the HTML elements parallel with the plane you are panning.

Image 1

Screenshot 2023-06-21 at 15 34 59

Image 2 - Safari, with size of HTML scaled by factor of 1.335

Screenshot 2023-06-21 at 15 43 06

Image 3

Screenshot 2023-06-21 at 15 44 33

Image 4 - Safari, with position of HTML elements scaled by a factor of 1.335

Screenshot 2023-06-21 at 15 37 35

Video 1

Screen.Recording.2023-06-21.at.15.55.08.mov

@katiasmet-93
Copy link

Any updates or workarounds on this issue?

@halitaydin
Copy link

Any updates or workarounds on this issue?

#720 (comment)

This can be a workaround. You can change margin-top according to the pixel-ratio.

@media (-webkit-device-pixel-ratio: 3) {}

Also you can wrap it with portrait.

@media (orientation: portrait) { @media (-webkit-device-pixel-ratio: 3) {} }

@donmccurdy
Copy link
Member

@chadimessmer
Copy link

chadimessmer commented Nov 3, 2023

I have the same problem.
My solution (probably not the best, but it works) is :

  • check if the browser is Safari (using react-device-detect)
  • check if the height of the canvas is an odd number
  • if yes remove 1px
  • add an event listener on window resize (not if it is a mobile device, useless)
import { isMobile, isSafari } from "react-device-detect";

export default function Canvas() {
  const [height, setHeight] = useState("100dvh");
  const canvasRef = useRef();

  useEffect(() => {
    const measureCanvasHeight = () => {
      const canvasElement = canvasRef.current;
      let canvasHeight = canvasElement.clientHeight;

      if (isSafari && canvasHeight % 2 !== 0) {
        setHeight(`${canvasHeight - 1}px`);
      }
    };

    window.requestAnimationFrame(measureCanvasHeight);
    const handleResize = () => {
      setHeight("100dvh)");
      measureCanvasHeight();
    };

    if (!isMobile && isSafari) {
      window.addEventListener("resize", handleResize);
      return () => {
        window.removeEventListener("resize", handleResize);
      };
    }
  }, []);

  return (
    <div style={{ height: height }} ref={canvasRef}>
      <Canvas>
        <CanvasStuff />
      </Canvas>
    </div>
  );
}

@thomasryu
Copy link

Having the same issue, <Html> element display the wrong position on iOS browsers with a dynamic address bar

@samzabala
Copy link

Having the same issue here too. any updoots?

@donmccurdy
Copy link
Member

A bug has been reported to WebKit at https://bugs.webkit.org/show_bug.cgi?id=263454. In the meantime, rounding the size of the canvas to even numbers seems to avoid or limit the issue:

@IsaacUA
Copy link

IsaacUA commented Jul 21, 2024

Any updates?

@chandlercasey13
Copy link

This issue is consistent across Chrome on iOS for me too. Has anyone noticed this as well?

@chandlercasey13
Copy link

chandlercasey13 commented Sep 28, 2024

Also, just theory crafting, could clamping the dpr of the Canvas component solve this issue? ex. Canvas dpr={[1,2]}

@IsaacUA
Copy link

IsaacUA commented Sep 28, 2024

You can use this fix https://www.npmjs.com/package/@isaac_ua/drei-html-fix
Just wrap canvas element

@chandlercasey13
Copy link

You can use this fix https://www.npmjs.com/package/@isaac_ua/drei-html-fix Just wrap canvas element

I’ll give this a try

@chandlercasey13
Copy link

I found the above npm package by @IsaacUA helpful. It fixed all but one HTML element which still gave me a positioning error. Learned later that the reason I had an issue with it is because it had a fixed sizing of 75px x 80px. Changed the odd number of 75 to 74 and it magically works. This is only on iOS from what I can tell

@chandlercasey13
Copy link

chandlercasey13 commented Oct 1, 2024

You can use this fix https://www.npmjs.com/package/@isaac_ua/drei-html-fix Just wrap canvas element

Wanted to say again that this worked really well! The only suggestion I’d have is to make the -1px to +1px. This way there wouldn’t be a slight white line visible to the user. This is how I ended up using it

@IsaacUA
Copy link

IsaacUA commented Oct 4, 2024

You can use this fix https://www.npmjs.com/package/@isaac_ua/drei-html-fix Just wrap canvas element

Wanted to say again that this worked really well! The only suggestion I’d have is to make the -1px to +1px. This way there wouldn’t be a slight white line visible to the user. This is how I ended up using it

Good point. I've made the necessary changes to the npm package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests