Howto: hide the Portal button on mobile

This might help someone else.

I found the Portal button really intrusive on mobile. This JavaScript in the header hides it:

if (window.matchMedia('(max-width: 640px)').matches) {
    const watch = new MutationObserver((mutations, obs) => {
        const portal = window.frames[0];
        if (portal) {
            watch.disconnect();
            portal.addEventListener("load", function () {
                body = portal.document.body
                body.innerHTML = body.innerHTML + '<style>div.gh-portal-triggerbtn-wrapper {display: none;}</style';
            });
        }
    });
    watch.observe(document, { childList: true, subtree: true });
}

If your theme is loading other iframes, you may need to change the number in frames[0].

This doesn’t hide the pop-up if you trigger it from a link using the ‘#/portal/signup/free’ and other such links.

Note: I’m building my own theme. This code has not been tested with any other themes. It may not work in yours, but it should give you a good start on what to google.

Is there anything preventing you from just using CSS?

@media (max-width: 604px) {
  .gh-portal-triggerbtn-wrapper {
    display: none;
  }
}

There’s a missing > on the closing style tag. It didn’t stop it from working, but just to make copying and pasting easier here is the corrected version of the code.

if (window.matchMedia('(max-width: 640px)').matches) {
            const watch = new MutationObserver((mutations, obs) => {
                const portal = window.frames[0];
                if (portal) {
                    watch.disconnect();
                    portal.addEventListener("load", function () {
                        body = portal.document.body
                        body.innerHTML = body.innerHTML + '<style>div.gh-portal-triggerbtn-wrapper {display: none;}</style>';
                    });
                }
            });
            watch.observe(document, { childList: true, subtree: true });
        }

If you try your CSS you will see that it doesn’t work. The portal code is loaded into an iframe. iframes exist in their own separate document context. Otherwise CSS from the containing page would effect the contents of the iframe.

You could just grab the portal iframe element using JavaScript and add the CSS to it, which I do in this line:

body.innerHTML = body.innerHTML + '<style>div.gh-portal-triggerbtn-wrapper {display: none;}</style>';

All the rest of the JavaScript is necessary to avoid the button popping up and then disappearing. MutationObserver is used to catch the iframe element when it’s added to the document. Then the iframe’s onload event is used to update the CSS once the contents of the iframe are in place.

Ah, I missed that you were applying the styles in the frame :upside_down_face:

What’s preventing you from targeting the iframe wrapper? (assuming you don’t have any portal links)

@media (max-width:604px) {
  #ghost-portal-root {
    display: none;
  }
}

Turns out this code is not a solution to hiding the portal button. It only works when developing locally because you can’t access an iframe’s CSS due to Cross Origin Request policies.

So I found a second solution which I document in this post.

1 Like