Live data from Hacker News

Vanilla JavaScript support for Tailwind Plus

tailwindcss.com

191–200 of 202 posts

Re: Vanilla JavaScript support for Tailwind Plus

#191

Earlier quoted context omitted.

Put simply: if you’re using something like React, Vue, Svelte, whatever, then Web Components are strict overhead in terms of bundle size and runtime overhead. And when there’s impedance mismatch between the two worlds, which I hear is particularly common in React (can’t attest it personally, I don’t use React), you have to compromise on functionality or ergonomics, or else do fancier bindings, at which point why even…

Here's my put simply: We've got some UI components built with html, CSS and JavaScript. They use web standards. We want to add them into web frameworks that are built in JavaScript. They are built for html, CSS and JavaScript. No need to overcomplicate things. And for a universal component library I'll happily accept 7kb extra overhead in my 4mb React slop website

But the data binding part isn't the same across frameworks. In Vue you have v-model, in React it's props and so on. The way you build a custom Select Dropdown, for example, will be very different between the two.

Sure, the actual HTML/CSS parts will be identical, but the JS portion is the issue here, because frameworks simply handle things differently there. In Vue you have reactive proxies getting passed around and a custom event system, whereas in React it's all objects and methods passed around as props.

Re: Vanilla JavaScript support for Tailwind Plus

#192

Earlier quoted context omitted.

When people complain about CSS being hard I'm not sure what parts of it really? It's rarely explained further too. As someone that did a lot of CSS like 15 years ago when fullstack was the norm, then just sporadically for various non-public tooling, is that yes, the old ways of trying to position things really sucked and had a lot of hacks and some of those trail-n-error "how-does-this-change-the-elements-position" s…

The hard part isn't just placing the correct styles, that is trivially learnable, it comes in when you have multiple people touching the same code, or even in small teams with a large enough project. In a large enough project, and IME that "large enough" point gets hit very quickly, things become messy and it becomes difficult to figure out why something is rendering in the way it is. Every non-tailwind project I've…

This sounds like it agrees with my point of going overboard with DRY? But this is true for pretty much all languages. When people go overboard with abstractions it usually ends up bad over time and changes, as in your example as well, starts becoming a dredge. But this is solved by experience and better practices, not throwing out the baby with the bath water. Tailwind seems strangely defeatist to me - going from one extreme to another.

Re: Vanilla JavaScript support for Tailwind Plus

#193

Lovely. Verbosity aside, now on top of knowing CSS you need to learn another hierarchical system within class names.

I think Tailwind became popular because React doesn't have a good way to combine CSS and JSX in a single file, unlike Vue/Svelte which support single-file components. With Tailwind utility classes you can just add them to your JSX template. React problem solved.

Re: Vanilla JavaScript support for Tailwind Plus

#194
post #119

Earlier quoted context omitted.

Oh yeah, when I open a typical big project with Tailwind I always love to see some: Team Settings Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces. Cancel Save Changes

This is like repeating code without using a function. If you have a nice abstraction - the same becomes cleaner like below. Team Settings Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces. Cancel Save Changes

Isn't this abstraction essentially just.. creating classes?

Re: Vanilla JavaScript support for Tailwind Plus

#195

Earlier quoted context omitted.

class soup is what tailwind is. It's terrible because is just abbreviations of css attributes which you still need to know because you'll inevitably fiddle around devtools trying things out. The only "smart" thing about it is leaning strongly on using rem. how can it spill out onto the page? it's inline css. The (rare) inline selectors target only descendants. Truth is that it's winning over because it works best wit…

> Truth is that it's winning over because it works best with LLMs. Inline soup works better than looking for styling on different files in the context of the project, so here we are. I saw this on another recent tailwind thread and I’m not sure I agree. LLM might be helping adoption, but I’ve been seeing and using tailwind for years without really going near LLM coding

oh I'm not saying tailwind didn't have significant adoption before, but post LLMs is when major adoption from frameworks came as the default choice.

Re: Vanilla JavaScript support for Tailwind Plus

#196

Earlier quoted context omitted.

People would rather have to parse out a big dumb list of classes than look at the actual list of what properties affect something, with a clear ability to drill down into them. Its madness, akin to carpenters giving up hammers, preferring to use glue, because they hit their thumb a few times by accident

On the site I maintain at work, if I check literally any of the old components that don't use tailwind, what I see in the styles list of the devtools is 75 different variants of .card__wrapper or whatever all overriding each other, and it's often an abject nightmare trying to figure out which of the 75 different .card__wrapper (or is it .card { &.__wrapper} ?) classes is the one I care about at the moment.

Click over to the computed styles tab, and now you have a list of all the styles that apply to an element, regardless of source. Click the arrow next to one and it shows you where it comes from

Also, have you ever tried to update old designs using tailwind? It's a disaster. Far easier to know what styles the ugly bem card class you mentioned apply to, rather than an arbitrary b-2 m-1

