Closed GustavoSept closed 2 weeks ago
I think you hit the limits of the function that's used to calculate the CSS class names.
https://github.com/a-h/templ/blob/4f2ce1648b0ba5b28c6716f43e99ac22cb84108f/runtime.go#L257-L264
As you can see, it only uses the 4 chars of the hex-encoded SHA256 hash of the CSS output once any values have been interpolated. Since it's a cryptographic hash, the output value should be evenly distributed regardless of input value, but since it only uses 4 hex chars there's only 65,536 random suffixes, so if a class name has a lot of usage, it's possible to get a clash.
There's a tradeoff between generated HTML output size, and the chance of collision. I think 65,536 is too low. Using 8 instead chars would be a 32 bit uint max value of 4,294,967,295.
IIRC, I originally picked 4 hex values because I looked up random prefixes that were used in Next.js or some other framework.
So, I think the fix for this... is to increase the number 4 to 8, and to add some tests to cover potential clashes to prevent regression.
Happy to take a PR for this, and happy to take a steer on a larger number than 8 from the author of the PR.
Cool project by the way!
So, essentially I was just unlucky then.
Technically, the problem will always be there though. I've thought about it, and any solution to make it go to 0% would require either a degraded performance (control conflicts on a per request basis), or would be too much of a hassle to implement.
I'll make a PR to bump it to 8 as soon as i can.
Bug
Initial context
I'm building an app that involves rendering the periodic table. I'm new to templ (this is my first project on it).
To Reproduce
I've provided the code in this repo. Simply run
docker compose up -d --build
and point a browser tolocalhost:4444
.Bug Description
The code
Each chemical element is a component. I'm rendering them using this code (notice how, for each sub-div, we're creating a new class):
I have a hard-coded Array of Literals containing the periodic table. It looks like this:
Actual behavior
The issue is that this code consistently generates a single naming clash when templ generates the class for Hydrogen and Thallium specifically.
Here's a comparison of outputs:
And the generated HTML for the buggy table:
Notice how Hydrogen and Thallium have the same class name
class="elementWrapperStyle_f781"
. It is correctly generated for Hydrogen, at position (1,1).Things I tried
elementWrapperStyle_f781
as the Hydrogen/Thallium case.Hypothesis
I don't know exactly how templ works internally, as I'm new to it. I suppose this is a Hashing issue when generating the name, hence why it's so consistent on outputting the same result, given the same input. Am i just unlucky that this particular combination of bytes is outputting the same Hash for two different rows, as long as they have the same coordinates?
To test this hypothesis, I've added a third random element to the generated classes:
And this also solves the issue! All elements are rendered where they should (and have a terrible look to them. But this was just to test the hypothesis).
More info
templ info
output Runtempl info
and include the output:Desktop (please complete the following information):
templ version
): v0.2.793go version
): go version go1.23.2 linux/amd64gopls
version (gopls version
): golang.org/x/tools/gopls v0.16.2Observation
I've fixed my issue, by implementing the coordinates directly in the div's style as an attribute, like this:
This solves my problem for now. But what if I actually needed dozens or hundreds of different CSS class names?