I know Lit is used a lot but I’m always looking for new approaches.
I know Lit is used a lot but I’m always looking for new approaches.
<el-dropdown class="relative inline-block text-left">
<button class="inline-flex w-full justify-center gap-x-1.5 rounded-md bg-white px-3 py-2 text-sm ...">
Options
</button>
<el-menu anchor="bottom end" popover class="w-56 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black/5 transition transition-discrete ...">
...
</el-menu>
</el-dropdown>
Bootstrap: <div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button">
Dropdown button
</button>
<ul class="dropdown-menu">
...
</ul>
</div>
(I realize you have full control over looks with TW, but Bootstrap and others have utility classes too for the common stuff.)If it saves you a bunch of time writing and maintaining the sort of components they are showing off, probably worth it?
It's like putting if postgres expected you to pay them a monthly fee.
edit: I see now their pricing is one-time perpetual access. Still, I'm genuinely curious how well this model works.
My biggest advice appears to be: remember that the Shadow DOM is optional.
[0] https://worldmaker.net/butterfloat/guides/web-components/
[1] https://github.com/WorldMaker/jocobookclub/tree/main/src/bf
[2] https://github.com/WorldMaker/butterfloat-presentation/pulls...
It's funny because they're unintuitive to their end users. However, that is deliberate - they are looking for a decision point that comes after, but not too long after, devs have heavily invested in the product.
Edit: apparently all framework integrations and the whole library and functionality is behind the same paywall? And regular tailwind is just the css classes/build process that I used to know? Do people not understand how casual readers might be confused about all this?
Nice to see devs picking up web components.
[0]: https://developer.mozilla.org/en-US/docs/Web/API/Web_compone...
Kind of like how Jeff Bezos threw a bunch of money at 37signals at some insane valuation, which helped them completely avoid the VC trap.
<Menu>
<MenuButton>Dropdown button</MenuItems>
<MenuItems>…</MenuItems>
</Menu>
which is even better than what Bootstrap provides since you get type safety for component props (and more opportunities for customization than what Bootstrap allows)Tailwind Plus (the commercial product) is like buying an off-the-shelf template. It’s just a collection of themes and pre-built components — useful for devs who want to get started quickly on a project, but it’s cookie-cutter and can easily be replicated by anyone with Tailwind itself.
Design tokens are the one Tailwind feature I genuinely like. Everything else – kill it with fire. Just use whatever scoped CSS your stack does (<style> in Svelte/Vue, Emotion in React?).
That has implications for event handling and style encapsulation.
But I understand that funding open source is never easy & I still appreciate tailwind from the bottom of my heart simply because some might hate it for what it is, but I appreciate that I have options to being with (daisy,tailwind etc.)
If anyone who has ever contributed to open source is reading this. Thanks. I am a real frugal person but one day, I want to earn enough money that I can donate to you guys without hesitation and be an open source contributor too.
edit: I can’t speak for Adam etc., this is just my impression. My impression is that they want to build a business of which tailwind (the open source project) is one part. I think that regardless of money in the bank they would want to have revenue generating projects. Laravel is a good comparable.
> It’s just a collection of themes and pre-built components
All reusable web components could be described as an optionally themed pre-built component. That's kind of the point.
Honestly, I kinda feel like 37Signals would have been better off with the founders having someone to report to...
I have a diagnosed anxiety disorder and I’ve benefited GREATLY from talk therapy in numerous ways. I’m an advocate for therapy. I simultaneously stand behind his post as a healthy nudge for many.
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 with LLMs. Inline soup works better than looking for styling on different files in the context of the project, so here we are.
I have a daisyui project too, so I might try this later.
edit:
Confirmed, they removed alpine from their copy/pastable code. Now you see:
<!-- Include this script tag or install `@tailwindplus/elements` via npm: -->
<!-- <script src="https://cdn.jsdelivr.net/npm/@tailwindplus/elements@1" type="module"></script> -->
This sucks because I have been using alpine and now I can't copy paste the examples ~_~
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.
With so many frameworks out there it's infeasible to build custom wrappers for them all. With web components they can build once, and work everywhere. It's only up to the frameworks to make sure they have great web components support (which just means great HTML support).
Web components are a mess but this is a great application of them: shipping reusable components that work in all frameworks. It's the one and only killer application of web components.
Frankly I'm surprised they're marketing this as "for vanilla javascript" and not as a "now supports all frameworks" type positioning.
No idea if he still does ok from it, but he certainly did at one stage.
> To pull this off, we built @tailwindplus/elements — a library we're releasing exclusively for Tailwind Plus customers.
This means if you want to use the Tailwind UI components without a Javascript framework, you have to build them all yourself, or pay.
<el-dialog-panel class="mx-auto block max-w-3xl transform overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black/5 transition-all group-data-closed/dialog:scale-95 group-data-closed/dialog:opacity-0 group-data-enter/dialog:duration-300 group-data-enter/dialog:ease-out group-data-leave/dialog:duration-200 group-data-leave/dialog:ease-in">
Lovely. Verbosity aside, now on top of knowing CSS you need to learn another hierarchical system within class names.We will see how long it takes for LLMs to make headway in this area specifically.
There are so many framework specific libraries like shadcn, and the community set about building half finished conversions for different frameworks like Vue, which are always several iterations behind and don't really work properly. They have their own version of the docs and it all relies on a specific version of Vue and a specific version of Tailwind and whatever else. It's an abomination.
Start with headless UI as a base and then build wrappers for specific frameworks if you really feel the need. But the wrappers should be syntax sugar only and linked directly to the base library.
I'm sure it's all more complicated than that but a man can dream.
Has Tailwind support out of the box, just had to mod oxide to get non threaded wasm support in the browser
Instead of being coupled to a specific JavaScript framework, these custom elements work anywhere you can use a <script> tag
But...React is still the elephant in the room here. Maybe TW is just in a different world if they're truly just anticipating folks using this via a `<script>` tag, but if not, very curious how they're going to deal with some of the web component (WC) stuff we've dealt with, like:- Despite signals/promises, React 19 didn't add full support for WC. React uses a diff algorithm for reconciliation. There are some rough edges for any "complex value" cases in the incomplete solution for 19's WC support with client vs server side rendering. This results in us being required to use 'use client' for parts of our component architectures, meaning WC providers aren't able to take full advantage of SSR.
- WCs are async loading, which in combination with React can have a negative impact on performance for things like core web vitals (and the dreaded cumulative layout shift).
- WCs are just different from React patterns. Each WC creates a DOM element, but React components don't have to, which just inherently means different shapes of code.
- React focus management libraries don't play nice with WCs. We've talked to multiple devs/companies that were excited about/using WCs that backed out because of cross-ecosystem complexities like this.
- React Native is, uh....a whole thing.
On a somewhat separate note...one of my complaints about TW historically has been that it feels like "just classes" (great!), yet requires a build step (oh...). I'm a little confused to see them leaning into `<script>` tags given that, so am I just missing something?
<div id="parent" class="group"><a class="group/hover:bg-black">Hover</a></div>
This eliminates the need for JS for a wide range of things.px-3, py-2, bg-red-400 etc. are everywhere in tailwind code and they become more or less undocumented conventions. Technically you can configure them, but practically without unintended side effects on an existing project? And if you make extensive config changes, have you just locked yourself out of the ecosystem?
I don't use bootstrap, but from a brief look at the documentation it seems much more reasonable to diverge from defaults. Looking at themes (https://themes.getbootstrap.com/) it seems more flexible than an average tailwind setup.
<div class={tw(
"block",
"transform transition-all",
"bg-white ring-1 ring-black/5 rounded-xl shadow-2xl",
"max-w-3xl mx-auto overflow-hidden",
"group-data-closed/dialog:opacity-0",
"group-data-closed/dialog:scale-95",
"group-data-enter/dialog:duration-300",
"group-data-enter/dialog:ease-out",
"group-data-leave/dialog:duration-200",
"group-data-leave/dialog:ease-in"
)}>
...
</div>
I currently do this manually but it would be nice to have some tooling to automate that kind of format.You don’t need a shadow dom, you don’t need rerendering of everything when a simple value changes. You simply need web components and scoped js/ts with vite or whatever rollup you use.
So things are fine but we do need to reverse the trend which is why we are pretty focused on the commercial side of things right now.
We started a corporate sponsors/partner program recently, and I'm hoping that will earn us enough funding to focus more on the free/open-source stuff, since that's where we create the most value for the world anyways. Fingers crossed!
I strongly prefer "button is-primary is-fullwidth" over the long list of tailwind classes.
I just find that at some point, Tailwind gets in the way and I revert back to plain CSS. TW invariably then just becomes another style src in the HTML.
Because people are lazy and don’t make a component for everything. And some people are even lazier and don’t make UI components at all. I’ve seen a project where there was a Button component and that’s it. Well, that was vibe coded probably so makes sense.
> Inline soup works better than looking for styling on different files in the context of the project, so here we are.
Only if you have a separate .css. If you do UI components with [insert your favourite CSS-in-JS solution], it stays in the same file. Maybe the proximity to markup within the file is important?
But no, Tailwind has been rising in popularity long before LLMs came along.
I find it very nice that you can re-theme or brand your app with virtually no code or class changes.
It will also commonly not play nicely with some more advanced aspects of the frameworks, like server-side rendering will probably suffer (depending on how exactly things are done).
In a world where React is dominant and you’re wanting to use React yourself, targeting Web Components just doesn’t make sense.
Then “headless” makes it worse. The more comprehensive implementations have a lot of overhead.
This sort of thing is objectively ugly and takes a minute to learn. The advantages of this approach I found is two-fold
1. You can be more confident that the changes you are making apply to only the elements you are interested in changing
You are modifying an element directly. Contrast with modifying some class that could be on any number of elements
2. You can change things around quite quickly
Once you're well familiar with your toolset, you know what to reach for to quickly reach a desired end state
But consider that a UI is 100% state management and side effects (so fundamentally imperative and asynchronous). On top of that it takes about three revisions for any tool to require bespoke display of something (everybody has an opinion). They also bring a layout engine which is best expressed in constraints.
And somehow we are trying to shoehorn all this into a functional paradigm.
I stumbled on Tailwind in 2018 and introduced it to a team looking to revamp a pretty massive project. I remember that the initial proposal I made was to treat it like Bourbon[1] and write classes that build on Tailwind’s utilities. That way, you can still have `.button`, `.button-primary`, and `.button-primary__accent` etc without the cryptic classes in the HTML.
However, after reading Tailwind, the team found it much easier to write the pre-built classes and stack them as they progressed. And it worked; if I don’t care about how the code is written, things were consistent. It reminds me of “Pixel Perfection” before the responsive design era, when things looked as designed in Photoshop and printed for clients during presentations.
// Not actually needed, here
// for competition
.group {}
// Child selector
.group:hover group\/hover\:bg-black {
background-color: black;
}
// Which is essentially the same as
.group:hover child {
background-color: black;
}
No one is writing a long paragraph of styles for _every_ button in their app.
I like BEM personally. "navbar__item" scopes the styling to the nav item
> Once you're well familiar with your toolset, you know what to reach for to quickly reach a desired end state
This also applies to plain CSS, doesn't it?
The big value add that Tailwind brought isn't their utility classes IMO - it's their philosophy around having a design system of consistent coloring and spacing. I actually borrowed that for my own projects. It taught me to be a lot more diligent about specifying the system upfront. Put it in CSS variables and re-use those
If I do something myself, I keep using bootstrap, as it is good compromise for those of us not honoured with CSS mastery.
Ironically I have no issues making great looking UIs with native toolkit.
In 5 years the tailwind craziness will be replaced by the next shiny CSS of the month.
It’s the same as how they enable media queries for example, they’re not using JS just plain CSS, but they’re making it available with these inline classes.
But, if you're building any long-term product, investing in your own design system + component library will put many many more miles on the board in terms of DX, flexibility, aesthethic language, dependency footprint, etc.
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
<div class="group relative w-full max-w-md mx-auto bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-2xl shadow-lg p-6 md:p-8 transition-all duration-300 hover:shadow-xl hover:border-blue-500 dark:hover:border-blue-400">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg sm:text-xl font-semibold text-gray-800 dark:text-white tracking-tight group-hover:text-blue-600 dark:group-hover:text-blue-400 transition-colors">Team Settings</h3>
</div>
<p class="text-sm sm:text-base text-gray-600 dark:text-gray-400 leading-relaxed mb-6">Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces.</p>
<div class="flex flex-col sm:flex-row gap-4 sm:justify-end">
<button class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 rounded-md transition-colors">Cancel</button>
<button class="px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-400 dark:focus:ring-blue-300 transition-all duration-150">Save Changes</button>
</div>
</div>
I doubt that changes your mind, though.
I'm never gonna argue learning proper CSS wouldn't be better, but Tailwind is by far the path of least resistance for someone that has no interest in writing frontend for a living. It's like putting legos together, it requires very little thought to get from nothing to a decently looking website.
Inline css
1. Can’t use media queries (responsive design).
2. Gets you to specificity hell - you loose ability to cascade.
3. Does not follow any system or reuse of values.
4. Values can’t be centrally changed. Utility clases are still classes - when you change class value it changes everywhere where the class is used.
5. Its verbose. Utility classes can have multiple css rules.
Conceptually it might seem that inline css is similar but thats just feeling. Functional css (utility classes) are about composing classes with simpler (one purpose) behaviour together to create complex behaviour.
This is not how custom functional css codebase looks. In custom projects you change the system/configuration to fit the project. You create your own utilities for example you wont have “text-lg sm:text-xl font-semibold tracking-tight” but will have class “font-heading-2”. Similarly you will create button/input classes that have you basic styles.
Generally you start with just simple utility classes inside html and go from there and where it make sense or its too complex you separate to more complex class. You end up with short css file that only has these special components and none of the basic stuff.
For most elemets it ends up like “flex justify-center gap-4”. In BEM i have to invent “nav-secondary__header” put it in correct place and hate myself when i need to change it to “flex justify-beween”.
Tailwind popularised functional css but is also aimed at masses/noobs. Somehow some of those concepts also resonated with some experienced users.
It is also pretty good configurable utility framework but that is secondary and new version 4 is worse at customisation.
So people are moving to https://unocss.dev/ with tailwind naming conventions.
I don't think Tailwind has a built-in `:has` tool, but I suspect it would be easy to add one as a custom class.
Because most of those classes are per component.
If you have a single card component defined with these classes, and then repeat it 20 times on the page, then of course the output will look like a giant mess.
> How did tailwind get so popular?
- quick to understand and get started with
- much cleaner for components than the variety of CSS-in-JS libs
- (mostly) do not require fighting CSS with BEM-style atrocities
- come with nice default styles and colors that can be easily changed and extended
> Learn plain CSS. It's really good now
CSS is okay now. We only just got nesting and scoping
for me the only thing I wish bootstrap had was the money color options tailwind has e.g bg-indigo-400 etc
Just a reminder that jQuery was once dominant, too.
At that point, why not write these in CSS instead? There is little advantage in using the tailwind shorthand classes in your own class definitions.
- You can use plain CSS variables for theming
- You're bringing back the supposed downsides of cascading and shared classes
- simple Gzip compression will achieve similar size reduction as the utility classes
Working on your codebase now requires full knowledge of the Tailwind utilities, layers, directives, pseudo-classes, theming, and all the complexity that comes along with them.
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" seems to still apply, but are much rarer now with grids/flex etc. But the structure of CSS itself is very straight-forward to me and has almost always been?
Is what's really going on that when people are trying to use vanilla CSS they go overboard with keeping CSS DRY? Which ofc ends up with an interdependent mess that's becomes increasingly harder to change. Just stop that? Start namespacing and copy pasting? CSS doesn't need to be compact.
EDIT: I'm sorry, I mixed you up with the other user who was replying criticising other people's CSS knowledge.
But like the person you’re responding to said, the ergonomics improve for the majority of cases that are just ‘flex items-center gap-2’.
And yes, you could write it all yourself but Tailwind is a good set of defaults for those classes and minimizes bike-shedding and improves consistency. These are useful things in lots of teams.
I don’t really use Tailwind on smaller personal projects because I love CSS, but in an org of mixed skill levels, it’s pretty damn useful.
(Also, Tailwind uses CSS variables. It had solid support for them in the last major and first class support for it in the current one.)
> There is little advantage in using the tailwind shorthand classes in your own class definitions.
There are few massive advantages. I dont have to figure out how to name these classes. Other people in the team know them too. And when they see class they dont know they know its something custom probably for a reason.
> You're bringing back the supposed downsides of cascading and shared classes
I never said cascade is bad. Creating new flat class with 0-1-0 specificity doesn’t break Tailwind. I’ve been through enough of - everything has specific class that’s nested/scoped… from my experience and usecase it’s harder for little benefit except neater html.
> simple Gzip compression will achieve similar size reduction as the utility classes
I meant custom css that you write by hand and have to scroll trough. Not the result pushed to browser. With functional css you manage to do most of the work in html and what doesn’t make sense you can do traditionaly. For example i dont like doing complex hover interactions in Tailwind so the html has all the layout utilities but also custom class that only has this custom interaction behaviour.
> Working on your codebase now requires full knowledge of the Tailwind utilities, layers, directives, pseudo-classes, theming, and all the complexity that comes along with them.
Is knowing Tailwind naming conventions worse than not having any convention at all? My experience is that Tailwind are just classes that are documented. Without it we would have classes that are undocumented.
There are cases where functional css is not that beneficial. Like in long running products which have single file component workflow where css is scoped and html/css live in same file. But in work i do in small team we just found it to solve many our painpoints.
Yes, CSS in theory is powerful and has everything necessary to avoid using Tailwind, but in practice CSS has a major flaw: You’re almost required to build a semantic model to get the full power. But this ignores that designers are working with mood and emotion just as much as document structure and information architecture. Capturing these more nebulous concepts as logical semantic rules is very difficult if not impossible. Tailwind just codified what everyone already did: Skip the semantic dance (“Making that text bold would be really cool, but what does it mean to be cool, as a general rule?”) and just create semantic rules like “bold” and “red”.
The "good CSS" you're talking about was always the product of convention, and it was never sustainable for big, long-term projects. The CSS Zen Garden showcase only made sense in a world where everyone shared the same document or document structure. Those insane stylesheets depended on the source HTML document's inherent structure, which is the exact opposite of separation of concerns.
Inexperienced developers always underestimated the complexity they were adding to their project by using overly abstract classes and hidden structures between the DOM and the stylesheets. Tailwind (or any reasonable CSS methodology even) recognizes these problems and solves them.
> If you do UI components with [insert your favourite CSS-in-JS solution], it stays in the same file.
I mean you can but "best practice" all around has been to put them separate and that's reflected in the majority of github repos in the training data of the LLMs.
> Maybe the proximity to markup within the file is important?
that's my assumption, yes. Seems to me LLMs work best when they output the relevant tokens right there with the markup instead of referencing some previous tokens even if relatively close.
styled components was the recommended solution in popular UI libraries like React MUI up until 2023 when chatgpt came out. Tailwind REALLY blew up with LLMs.
Not everything needs that level of separation, but to say that even basic separation is a problem to be solved by jamming everything into the class list is completely wrong.
The big problem with Vanilla CSS is that's it's sort of like Perl. It's a read-only language in practice.
Yes, theoretically, you can have perfect semantic CSS classes and use those. In practice, not every button is the same and you'll need slightly different styling in different places.
Yes, we could go in and change the .button class. But who is using the .button class? Where is it used? Nobody knows, and you can't find out. So editing that class is EXTREMELY risky. I have seen many an entire application break because some dev decided to edit CSS. The bigger the application, the bigger the risk.
Where I work, we have 1500 devs. Does anyone know the complete set of usecases a CSS class would have? No. Even if I gave you a month to research it, you would not find out. So you cannot edit CSS classes, it's far too risky.
So, the result is that everyone just tacks on to the end of the CSS. And now, in your clean code world, you have 50 different button classes. Um... whoops.
If you want to compartmentalize, what you can do is use components, in whatever backend/frontend framework you have. You can have the component have their own state and allow users of the component to change parts of it. Then, it doesn't matter how "unclean" the tailwind is - because you'll almost never see it. But if you need to change it, you can, without destroying the entire application. No more 50 button classes, and no more read-only implementations.
We had css, then SASS/LESS/etc, now Tailwind.
In the days of just CSS people would create variables/functions for their CSS in their server side language & have the server side language create the CSS. SASS/LESS allowed us to do that in stylesheets.
Now we have Tailwind (and of course CSS variables). Tailwind (and the code editor plugin devs) have done an amazing job at making a great workflow to handle CSS, especially in component type UI designs.
* Shout out to Foundation and Bootstrap for also helping us get to where we are today. Foundation is underrated in the history.
class App extends HTMLDivElement {}
customElements.define(“main-app”, App)
<body><main-app/></body>
This is the simplest web component.More examples:
the second part of your answer answered it perfectly. Thanks
> Has Tailwind support out of the box, just had to mod oxide to get non threaded wasm support in the browser
have you checked unocss? might be more efficient.
However I use it in a much more blended way than the authors probably prefer. I use it with Tailwind Variants and to quickly hack out components. However depending on the project, component, and etc I may also construct BEM-based CSS files to live along side the component.. I use "@apply" in the CSS files, something the author(s?) are on record saying they regret. However I'd counter them by saying if it weren't for "@apply" Tailwind wouldn't be where it is today..
<div class="group card">
<div class="flex items-center justify-between mb-4">
<h3 class="card-title">Team Settings</h3>
</div>
<p class="card-description">
Manage your team permissions, invites, roles, and integrations here. Changes apply instantly across all team workspaces.
</p>
<div class="flex flex-col sm:flex-row gap-4 sm:justify-end">
<button class="btn btn-cancel">Cancel</button>
<button class="btn btn-save">Save Changes</button>
</div>
</div>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
Personally, I’m a Svelte fan, and I think they got it right – you just write <style> in your component and that’s it. I think Vue works in a similar way, too.
Every non-tailwind project I've ever worked on inevitably devolved into a mess where you have 50 billion CSS files scattered all over the place, many containing classes that contradict and override other existing classes, often in completely unclear ways as it's hard to know in which order things will get compiled ultimately. As time passes, you'll see BEM done in various ways, you'll see cursed SCSS functions that generate styles dynamicslly, you'll see a bunch of !importants, and eventually you end up in a state where making a change to a legacy page becomes an exercise in dodging specificity and ordering minefields.
Meanwhile with Tailwind, everything is localized to the element it's affecting, and very importantly the entire team has a "standard library" of properties and patterns they can pull from, so you don't end up with people in different teams naming similar UI patterns differently, and you straight up never have to think of specificity ever again (which in my view is a boon, despite what CSS purists might say). Yes, the HTML is more verbose, but this is just such a non-issue after the first 5 minutes of discomfort, plus all the other benefits.
Hot take, but the Cascading part of CSS has proven itself to be a massive drawback, and not a benefit. Tailwind obviates that completely.
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.
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
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 /\* 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;
}
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.
Fwiw, I struggled with anxiety and depression for nearly 20 years. Commitment to therapy and my modalities brought me out of that. My _therapist_ guided me, including finding purpose and building meaningful relationships.