Re: Vanilla JavaScript support for Tailwind Plus

#197

Earlier quoted context omitted.

We use web components at the hook for my company's advertising code but I've found them pretty thoroughly disappointing, personally. They make it simple to trigger code execution but their API isn't really that good

The whole point is to make it simple to trigger code and to be interoperable. Then you write whatever code you want to implement the component. Web components are not analogous to frameworks because frameworks tightly couple the component interface and lifecycle hooks with the component implementations. Those are properly decoupled in web components and you bring whatever rendering layer you prefer.

Yes but their choice to abandon constructors as a primary part of the lifecycle means that adding some kind of member field to the class will leave it inherently uninitialized in the `connectedCallback`. All fields basically have to be declared as `| undefined` if you're using typescript, which leads to reall ugly code:

    class MyComponent extends HTMLElement
    {
        private width: number | undefined; // must be | undefined or
                                           // you'll get a typescript error
        constructor()
        {
            // useless, unpredictable
        }

        connectedCallback()
        {
            this.initAttributes();
            // using this.width will still require an undefined check at some point
        }
   
        initAttributes()
        {
            this.width = Number(this.getAttribute('width'));
        }
    }
If you could reliably load attributes in the constructor instead of being forced to do everything in connectedCallback (or even better, load them automatically with decorators), it would make typescript implementations much cleaner. Just some way to validate attributes before connectedCallback, or work with typescript guarantees would make this much more attractive

Re: Vanilla JavaScript support for Tailwind Plus

#198
post #119

Earlier quoted context omitted.

Oh yeah, when I open a typical big project with Tailwind I always love to see some: Team Settings Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces. Cancel Save Changes

This is like repeating code without using a function. If you have a nice abstraction - the same becomes cleaner like below. Team Settings Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces. Cancel Save Changes

Such a pleasure to see a nice tailwind abstraction, at some point inlining starts looking just a bit too much, luckily there is a solution ;)

  /\* tailwind.css \*/
  .card-container {
    @apply flex flex-col md:flex-row items-center justify-between
      w-full max-w-screen-xl px-6 md:px-12 py-8
      bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700
      rounded-lg shadow-md space-y-6 md:space-y-0 md:space-x-8
      text-sm text-gray-700 dark:text-gray-300 font-medium tracking-tight leading-relaxed
      hover:bg-gray-50 dark:hover:bg-gray-800 transition-all duration-300 ease-in-out;
  }

Re: Vanilla JavaScript support for Tailwind Plus

#199

Earlier quoted context omitted.

The whole point is to make it simple to trigger code and to be interoperable. Then you write whatever code you want to implement the component. Web components are not analogous to frameworks because frameworks tightly couple the component interface and lifecycle hooks with the component implementations. Those are properly decoupled in web components and you bring whatever rendering layer you prefer.

Yes but their choice to abandon constructors as a primary part of the lifecycle means that adding some kind of member field to the class will leave it inherently uninitialized in the `connectedCallback`. All fields basically have to be declared as `| undefined` if you're using typescript, which leads to reall ugly code: class MyComponent extends HTMLElement { private width: number | undefined; // must be | undefined…

The constructor is a part of the lifecycle, and always has been. It wasn't abandoned.

The lifecycle of custom elements reflects the behavior of the HTML parser and DOM APIs. Attributes aren't consistently available in the constructor because the HTML parser is streaming and may yield to the main thread at any time. So the element is constructed first, possibly before attributes are parsed. Attribute also aren't available because when element are constructed imperatively they will never have attributes at first, ie:

    // ctor is called, no attributes!
    const el = document.createElement('my-element'); 
    // now there will be an attribute:
    el.setAttribute('width');
You also shouldn't ever consider attributes to be fixed in a web component, since they may be added and removed at any time, and of course may never be set in the first place. You should implement attributeChangedCallback() and give your element defined behavior for any set of possible attributes.

Or you can use a helper library like Lit which does let you declare and consume your attributes via decorators.

Re: Vanilla JavaScript support for Tailwind Plus

#200

Earlier quoted context omitted.

Yes but their choice to abandon constructors as a primary part of the lifecycle means that adding some kind of member field to the class will leave it inherently uninitialized in the `connectedCallback`. All fields basically have to be declared as `| undefined` if you're using typescript, which leads to reall ugly code: class MyComponent extends HTMLElement { private width: number | undefined; // must be | undefined…

The constructor is a part of the lifecycle, and always has been. It wasn't abandoned. The lifecycle of custom elements reflects the behavior of the HTML parser and DOM APIs. Attributes aren't consistently available in the constructor because the HTML parser is streaming and may yield to the main thread at any time. So the element is constructed first, possibly before attributes are parsed. Attribute also aren't avail…

I understand all these things, I think they are weaknesses. They make web components less generally useful, and really only useful for one thing. Constructors are only useful for dependency injection.
Post reply on HN