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

Safety margins value getter #8

Open
dirkcremers opened this issue May 16, 2024 · 20 comments
Open

Safety margins value getter #8

dirkcremers opened this issue May 16, 2024 · 20 comments

Comments

@dirkcremers
Copy link

dirkcremers commented May 16, 2024

First of all, thanks for maintaining the plugin. It's really helpful, and I appreciate your effort.

Is your feature request related to a problem? Please describe.
After integrating the plugin and configuring settings in capacitor.config.ts, our application achieved an edge-to-edge display, which is fantastic. However, we're encountering issues with content overlapping with the device notch, for instance. We're exploring options to maintain edge-to-edge layout while ensuring content remains within safety margins.

Describe the solution you'd like
We're looking for a getter function that can provide the safety margin values for different devices.

Describe alternatives you've considered

Additional context
As I'm new to Capacitor, I'm still familiarizing myself with its framework. However, I'm eager to learn and contribute to the project in case I can.

@frederikheld
Copy link

There is a different plugin that does this: https://www.npmjs.com/package/capacitor-plugin-safe-area

I've never used it though, so no recommendation, just information.

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

Could you provide me with some info as why you would want a getter function? This plugin injects a CSS variable which you can use directly in your CSS. For example, it enables you to do the following:

#header {
  padding-top: var(--safe-area-inset-top);
}

Maybe it's not very clear from the docs that this is the case. So I will update the docs accordingly. Please let me know if this 'fixes' your issue

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

@frederikheld Thank you for the information. If you'd like to know the differences between that plugin and this one, I've outlined them here: AlwaysLoveme/capacitor-plugin-safe-area#29

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

I think the docs are a bit easier to understand with this change: #11

Let me know what you think and if your issue is resolved now

@frederikheld
Copy link

frederikheld commented May 17, 2024

Thank you for the hint about the injected css variable. A JavaScript getter would still be useful.

Use Case:

I have a map that covers the top half of the screen and goes right to the edge. So there is an unsafe part that the user can't interact with and that will be overlaid with status bar text and icons. The map is centered to a location and I want the centering to compensate for the unsafe area.

@frederikheld
Copy link

Could you provide me with some info as why you would want a getter function? This plugin injects a CSS variable which you can use directly in your CSS. For example, it enables you to do the following:

#header {
  padding-top: var(--safe-area-inset-top);
}

Maybe it's not very clear from the docs that this is the case. So I will update the docs accordingly. Please let me know if this 'fixes' your issue

A question about this: did I understand the whole safe area CSS stuff correctly that env(safe-area-inset-*) only exists on iOS, but your solution var(--safe-area-inset-top) works on all platforms?

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

