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

Shadow-Dom Support #402

Open
hallzy opened this issue Oct 19, 2021 · 7 comments
Open

Shadow-Dom Support #402

hallzy opened this issue Oct 19, 2021 · 7 comments

Comments

@hallzy
Copy link

hallzy commented Oct 19, 2021

Is your feature request related to a problem? Please describe.

We are developing something that uses a shadow dom, but it seems like this project doesn't work fully inside of a shadow dom.

If I understand the code correctly, chrome on desktop shouldn't have a 30px border-right and right on 2 of the os content wrappers, but that is what we see inside of the shadow dom, so at the very least it seems like the detection that exists to determine if those styles should be applied doesn't work correctly inside a shadow.

This basically means that without adding our own code, we end up with different gaps between the content of the scrollable area and the scrollbar for different browsers.

What we have ended up doing in the meantime is calculating the width of the scrollbar on our own, and adding a margin to our content based on that calculation, which works, but having it work built in would be more convenient.

I don't know if there are other things not working as intended, this is just the one that we've noticed.

Also, to make it more convenient to use, it would be nice to be able to easily import the JS as a module. We have a workaround for that right now as well.

Describe the solution you'd like

Support for use inside of a shadow dom, and a JS file that can be imported as a module.

Describe alternatives you've considered

As mentioned, We currently determine the width of the scrollbar ourselves and add a CSS style to account for it.

For importing the JS, we are adding the script tag for that into an iframe, and a promise gives us back the OverlayScrollbars function (a frame is used because our product is embedded onto customer sites, and we are trying to not pollute their global scope).

@KingSora
Copy link
Owner

Good day @hallzy :)
Thanks for the detailed description! Indeed I've never tried to use the library in Shadow DOM yet, so I'm not sure how it reacts... Is it possible for you to create a small example on JSFiddle, CodeSandbox or StackBlitz?
Can you also provide me the output of the command OverlayScrollbars.globals() and the name of your operating system?

@hallzy
Copy link
Author

hallzy commented Oct 22, 2021

I don't know about "small", but I have created as small of an example as I can. https://jsfiddle.net/ex4p6mja/105/

While creating this, I realized that it isn't actually an issue with being inside a shadow dom, so much as it is with us trying to not pollute the global scope.

If I include OverlayScrollbars as a script tag in the main HTML document (or even inside the shadow dom) it works fine. But both of those solutions mean that we have an OverlayScrollbars function attached to the main window object (shadow doms do not have their own window object).

So, what we do is use ES modules to import code that we want into the files that we need access to that code. In some cases, as is the case with OverlayScrollbars, there is no module we can import like this. So our workaround is to create a throwaway iframe that we load all of our scripts in that cannot be loaded as a module, and when the script is finished loading we resolve a promise which we can import which has the result of the script execution.

There isn't really a way to import modules that I could find in JS fiddle, so I just put it into the same file, but it would normally be imported.

Once the promise finishes we call the scrollbar function on the scrollable div I created

And the getHTML and getCSS functions at the bottom can be thought of as template imports that we would normally have so that we can easily insert this stuff into the shadow.

So basically, we can work with OverlayScrollbars even if we don't have a module, but if we could just import a module and have that work, that would be easiest.

And at least with the way we are doing it now with the iframe, we end up with a 30px right and border in chrome which as I mentioned in my previous description, I don't think it supposed to happen.

I hope this helps :D

My OS is Ubuntu, and the output of OverlayScrollbars.globals() is:

{
    "defaultOptions": {
        "className": "os-theme-dark",
        "resize": "none",
        "sizeAutoCapable": true,
        "clipAlways": true,
        "normalizeRTL": true,
        "paddingAbsolute": false,
        "autoUpdate": null,
        "autoUpdateInterval": 33,
        "updateOnLoad": [
            "img"
        ],
        "nativeScrollbarsOverlaid": {
            "showNativeScrollbars": false,
            "initialize": true
        },
        "overflowBehavior": {
            "x": "scroll",
            "y": "scroll"
        },
        "scrollbars": {
            "visibility": "auto",
            "autoHide": "never",
            "autoHideDelay": 800,
            "dragScrolling": true,
            "clickScrolling": false,
            "touchSupport": true,
            "snapHandle": false
        },
        "textarea": {
            "dynWidth": false,
            "dynHeight": false,
            "inheritedAttrs": [
                "style",
                "class"
            ]
        },
        "callbacks": {
            "onInitialized": null,
            "onInitializationWithdrawn": null,
            "onDestroyed": null,
            "onScrollStart": null,
            "onScroll": null,
            "onScrollStop": null,
            "onOverflowChanged": null,
            "onOverflowAmountChanged": null,
            "onDirectionChanged": null,
            "onContentSizeChanged": null,
            "onHostSizeChanged": null,
            "onUpdated": null
        }
    },
    "autoUpdateLoop": false,
    "autoUpdateRecommended": false,
    "nativeScrollbarSize": {
        "x": 0,
        "y": 0
    },
    "nativeScrollbarIsOverlaid": {
        "x": true,
        "y": true
    },
    "nativeScrollbarStyling": false,
    "overlayScrollbarDummySize": {
        "x": 30,
        "y": 30
    },
    "cssCalc": "calc",
    "restrictedMeasuring": false,
    "rtlScrollBehavior": {
        "i": true,
        "n": false
    },
    "supportTransform": true,
    "supportTransition": true,
    "supportPassiveEvents": true,
    "supportResizeObserver": true,
    "supportMutationObserver": true
}

@hallzy
Copy link
Author

hallzy commented Oct 27, 2021

Hi @KingSora, just wondering if you've had a chance to look at this yet :)

@KingSora
Copy link
Owner

@hallzy not yet.. sorry I'm a bit busy, but I'll try to do it this weekend :)

@hallzy
Copy link
Author

hallzy commented Oct 27, 2021

No problemo 😃

@lincolnthree
Copy link

Has anyone gotten this working with a viewport / scroll container contained within a shadow DOM element / component?

@lincolnthree
Copy link

lincolnthree commented Oct 14, 2024

Adding my notes to this. I was able to get OverlayScrollbars working in the Shadow DOM, but it required custom initialization (see docs: https://kingsora.github.io/OverlayScrollbars/), and also required injecting the OverlayScrollbars styles into the shadow DOM element's root <style> element.

See this issue for notes: #682 (comment)

You also need to manually call instance.update() periodically on the OverlayScrollbars object you instantiate in order to get it to properly init or resize whenever content is added or removed to the Shadow DOM elements, if that comes in dynamically (if that content would change the height of the scrolling content/element).

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