Code Monkey home page Code Monkey logo

Comments (11)

jimafisk avatar jimafisk commented on September 27, 2024 13

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.

zoop-btc avatar zoop-btc commented on September 27, 2024 11

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.

a-h avatar a-h commented on September 27, 2024 5

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.

zyriab avatar zyriab commented on September 27, 2024 5

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.

bastianwegge avatar bastianwegge commented on September 27, 2024 3

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.

Riu avatar Riu commented on September 27, 2024 1

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.

gamebox avatar gamebox commented on September 27, 2024 1

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 consts 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.

joerdav avatar joerdav commented on September 27, 2024 1

@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.

cevdetardaharan avatar cevdetardaharan commented on September 27, 2024 1

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.

stuartaccent avatar stuartaccent commented on September 27, 2024

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.

stuartaccent avatar stuartaccent commented on September 27, 2024

thanks, @a-h that looks like a solid idea i will take a look.

cheers stu.

from templ.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.