/|\  /|\
/|\ /|\•15mo ago

[fresh] injecting css into head in a component

When I inject css in the head of my html in a component, it works perfectly, but when I reuse the component somewhere in my html, it reinjects the css a second time
19 Replies
/|\  /|\
/|\ /|\OP•15mo ago
@Deno AI Helper
Deno AI Helper
Deno AI Helper•15mo ago
Sure, I'd be happy to help! Could you please provide me with the question you'd like me to answer?
/|\  /|\
/|\ /|\OP•15mo ago
When I inject css in the head of my html in a component, it works perfectly, but when I reuse the component somewhere in my html, it reinjects the css a second time @Deno AI Helper
Deno AI Helper
Deno AI Helper•15mo ago
According to the documentation, when you use plugins in Fresh, you can inject CSS into the <head> of your page as inline CSS. This is done by adding the CSS to the styles array in the PluginRenderResult object that the render hook returns. Each entry in the styles array can define the CSS text to inject, as well as an optional id for the style tag, and an optional media attribute for the style tag. However, the documentation does not explicitly mention how Fresh handles the injection of CSS when a component is reused in the HTML. If the CSS is being injected each time the component is used, it might be due to the way the render hook is implemented in your plugin. One way to avoid this could be to check if the CSS has already been injected before adding it to the styles array. However, the documentation does not provide a clear answer on how to do this. If you're experiencing issues with this, it might be helpful to debug your render hook implementation to see why the CSS is being injected multiple times. 🦕
marvinh.
marvinh.•15mo ago
@kamil.l Fresh maintainer here. I'd love to look into this. Do you have a repo or something I can take a look at?
/|\  /|\
/|\ /|\OP•15mo ago
I have a repo but the code is really to complicate for this, I can try to make a simple reproducable example My component looks like that:
import { JSX } from "preact";
import { Head } from "$fresh/runtime.ts";

interface props extends EventTarget {
title: string;
content: string;
linkText: string;
};

export default function Card(props: JSX.HTMLAttributes<props>) {

return (
<>
<Head>
<link rel="stylesheet" href="/css/card.css" />
</Head>
<div></div>
</>
);
}
import { JSX } from "preact";
import { Head } from "$fresh/runtime.ts";

interface props extends EventTarget {
title: string;
content: string;
linkText: string;
};

export default function Card(props: JSX.HTMLAttributes<props>) {

return (
<>
<Head>
<link rel="stylesheet" href="/css/card.css" />
</Head>
<div></div>
</>
);
}
If you need more information, don't hesitate to ask
marvinh.
marvinh.•15mo ago
ah it looks like we don't de-duplicate tags added via <Head />
/|\  /|\
/|\ /|\OP•15mo ago
Is there any simple way to avoid this?
marvinh.
marvinh.•15mo ago
The easiest way to work around this is to hoist the <Head /> tag to the route
/|\  /|\
/|\ /|\OP•15mo ago
Oh ok thank you, I was hopping to do it automatically
marvinh.
marvinh.•15mo ago
not sure how to do that without fixing the bug fwiw: injecting the css style again doesn't affect the correctness of the page and the browser deduplicates the requests.
/|\  /|\
/|\ /|\OP•15mo ago
Is there a way to read the current head to check if it's already there?
marvinh.
marvinh.•15mo ago
Currently it writes into as standard context value. It's exported as HEAD_CONTEXT. Be aware though that this will likely be removed with fixing this bug, so you might need to remove that workaround again when the next version of Fresh comes out
/|\  /|\
/|\ /|\OP•15mo ago
Ok ty I'll check that
marvinh.
marvinh.•15mo ago
FYI: here is the PR that fixes this https://github.com/denoland/fresh/pull/1793
/|\  /|\
/|\ /|\OP•15mo ago
Ok amazing thank you May I ask when it'll become available in fresh?
Deno AI Helper
Deno AI Helper•15mo ago
It seems like you're experiencing an issue where CSS is being injected multiple times when a component is reused in your HTML. This could be due to the way the render hook is implemented in your plugin. According to the Fresh documentation, the render hook allows plugins to control the timing of the synchronous render of a page and inject additional CSS and JS into the rendered page. The CSS is injected into the <head> of the page as inline CSS. Each entry can define the CSS text to inject, as well as an optional id for the style tag, and an optional media attribute for the style tag. However, the documentation does not provide specific details on how Fresh handles the injection of CSS when a component is reused. If the CSS is being injected each time the component is used, it might be due to the way the render hook is implemented in your plugin. One way to avoid this could be to check if the CSS has already been injected before adding it to the styles array. However, the documentation does not provide a clear answer on how to do this. If you're experiencing issues with this, it might be helpful to debug your render hook implementation to see why the CSS is being injected multiple times. 🦕
marvinh.
marvinh.•15mo ago
@kamil.l not sure when the next Fresh release is going to be, but you can always point the import map at any git commit sha. See https://fresh.deno.dev/docs/examples/using-fresh-canary-version
Using Fresh canary version | Fresh docs
For cases where the latest release doesn't fit your needs.
/|\  /|\
/|\ /|\OP•15mo ago
Ok thank you