env(safe-area-inset-*) exists on all platforms (https://developer.mozilla.org/en-US/docs/Web/CSS/env#browser_compatibility). But there's a bug on Android that it doesn't provide the correct values (it will always be 0px) when trying to use it in a webview with Edge-to-Edge enabled

With this plugin var(--safe-area-inset-*) will also exist for all platforms. For all platforms except Android it will just have the exact same value as env(safe-area-inset-*)

@frederikheld
Copy link

Ah, okay. Thanks a lot for the clarification!

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

As for your other question, I'm not sure I'm willing to accommodate for that type of behavior in this plugin, for several reasons:

@frederikheld
Copy link

I understand. But reading computed styles only works in some cases. If the plugin knows those values before the CSS is rendered, it would help if we could access them directly through JS.

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

If the plugin knows those values before the CSS is rendered, it would help if we could access them directly through JS.

Using a new MutationObserver instead of a SafeArea.addListener('safeAreaChanged') for example, is just as fast. They both have to wait till the JavaScript has been loaded.

But reading computed styles only works in some cases.

I'm not sure what you mean by this

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

I have a map that covers the top half of the screen and goes right to the edge. So there is an unsafe part that the user can't interact with and that will be overlaid with status bar text and icons. The map is centered to a location and I want the centering to compensate for the unsafe area.

How is this not already possible using CSS by the way?

@frederikheld
Copy link

frederikheld commented May 17, 2024

If the plugin knows those values before the CSS is rendered, it would help if we could access them directly through JS.

Using a new MutationObserver instead of a SafeArea.addListener('safeAreaChanged') for example, is just as fast. They both have to wait till the JavaScript has been loaded.

But reading computed styles only works in some cases.

I'm not sure what you mean by this

computed style means: the CSS values that the browser has computed after applying all CSS directives. The browser computes those values during rendering. So they will only be available AFTER rendering. But in some cases they are needed before rendering because otherwise you have to update an element that has already been rendered which can cause layout shifts.

This is a common issue when you use getComputedStyle to read the hight of an element with dynamic height because the height will only be known after the element has been rendered and display and position attributes have been applied.

I expect the same issue here.

@frederikheld
Copy link

frederikheld commented May 17, 2024

I have a map that covers the top half of the screen and goes right to the edge. So there is an unsafe part that the user can't interact with and that will be overlaid with status bar text and icons. The map is centered to a location and I want the centering to compensate for the unsafe area.

How is this not already possible using CSS by the way?

Because the Google Maps JS SDK is a very well designed modern library with great DX /s

IDK, ask the Google guys. But you do the centering via JS. Of course I could move the whole map via CSS, but then I don't have the e2e look anymore. I just want to move the center to have the map centered within the safe area.

// EDIT: Maybe it's not clear what I mean by "centering" if you are not familiar with maps: with the Google Maps SDK you can embed an interactive map into your app. And you can define which Geolocation will be centered in the visible area of the map via JS. With the notch, I have a visible area that goes beyond the safe area and I want to have this Geolocation not centered within the visible area but within the part of the visible area that overlaps with the safe area. So I need the safe-area-inset-top value in JS. In my case reading the CSS value with getComputedPropertymight work though as I defer the map rendering to the next rendering cycle (for other reasons), but this is already a hacky solution, so it would be better not to build on top of it :-D

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

Understandable. To support this use case, I would have to write logic for web and iOS as well. Which I'm deliberately trying to prevent - as opposed to the other solutions available. So I'm still not very eager to implement such functionality.

Also it's not possible to listen to safe area inset changes on web apparently: w3c/csswg-drafts#2732, w3c/csswg-drafts#2628

So you will have listen to screen size changes or something. This is not something I'm willing to get into. It will probably get messy and that's not something I'm looking forward to maintain. Especially since probably most users won't need it

@frederikheld
Copy link

Ok, understandable. Would you accept a PR? I won't promise anything, but if I don't find a solution to my case, I might be looking into it.

@tafelnl
Copy link
Member

tafelnl commented May 17, 2024

Yeah sure, go ahead! But to be honest, I can't give you any guarantees I will be merging it. It also depends a bit on the solution you end up finding and implementing. If it's - purely hypothetically - like 10 lines of code, it's a lot more likely for me to accept it and maintain it, than when it's like a few hundred lines of code.

@dirkcremers
Copy link
Author

Hi, sorry for the slow response. Just came back from holiday!

There is a different plugin that does this: https://www.npmjs.com/package/capacitor-plugin-safe-area

I've never used it though, so no recommendation, just information.

Yeah true. However, people were complaining about the compatibility of the plugin with regards to capacitor v6.

So basically, my app now has an edge-to-edge design, which looks great. However, I'd like to add some margin or padding to the interactive content (e.g., buttons) to prevent them from overlapping with the notch. Currently, in the edge-to-edge layout, this issue occurs. It's essential that the interactive content remains clickable. This might align with Frederikheld's comments.

@frederikheld
Copy link

@dirkcremers This is exactly what @capacitor-community/safe-area helps you with. It exposes the correct margins as CSS values so you can use them to set margins to your containers. @tafelnl updated the README.md to make this more clear.

My use case is a different one where I need the value in JavaScript. But yours sounds like it can be solved with pure CSS.

@dirkcremers
Copy link
Author

Thanks for both your replies! I will try it out

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

No branches or pull requests

3 participants