Comments (11)
These tools require a more complex setup in that you have to have node installed, and will need an esbuild config mjs file, a package.json and a postcss config
For me personally, this is something I'd really like to avoid. The main reason I picked Templ over Svelte for my new app was to avoid the JS ecosystem. I'd prefer a built-in solution, even if it had less features, but of course I understand the constraints on developer time and know you have a lot of competing priorities. Templ is awesome overall, thanks for sharing your thoughts with us in real-time!
from templ.
I started building with templ precisely because I don't want to setup JS tooling. Integrating with them is fine as long as it's optional.
from templ.
I love what you're doing there @stuartaccent.
Couple of ideas (not sure if you've already of thought of this)...
If you wanted to, you could update the gcss.Style
type to have a Render
method.
func (s *Style) Render(ctx context.Context, w io.Writer) error {
//TODO: Get a CSP nonce from the context.
//TODO: Check errors etc.
io.WriteString(w, "<style type=\"text/css\">\n")
s.CSS(w)
io.WriteString(w, "\n</style>")
}
func (s *Style) CSS(w io.Writer) error {
// Existing
}
You could also create a gcss.Stylesheet
type which is an alias of []Style
, and add the Render
method to that too.
type Stylesheet []Style
func (ss Stylesheet) Render(ctx context.Context, w io.Writer) error {
//TODO: Get a CSP nonce from the context.
//TODO: Check errors etc.
io.WriteString(w, "<style type=\"text/css\">\n")
for _, s := range ss {
s.CSS(w)
}
io.WriteString(w, "\n</style>")
}
Doing this would mean that gcss.Style
and gcss.Stylesheet
both implement templ.Component
and you can drop styles into components. Combined with the new templ.Once
function (#750), you'd be able to have CSS that's only loaded once per HTTP request.
So, defining a set of styles as a templ.Component
that's only rendered once per HTTP request.
package deps
var buttonStyles = gcss.StyleSheet{
{
Selector: ".button",
Props: gcss.Props{
AlignItems: props.AlignItemsCenter,
BorderRadius: radius,
Display: props.DisplayInlineFlex,
FontSize: fontMd,
FontWeight: props.FontWeightMedium,
Height: spacing10,
JustifyContent: props.JustifyContentCenter,
LineHeight: leadingTight,
PaddingTop: spacing2,
PaddingRight: spacing4,
PaddingBottom: spacing2,
PaddingLeft: spacing4,
},
},
// More...
}
var buttonStylesHandle = templ.NewOnceHandle()
templ ButtonCSS(ctx context.Context, w io.Writer) (err error) {
@buttonStylesHandle.Once() {
@buttonStyles()
}
}
Then, using those CSS classes as components in templ:
package components
templ Button(name string) {
@deps.ButtonCSS
<button class="button">{name}</button>
}
templ ButtonPrimary(name string) {
@deps.ButtonCSS
<button class="button-primary">{name}</button>
}
If you then use Button
and ButtonPrimary
on a page (bad API design, I know, it's just as an example - https://gopress.io/ uses a struct for attrs which is likely more appropriate here).
But, in this case the CSS would only be loaded into the page as a <style>
element if required by the component.
Obviously, I'm not aware of gcss
, so maybe you've already discounted these ideas. 😁
Either way, it looks very great.
from templ.
I think keeping a minimal in-house solution and allowing the user to plug in something else if they want is a good approach.
from templ.
I agree with the proposal, as I don't think CSS should be a scope for templ at all. I would also like to opt out of the JS ecosystem (@jimafisk ) but I think it's almost impossible right now.
We migrated a medium sized go+react project completely to templ. As we swapped away from React components, we also needed interactivity. We looked into web-components, especially things like stencil or lit but this would ultimately bring back JS dependencies and build processes back into the project. We ended up using HTMX + Alpine.js which is an awesome combination that really drives the idea of locality of behavior and HATEOAS, but it definitely is not a silver-bullet and I'd be open to better solutions.
from templ.
As a Gopress creator, all I can say is - CSS in template engines is a huge topic. It is important to answer the questions: what architecture are we creating for, where and how will we embed styles, what do we want to share/reuse or what should be global, how will we introduce changes (e.g. after changing from the UI designer in Figma). Some challenges:
- if you have inline css then there will be problem with global changes;
- if you put styles in files you need to serve only what you use;
- if you are rendering mail templates maybe you need pure inline css;
- if you have got microfrontends/htmx architecture, then the number of challenges doubles;
- if you would like to make library components like we have in FE frameworks (scoped styles), you should not render
<style>css code</style>
every time you render arrays of components; - much, much more...
Gopress has a very unique approach in that we have sets of Tailwind classes that are transferred one-to-one from Golang to, for example, Vue, because we use an atomic design approach. These sets create variants based on attributes. Instead of classes you can use just pure css (it will be worse DX, but the effect can be more or less the same). DX is very important - you can see immediately what styles the class gives (syntax suggestions from Tailwind). The component is isolated and the only dependency is the Tailwind configuration file.
Because Tailwind is also not perfect i'm working on alternative solution (without Tailwind) and one more thing - by design, Gopress was built in such a way that components could be generated and changed from an application designed for this purpose. This is related, on the one hand, to AI and, on the other hand, to the problem of technology adoption.
Gcss is interesting because it has no dependency and in some cases it can be good solution, definitely worth attention.
from templ.
style attribute
Currently, the style attribute can't contain templ expressions. I think this could be relaxed, and any CSS within the style attribute could be pushed through a CSS sanitization process. This would allow the use of style={ fmt.Sprintf("background-image: url(%v)", url) } or the use of a dynamic builder (not implemented, just an example) style={ css.BackgroundImage(url).PaddingPx(10, 10, 10, 10) }.
This is very much needed. I am trying to use Templ for HTML Emails, and am finding that this undocumented restriction on style
elements is very much a roadblock to success. Even in 2024, inline style blocks still do not have the necessary email client support to allow me to use them, so the existing CSS tooling in Templ falls short for me there. And to your point, if they worked I'd be doing something with Tailwind to do this anyway as that is my normal workflow for web page HTML.
I think that not baking this in from the start - or at the absolute minimum, documenting it - was a mistake. I know that the design philosophy behind Templ is to be helpful, sometimes erring on the side of being "hand holdy", but these sorts of seemingly arbitrary restrictions can lead to a lot of disillusionment from developers just trying to ship product.
Oh, and one last thing I'll mention is I agree with @jimafisk that I too do everything I can to avoid having a package.json
in my application. I vendor HTMX, and only work with the tailwindcss
executable.
For context
This is all I want to be able to do in an HTML Email. I want to keep my color scheme and theme information the same so I want to use some const
s to do so in inline styles:
templ emailLayout() {
<!-- Don't worry about the rest -->
<body style={ "margin:0; padding:0; background-color:"+common.BackgroundColor+";" }>
<!-- Don't worry about the rest -->
}
One very last thing...
I have a similar issue with the <!DOCTYPE>
tag, there is a much more expressive grammar allowed inside of that tag than what Templ allows for, and not utilizing it can cause compatibility concerns with Emails. I can understand that you may not care to support HTML Email authoring in Templ - but it's a big and important use case for web services, so you should at least consider that use case.
from templ.
@a-h I think we are circling a decision here. It may be worth us splitting this into a few different features...
- Allow dynamic style attributes
- Document recommended approaches going forward
- Add a generate warning for use of
css
/script
components - Create migration that converts
css
/script
components to use script/style tags - Remove
script
/css
components
from templ.
In my opinion, using build system should be optional but even when we use templ, we have a build step that generates go files. So what we can do is getting the best solution (performance and compability) into the build system in order to achieve faster builds and better developer experience.
My suggestion would be using lightningcss[repo].
from templ.
im not advertising what ive done just a mere food for thought. Im using temple and very quickly found I needed more than the css provided so started our own way of generating css from go. very early days and still working out the best way to use it and what we need from it.
https://github.com/AccentDesign/gcss
from templ.
thanks, @a-h that looks like a solid idea i will take a look.
cheers stu.
from templ.
Related Issues (20)
- Getting this error while using the latest version or templ and gopls HOT 11
- proposal: improve developer experience for basic passing of data to JS expressions HOT 8
- Templ config for passsing additional variables to component HOT 1
- Proxy not ready, retrying infinitely HOT 2
- Improved dev flow HOT 1
- Proposal: Introduce JsGenericVar for Event and Element Access in element event handlers HOT 5
- `templ generate` takes a long time for unformatted files HOT 6
- refactor: update `templ generate` to support pwd being a symlink HOT 3
- Templ formatting breaks imports at v0.2.747 HOT 7
- Composable templates do not render properly in tests HOT 1
- App freeze using air proxy HOT 1
- templ-vscode "Request textDocument/codeAction failed" HOT 2
- Streaming Not Working
- [Proposal] Improve embedding components HOT 2
- proposal: Go comments within HTML tags HOT 1
- Raw go errors if block ends with a comment
- LSP crashes after being started by kakoune-lsp HOT 4
- How to prevent cache HOT 1
- .templ file with only script elements leads to unused import HOT 1
- Anyway to instantiate a templ once per rendering context? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from templ.