barba
barba copied to clipboard
CSS file doesn't load on page transition
Hi, I have a problem with the css and js files. I would like to use different style sheets and scripts on the various pages. when I open the page everything normally works, but when I change the page using the transition it is not loaded. How can I solve it?
for example in the contact page i want to use contact.css. contact.css is used only in this page. when I access the page directly the css works correctly but when i came from (for example) index.html that doesn't have contatti.css the style doesn't load.
As far as I'm aware, everything will need to be loaded outside of the container. Combine your CSS files into one and it'll work fine. In my opinion, this is only adding more http requests every time the user goes to another page, increasing the load time.
As for JS, it won't be re-evaluated when a transition completes, so it too will have to be compiled and loaded outside of the container. You'll have to reinitialize any functions using barba hooks.
On barba v1:
Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container) {
// JS functions here
});
on barba v2:
barba.hooks.afterEnter( ( data ) => {
// JS functions here
} );
I agree with @c0mrx,
Just one file for CSS and another one for JS = no more https requests when you switch between pages.
Anyway, this is a feature that will be implemented soon in the v2, called @barba/head, allowing Barba to automatically fetch head files that are not in the cache, mostly scripts and stylesheets.
:wink:
Any update about the @barba/head addition?
I have a similar issue.
I have some 'detail' pages that get some inline styles injected. The styles get inject in the head and are specific for each 'detail' page. So it should reload the head on every 'detail' page.
Hi @Geestig,
Still a feature to implement into the library, but no roadmap specified for the moment.
Thanks for using Barba and for your patience :wink:
Do you happen to have a temporary solution/idea for my issue?
I was thinking on using the beforeEnter hook to check the incoming HTML for the style tag en inject it into the head of the page. And remove it afterwards with the afterLeave hook.
Using the beforeEnter hook to inject styles using <link> into the <head> seems to be the appropriate solution :+1:
Be sure to properly remove the styles on the afterLeave hook and it will work just fine :+1:
For a complete example, see: https://github.com/barbajs/barba/issues/485#issuecomment-580158426
I was thinking on using the beforeEnter hook to check the incoming HTML for the style tag en inject it into the head of the page. And remove it afterwards with the afterLeave hook.
@Geestig there's no need,technically or otherwise, to make things more complicated and parse out <style> or <link> elements to move them or their contents to the <head>. Generally speaking: CSS within style/link elements anywhere on the page is not scoped but follows the cascade and whatever @media rules within it apply even if added after the fact (page load).
If you include CSS (snippets) to the incoming HTML to only format that additional content it'll be automatically enabled by the browser for the whole rendered page; remove the HTML and style elements/CSS and all is gone. Using ids to easy select these element will simplify your code.
Since you already fetch additional files from the server, using sth. like
<style>@import "page-foo.css"</style>
<style>.bar {color:fuchsia}</style>
... the remaining HTML for that page ...
or
<link rel="stylesheet" href="page-foo.css" media="all" >
... the remaining HTML for that page ...
None of this would bring down the page (nor server), yet @import just like <link> -- in this case -- will be cached and allows you to use and reuse external .css chunks on various "pages". If you prefer CSS code inline, you're also good to go, but loose caching.
You're unlikely to experience FOUC with this approach.
Don't be too religious about minimizing HTTP requests :) Your server probably runs with http2 anyways.
Enjoy.
@WebMechanic thanks for the reply, but it was a style that was added upon load automatically. I solved it by simply filtering it out of the head and adding it to the currect active head as @xavierfoucrier had suggested.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Hi there, just wondering if @barba/head is still planned? Barba.js is amazing but fight with
and loading additional scripts & styles is a hughe hassle. Would be amazing to get that "official" solution.
Hi @ouun,
It steel planned of course, but not in the next few months, sorry.
For now, you should use a workaround to properly manage styles inside your head.
Thanks for your interest into Barba :wink:
As far as I'm aware, everything will need to be loaded outside of the container. Combine your CSS files into one and it'll work fine. In my opinion, this is only adding more http requests every time the user goes to another page, increasing the load time.
As for JS, it won't be re-evaluated when a transition completes, so it too will have to be compiled and loaded outside of the container. You'll have to reinitialize any functions using barba hooks.
On barba v1:
Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container) { // JS functions here });on barba v2:
barba.hooks.afterEnter( ( data ) => { // JS functions here } );
So I'm a very new and young dev can someone explain me how should I implement it in my JS code.
Hi @OutdatedDesigns,
Please use the Slack workspace in order to ask the whole community for support. Join using the invite link here: https://barba.js.org/docs/getstarted/useful-links/#Developer.
Thanks! :wink:
This is also an issue for seo! Barba does not keep the head title and meta tags current with the page content.
Hi @mudlabs,
This if off-topic here :wink:
And no, this is not a problem for SEO to not have head title and meta tags updated with the current page, see https://barba.js.org/faq/#What-about-SEO-concerns.
A solution I came up with for my needs here:
I had a problem with web components (custom HTML elements) not initializing when their script tags were in the barba-container. Here's what worked:
barba.init({
...whatever settings you have,
transitions:[{
name: : "your-transition-name",
beforeEnter(data) {
const nextEl = data.next.container;
if (nextEl) { //Just a little check to make sure we don't run this on an error
// Find all scripts in the next container
const nextScripts = nextEl.querySelectorAll('script');
//Iterate over incoming script tags
nextScripts.forEach(nextScript => {
const src = nextScript.src;
//Duplicate check - no need to re-execute scripts that are already loaded.
if (document.head.querySelector('script[src="' + src + '"]') == undefined) {
//Have to create a new script element in order for the browser to execute the code
const newScript = document.createElement('script');
newScript.src = src;
newScript.async = true;
document.head.append(newScript);
nextScript.remove(); // Cleaning up the script in the container;
}
}
},
(...whatever other transition functions you need, like after(), once(), etc.)
});
I'm pretty sure this solves the primary problem of the script not being executed, by creating a new script tag in the header for each script tag being loaded in the body. (It seems as if the body HTML is being loaded in such a way that re-executing scripts doesn't happen, which is normal for AJAX replacement).
Some thoughts:
- This obviously doesn't help with inline scripts, but it could easily be modified to create new script tags with the content of inline scripts from the barba-container.
- I don't see any reason to remove scripts which were injected in previous barba lifecycles, is there a good reason to do this?
- I also didn't have any need to reload
<link>elements in the head, they seem to execute just fine from the incoming barba container. - What else is needed for
@barba/head? Meta Tags are probably the biggest other tag to iterate over, and then probably JSON metadata.
Hi guys, I needed to load inline scripts on each Barba transition. Inspired by @evankford, I came up with the solution below. Also related to #485.
window.Barba.currentInlineScripts = []
window.Barba.init({
transitions: [{
sync: false,
afterLeave({
current,
next
}) {
if (next.container) {
// Remove old scripts appended to the head
window.Barba.currentInlineScripts.forEach((currentInlineScript) => {
currentInlineScript.remove()
})
// Find all new scripts in the next container
const nextScripts = next.container.querySelectorAll('script');
// Iterate over new scripts
nextScripts.forEach((script) => {
// Check if it is an inline script
if (!script.src) {
// Clone the original script
const newScript = script.cloneNode(true)
// Create a new <script> element node
const newNode = document.createElement('script');
// Assign it innerHTML content
newNode.innerHTML = newScript.innerHTML
// Append to the <head>
const element = document.head.appendChild(newNode)
// Save for later
window.Barba.currentInlineScripts.push(newNode)
}
// Remove the inline script
script.remove()
})
}
}
}]
})
I hope it helps. Any progress on the @barba/head plugin by the way?
I hope it helps. Any progress on the
@barba/headplugin by the way?
Bumping this request
Yes, it's still planned, no need to bump again. I am reopening the issue in order for everyone to know.
Thanks again for your patience 😉
Thanks @stepanjakl I'm also working to get link[rel=stylesheet] elements from head! It would be nice if it were included in @barba/head
WIll we ever get the head we deserve?
Any further updates on this?
I think now with http2, there's not as much need to have everything bundled into a single file and progressively load scripts based on the page your on, including using CDNs.
Forgive me if I'm wrong, but hasn't this been planned for 2 years or more?
@aaronstezycki As soon as we will find time to work on this, but since Barba v2 release, it is not a priority: this explained why we haven't worked on this since the beginning. Even with http2, it's still a good practice to bundle everything into a single file, especially when working with dynamic imports. And finally, it really depends on the app you are building.
Anyway, the issue is still opened and we know that in certain cases, the head plugin could be useful.
Thanks for your patience! :wink:
:wave: Keep in mind that:
- this project is open source / still maintained
- not sponsored (as of today we have no sponsors)
- contributors are working on it on their own free time (for free)
Okay, that's a fair answer. :)
I would say though, the everything in this statement could be argued against. Http2 was created to allow for more freedom to separate files and suffers less from multi-file bottlenecks. Like you proceed to say, depends on the app though. Large libraries/scripts would preferably be only downloaded on the page they are being used on, i.e login scripts, large SPA's etc.
Anyway, thanks for reply, .ps I'd be up for donating page.
Thanks @aaronstezycki :wink:
I am not an expert in http2, but as I said, it depends on the application, and today with code splitting / three shaking / dynamic imports, it's still possible to have a consistent+robust app with only one bundle. But, it also depends on what you want to do for your clients, because needs / possibilities can differ from a project to another.
Currently, there is no donating / collective page for the BarbaJS project, but you can support maintainers using Github Sponsors, what I highlighted in the beginning of 2022 here on Slack: https://barbajs.slack.com/files/TFDHZ8NN5/F030B08EB8U.
I will probably update the README to make this more clear in the future.
Thanks anyway for your support in open source projects! :v:
I'm trying to integrate Barba in a Shopify theme. Even though I bundle css & js to a single file, Shopify also ads their own script tags to the head depending on the page type. (For example: On product page support for accelerated payment methods like Apple Pay, Marketing pixels for tracking, Cart functionality etc)
The head plugin would be a perfect use case for this. Would be great if this could be considered again. Thank you!
+1
+1 :)
+1
+1
+2 ? ... :trollface: