craftedbygc / taxi

Taxi is a 🤏 small and 🐊 snappy js library for adding slick PJAX navigation and beautiful transitions to your website.
https://taxi.js.org
565 stars 11 forks source link

[Feature/Idea] Add option to add CSS from target page to <head> #6

Closed walpolea closed 1 year ago

walpolea commented 1 year ago

I was attempting to put up a quick demo using taxi and Astro since it's one of the new hot frameworks in the current MPA resurgence. I got it going pretty easily, except for the fact that Astro will only include the component CSS in the head for components that are used on that page. So if I start from the homepage and navigate to another page with a new component, I have missing styles because the target page css never gets transferred into the current page.

I asked if there was a way to ask Astro to compile all component CSS down into a single CSS file but it seems like there isn't.

I could just pull all my single-file component styles out of each component and into a global library of CSS, in fact if you switch to tailwind, since the classes are component-local and the styles are global, this issue goes away. But I really like the DX of the single-file components.

So I'm not entirely blocked here, but I thought it would be neat if there were an option in taxi, similar to how you look for scripts, to look for and inject stylesheets.

One of the Astro folks pointed me to an example where they implemented something similar for a prefetch option: https://github.com/withastro/astro/blob/main/packages/integrations/prefetch/src/client.ts#L54

I think the hard part might be making sure you're not just stuffing the same style tags into the head when you traverse back and forth on pages, but otherwise it could be a neat feature. Or perhaps the solve there is that all the existing CSS is removed and the new CSS is added, since it's likely you're working with an MPA where all the styles that page needs are on the page.

Anyway, curious to know what you think!

My company just launched our new website wearetraina.com which uses taxi! It was a real joy to work with!

jakewhiteley commented 1 year ago

Hi @walpolea !

I will add this as an opt-in feature. It was always on my to-do list ;)

My general approach will be to add a data-attribute to all css on page during load, and then to all style tags injected by taxi. This way I can easily work out which have already been enqueued to the page.

For most users this is fine, but I can possibly see an issue if a user has css files with the same classnames in it, but meant for different pages. Honestly, I feel like that is just bad practise so I probably won't account for it :p

DamChtlv commented 1 year ago

I second this feature request which could be really nice 🤞

For example, i have the issue on WordPress where WooCommerce load some CSS only on some specific pages (like single product) for the gallery photo lightbox (of course i can load those specific CSS myself additionally but that needs some extra-work which could be avoided)

EDIT : Managed to append them using NAVIGATE_IN event and getting them from to.page.head argument like so (code example if someone comes by with the same issue while this feature is not released yet, not the most clean way of doing it but you get the point):

navigateIn({ to, trigger }) {

    const incomingInlineStyles = [...to.page.head.querySelectorAll('style')];
    incomingInlineStyles.map(s => {
        if ( s.outerHTML.includes('woocommerce') || s.outerHTML.includes('wc') ) {
            document.head.appendChild(s);
        }
    });

    const incomingStylesheets = [...to.page.head.querySelectorAll('link[rel="stylesheet"]')];
    incomingStylesheets.map(l => {
        if ( l?.id?.includes('photoswipe') ) {
            document.head.appendChild(l);
        }
    });

}
jakewhiteley commented 1 year ago

@walpolea @DamChtlv This is now done and in 1.5.0 - check out the docs, but works the same way that reloadJsFilter works.

let me know if you have any issues!