84 comments

[ 1.9 ms ] story [ 51.2 ms ] thread
Tailwind before tailwind.

It's strange, I never saw the point of it, however I saw the value in tailwind almost straight away.

I think that might be the difference in examples. The tachyon examples always look uninspiring.

For me it is the opposite, tailwind makes me immediately feel ill, Tachyon looks like fun.
Tachyons __is__ fun! I have found it to be better for rapid prototyping than Tailwind. The class names are more intuitive as they seem to line up somewhat with Emmet text-expansion triggers, and it's much faster to throw the single <link> in the header than to set up Tailwind every time. Tachyons has always felt so fast.
I second this. Tailwind is an awful little tech that will fade away in a few years (already doing so) and will leave behind nothing but a horrendous, unreadable overhead of technical debt.

There was a push to build tutorials for whatever using Tailwinds (Build a blog with Hotwire, or something), those were there fastest tab closes ever performed on my lifetime. Those tutorials are useless, they have so much added nonsense that will not stand the test of time that might as well not exist at all.

Tailwind was great because it made it obvious how the classes connected to the configuration. Tachyons was very much was marketed as a "bootstrap" sort of thing where it wanted you to use their configuration and that's it.
Tachyons and Basscss were Tailwind before Tailwind. Both are proof that a good idea (debatable) alone is not a enough to earn the collective mindshare of front-end devs; you need shiny examples, a cool splash page, and a looooot of marketing.

For what it's worth, I enjoyed Basscss more than Tailwind, although I mostly just stick to CSS Modules + CSS variables these days.

Yeah, it's funny how dev-minds who typically insist on being objective, etc. get sucked into the trendy hype of something like Tailwind. Don't get me wrong, the Tailwinds of the world have a place. It's unfortunate those who pick it up insist on hammering screws with it.
Yep, not bashing Tailwind, but this is how it usually goes from my experience:

> Team is doing OK with the current boring tech stack

> Senior Dev who is chronically on Twitter: "Hey guys, we should adopt this new library, React-TailsbyQL-babelfu by so-and-so Node though-leader because it makes this one very specific pattern easier! Look at how slick the docs look!"

> Team: "But we already swapped that part of our stack a year ago, and that one pattern would only help in a few specific parts of the codebase."

> Senior Dev makes argument to Product Manager

> Product Manager agrees because it'll look good to the rest of the company

> We complete migration to new shiny new tool; 30 transient dependencies and 4 config files added

> Senior Dev and Product Manager boast to other teams about the successful migration and cherry-pick LOC reduction in certain modules, omitting the added configs and complexity elsewhere; other Product Managers are impressed

> Meanwhile the app now performs worse; weird bugs creep up because details are now obfuscated by the new library; new devs now have to learn the codebase + the way this library dictates things must be done

> Devs start paying for courses by the author of said library using continuing education funds because the docs for the library are insufficient

> Author of library deprecates library; moves on to new library that does almost the exact same thing, and starts evangelizing it on Twitter

> Senior Dev comes back "Hey guys, check out this new library..."

You can tell I'm not bitter.

That would be all well and good but the problem is the product they're generating continues to be second-rate at best. Their user are still dealing with too much friction. Etc.

I'm going to come up with a trendy library or framework and name it Fool.

"A fool with Fool is still a fool." lol

I saw the value in Tailwind, then switched over to Tachyons when I realized it was just like Tailwind but without the JavaScript build step (and you can actually use the full bundle as-is because it's 14kb gzipped)

Tailwind probably looks better, but I'm primarily using Tachyons for common spacing stuff and if I need better looking colors, I'll copy what Tailwind has or define my own. I can still write CSS, I'm not trying to stuff everything into classes generated by some configuration tool or whatever.

The thing I don't like about tachyons, or many CSS "frameworks", is that it severely uglies-up your markup with long class attributes.

Give me a web dev framework with view encapsulation / scoped styles and you can almost get rid of class attributes in your markup all together, especially if you build a component library that your higher level components can consume.

The ugliness is a feature. Declare HTML components that encapsulate the classes. Then each component is stand-alone WYSIWYG and composes easily with others.
Except you still see the encapsulated classes when you inspect it in production, and often that is where the bugs appear and need to be figured out.

The ridiculous class strings get particularly hilarious when anything beyond basic CSS is used. Want CSS variables? Now it's even less readable!

Reading them is easy, that's one of the main benefits of atomic CSS. WYSIWYG.
It's all about the config system. you can really make tailwind your own.
I like it and I don’t. I mean

  <b>bold</b>
is a little simpler than

  <div class=“b”>bold</b>
Certainly designers have struggled to think systematically enough to define a set of classes that are basically semantic even though, when they do it puts their skills on wheels because they can design it and other people can knock out pages consistent with the design.

Things like this make me think CSS needs namespaces though, just the other day I found out there was more than one library in an application I am working on that declares properties of “.dropdown” which could be a problem.

More generally you really ought to be able to pull some HTML out of page A and transcode it into page B and that means copying the styles and a lack of namespaces for id(s) and class(es) gets in the way of that. In principle you could have syntactic macros for HTML or frameworks that work on the DOM more imaginatively than React does but you run headlong into the “macro hygiene” problem.

There's lots of cases in web design where you want to change the font weight, color, size, font family, capitalisation etc. of some text to create contrast with other text where the semantics of <b> don't make much sense and there aren't other tags that would help.

See this example where semantic HTML tags aren't going to help much with the styling or getting the information hierarchy right: https://twitter.com/steveschoger/status/997125312411570176/p...

> I like it and I don’t. I mean <b>bold</b> is a little simpler than <div class=“b”>bold</b>

Of course in this example, semantic HTML makes sense. How do you compose styles? Do you have a semantic element for every CSS property and every combination of every CSS property? Utility frameworks are used for much more than making text bold. The idea is to write as little CSS as possible, which reduces CSS bloat, collisions, specificity hell etc.

> More generally you really ought to be able to pull some HTML out of page A and transcode it into page B and that means copying the styles and a lack of namespaces for id(s) and class(es) gets in the way of that.

That is quite literally what tools such as tachyons/tailwind solve.

> or frameworks that work on the DOM more imaginatively than React does

I don’t really know what this means. But if you’re using React, you can leverage CSS Modules or one of the many CSS-in-JS frameworks. Both of these approaches solve your issue with namespacing.

Most back end systems do string templating, most of the exceptions compile templates ahead of time like Cold Fusion and .NET.

An alternate approach is to work entirely at the DOM level, a bit of a manifesto for that

https://ontology2.com/the-book/html5-the-official-document-l...

To take the common case, your "master template" could be an HTML page with a few "slots" in, say <div> elements with a certain id or class. The main content for a page is another HTML page, both of these are parsed to the DOM, the <body> of the donor page is extracted, grafted into the slot of the host page.

More generally we can write functions that act on the DOM just as someone can write code that works on the AST of a programming language.

One capability that ought to be possible is transclusion, in fact the "Real Semantics" system that was being designed at that time was a system for annotating documents and extracting knowledge from them and the first step of that is that a document is "fixated" an embedded in an another document, pinned down the way an entomologist pins down a butterfly.

This is on the edge of possibility: cut-and-pasting an arbitrary fragment of HTML out of somebody else's document and also rewriting id and class names and relevant CSS styles such that the the donor HTML looks the same way it did in the host HTML. (Or better yet, the CSS is manipulated so as to maintain the intent of the donor document in a way consistent with the host document)

Anyhow, one major barrier to this is that DOM parsing is pretty slow, a simple system based on DOM parsing can be two orders of magnitude slower than string templates. (No wonder ASP.NET compiles templates ahead of time)

Another one is ubiquitous Javascript; from my viewpoint a static document that can be "pinned down" is dramatically more valuable than a changable document in that I can easily repurpose the static document. (In literary criticism is is notable that a document is "dead" and can't fight back against a hostile or inventive reader, say Derrida or Badiou.) You certainly can snapshot the DOM of a dynamic document the way that Google can index React-based sites, but it sure is a hassle.

I love their components page and modular system. With article components any one can create a clean, responsible blog or landing pages. As a non profesional it's a perfects system for me.
You could also use Tailwind.
Many of the patterns Tailwind classes encourage are invalid per the CSS spec and can't be selected via javascript
I have no idea what "invalid per the CSS spec" is supposed to mean but if you need a selector add one.
Invalid per the CSS spec is pretty self explanatory. There is a common CSS spec used by the JS engine and web browser. When the class used does not comply to that defined standard, the class is invalid.

You can see this when trying to trying to use querySelector with responsive:property-[arbitrary] classes (I think, or it might be a different pattern of which I'd have to go back and check) and other cases where the JS engine will throw an error for trying to use a class Tailwind encourages you to write.

Okay, but I struggle to see how this has a meaningful impact given that you can simply just add a different class to use when selecting with JS.
Perhaps because that would be wasteful if what you want to select already has a class that identifies all the elements you want and only the elements you want? Adding an extra class for your JS might mean adding it in several places around your work too, not just in a single template. Why define .things-to-select-when-I-look-for-red-things when .red-things already exists and could do the job?

There is also the matter of separation of concerns, not wanting to add classes specifically for particular bits of code where possible to avoid it, but given the sea of classes generated by frameworks these days I'm not sure that is an ideal which is much followed ATM.

It’s a fair thought, and it’s interesting you mention that. I do think of it as separating concerns. I think of CSS for styles and JS for dynamism that can’t be achieved out of the box. Classes are only attributes, after all. Hypothetically, if you remove the JS-dependent class it doesn’t break any styles (unless of course, you’re using JS to apply styles, which is another conversation). That being said, if someone still felt strongly I’d concede this is subjective and only relevant to developer experience.

I think you touched on an objective subject, however, if you were alluding to performance. Classes are generally free and cheap. I’d be very interested in evidence to the contrary if anyone could share.

My last, somewhat random, thought is that it does indeed seem that who likes TW and who doesn’t does seem to depend a lot on the stack they’re thinking of when they mull over its (de)merits.

> if you were alluding to performance

It isn't as much about performance (the small amount of extra network transfer is likely to be brought close to zero if compression is used, the extra CPU load might be measurable on low-spec devices but on top of all the junk already in sites using heavy frameworks this is not going to make/break anything) as maintainability. You have something extra to make sure is set everywhere it needs to be.

(comment deleted)
No. As of 2022[1], the CSS spec defines a class-name (in a .css rule's selector) as "." + ident, and the lexical scanner rules for ident specifially allow any character outside of 0x00-0x7F in a class name after an initial [_A-Za-z] character.

[1] https://www.w3.org/TR/selectors-3/#w3cselgrammar

From my reading you can use any valid non-ascii character for the initial one too:

  ident     [-]?{nmstart}{nmchar}*
  nmstart   [_a-z]|{nonascii}|{escape}
  nonascii  [^\0-\177]
  unicode   \\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?
  escape    {unicode}|\\[^\n\r\f0-9a-f]
  nmchar    [_a-z0-9-]|{nonascii}|{escape}
(nmstart being the key definition for this point)
So why does this tailwind class fail?

document.querySelector('.[&_a]:underline')

> Invalid per the CSS spec is pretty self explanatory.

It is, but in the same way “I received an error” is not an incorrect error report it just lacks specificity.

I think what CSSer was asking (though the question itself was not worded as precisely as it could be) is: can you give examples of the invalid identifiers that it encourages?

Never tried it, thank you for pointing out, let me take a look
I’ve been using it for a couple years now, absolutely love it. I personally prefer it over Tailwind (and don’t feel like learning _another_ css framework) and, ngl, the “components” section of the page is a big reason for it.

When I started using it, if I needed a card or a list I could go to the components section and pick one, copy-paste it and then change it to my liking. When I tried the same in tailwind I was faced with a paywall and automatically lost all interest.

Quick fix:

  - .sans-serif {
  -   font-family: -apple-system, BlinkMacSystemFont,
  -                'avenir next', avenir,
  -                helvetica, 'helvetica neue',
  -                ubuntu,
  -                roboto, noto,
  -                'segoe ui', arial,
  -                sans-serif;
  - }
  + .sans-serif { font-family: sans-serif; }
I already set my preferred sans serif in my user agent; if you don’t care enough about the design to provide a real font stack, I don’t need your site trying to override my preferred default with Ubuntu, Roboto, or ugh Arial. If you just want something sans serif, please just fall back to the user agent so users can define the value.
I believe the issue with this is that the font that the browser picks with “sans serif” can vary wildly depending on the user’s system, with totally different metrics, weights, etc, meaning that the page might look anywhere between passable and broken. The most egregious case of this is probably on some of the more “libre” type Linux distributions that default to that one oddly wide sans serif that I can’t remember the name of.

The idea of user configurability is nice but most users have no idea how to do that or that it’s even possible, and browsers bury these settings increasingly more deeply which doesn’t help matters either.

The other side of that coin is that Nimbus (if it's installed) will happily insert itself as an alternative to Arial and/or Helvetica (cannot remember), even though it's a trash typeface with a broken baseline.

I think just going with sans-serif is the better choice.

It’d be nice if something like Inter[0], which is specifically designed for onscreen/UI usage, were bundled with each OS and could be assumed to be present, making it unnecessary to include Arial or Helvetica in one’s stack.

[0]: https://rsms.me/inter/

This makes more sense why Tailwind chose Inter as their default font (for at least a long time). I've noticed tons of sites now use Inter as a result of using Tailwind and derivatives. I think Laravel did some level of popularization of this too
Then put the desired typeface at the beginning of the stack, and the generic (sans-serif) at the end.

I've never had a designer ask for 17 fallback options before selecting a generic (like this font stack).

> The idea of user configurability is nice but most users have no idea how to do that or that it’s even possible

No need to baby users. In the context of Hacker News, a lot of the websites built here are demo sites/documentation where the audience is definitely technical enough to not need this.

In the case of libre, Free Sans is a clone of Helvetica (as is Nimbus) & they are usable if a user decides to set them as their preferred font (or a fallback in fontconfig).

System defaults can be ugly sometimes. Sometimes user might set their default font to something like Comic Sans or Papyrus accidentally or not and have no clue how to fix it. Users are really, really dumb. I wouldn't like my designed website to look like trash because the user wants to bring their ugly font, I want it to be consistently classic book sans-serif. Any time of the day I'd choose Segoe UI over Arial or god forbid Verdana. Hence that line and https://systemfontstack.com/ exist. The latter one is, by the way, always in my toolkit.

My website, my design. my fonts. Period.

Some people, believe it or not, actually like Comic Sans.

Their device, their preferences, their fonts. Period.

It’s not uncommon for people with dyslexia to use Comic Sans because some of them find it easier to read.

However pretty much every website specifies which font to use. If you want your own font, you aren’t going to get it by complaining about one particular CSS framework. There’s a way of overriding fonts in every browser; find that and you’ll get what you want.

Opinionated design is design.
I think you’re misinterpreting what’s going on here. That looks like a backwards compatibility replacement for the standard font-family: system-ui; CSS rule. They aren’t trying to force you to view Roboto. They are trying to tell the web browser to use the standard font for the platform.

-apple-system will give San Francisco on Apple systems. BlinkMacSystemFont will do the same in Chrome. Roboto is the Android default font. And so on. Since most people don’t typically have the default system font for other platforms installed, a rule like this will typically give the same font that is used everywhere else in the platform.

Web browsers don’t typically use the standard font for the platform for backwards compatibility reasons, which is why system-ui was created. Older browsers don’t support system-ui, so tools like PostCSS will often replace it with a stack like this in an attempt to get the same behaviour in older browsers.

This basically boils down to somebody saying “let’s use the standard font for the platform the user is using”.

> This basically boils down to somebody saying “let’s use the standard font for the platform the user is using”.

Exactly. This is what system-ui should be but some browsers instead default to something else, perhaps in a misguided effort to make their UA look consistent between platforms, to many use a font-list like the above to try enforce what system-ui should be. Unfortunately it falls apart if the user has fonts for other systems installed (perhaps for compatibility with others they collaborate with on documents, or to be able to view HTML more exactly as those users will see it) and those users get someone else's system font instead because it is ahead of thiers in the list.

It’s a weird game of whack-a-mole where it solves a problem for some while creating new problems for others. That’s why it’s best to just save the bits & ask the UA.
Ah, the age-old battle between some many designers who want their output to be “just so” and some people who have a strong preference for what they read to be “just thus”!

Perhaps there is room for new preferred-sans-serif-font, preferred-serif-font and preferred-mono-font aliases that we can shove at the top of font stacks like this and are set by the user if they wish (defaulting to nothing if they don't). That way people with a strong preference get listened to if they set this, so you can have other fonts installed for compatibility with documents written by others you collaborate with without them overriding your preference which is otherwise further down the list. Though that might be impractical: you need to convince browsers to implement the setting and designers to add it to the top of their stacks. The browser makers are not always fast to implement things until there is demand and there might not be demand because no one tries to use it while browsers don't support it. That and many designers may think “let the user pick the typeface, eeewwwwww!” & similarly browsers those packaging browsers for their OS might implement it wrong (putting something in those settings by default instead of them being blank unless specified). It could be described as an accessibility issue to get more traction, allowing users with certain vision issues to specify typefaces (and maybe other properties like minimum sizes & weights) that improve readability for those with their condition.

If a designer wants something “just so”, they would have included a @font-face. This sort of font stack is usually mislabeled something along the lines of “system font” (hence it just being labeled sans-serif unlike the specific font face fallbacks). Instead we see a cascade of ‘find something that looks a bit Grotesk per platform’ which may not be the type of sans serif the user wants. And that’s the problem: if you wanted a system font, just ask the system.

I actually don’t mind something designed with purpose & has a reasonable font stack to match it, but this stack isn’t that.

Unfortunately you can't just ask the system, because browsers don't consistently use the system font, or otherwise make good choices, for system-ui.

Using a system font stack isn't about “a typeface that is a bit Grotesk” and more about trying to integrate with the look of the users OS. Including a @font-face will not achieve that version of “just so” unless you want to mimic one OS for everyone.

I won't be using this.

The grid system is still using floats instead of flex/grid.

thanks for letting us know. we were all waiting to hear if you'd be using it or not.
The project is outdated. The grid system is not using any CSS3 feature. So, yeah, it's an old framework. If you want better features, you may go Tailwind CSS.
Last release in 2018, last commit in 2021. Why was this posted?
Tachyons is feature complete for most people's/project's needs. It doesn't need to be updated. Every day we all use code that was last updated 10+ years ago without realising it.

Having said that we switched to Tailwind for a very specific reason: customisability. see: https://github.com/dwyl/learn-tailwind#what-about-tachyons

Still Tachyons is a perfectly valid and lightweight utility class based CSS library.

(comment deleted)
I want a CSS framework. Tailwind is practically a JS framework at this point. It’s own custom build system & everything.

Personally? Not a fan. Wish it would have stuck to utility classes.

Well, I wrote a functional CSS framework that is platform agnostic. It was built on sass. Post: https://www.minid.net/2019/4/7/the-css-utilitarian-methodolo..., github https://github.com/meerita/utilcss I am working a different project now, and now I evolved it to simply pure css files that i compile later with postcss and purge everything.

The latest and newest i did https://github.com/meerita/fcss

just drop into your react app, in this order:

root.css normalizer.css generics.css (all css classes) sm.css (mobile classes) md.css (mid desktop/iPad) lg.css (standard desktop) xl.css (large desktop) xxl for large large desktops

The usage is easy, lets build a grid:

<div className='display--grid gap--8'>...</div>

Those are from the generics.css, but if you need 2 cols in mobile and 4 in desktop you can do it

<div className='display--grid gap--8 sm-template-columns--2 md-template-columns--4'>...</div>

The structure of every class is made using the css language, contrary to tailwind has its own syntax. it takes huge amount of time and mental effort to get it. With FCSS you learn the pattern and you can advance it or extend it.

I would like to work on one of your projects. Great job! I will get across via Github.
Thank you, all PR are welcome.
That is a very nicely constructed project!
In what way is it a JS framework? There’s a build step because there’s so many possible utility class combinations that it would be size-prohibitive to ship them all.
Well, so is this. They both use PostCSS. But the JS is only in the build system. Tailwind does not deploy JS.
Right, didn’t mean to imply it did.
CSS is so good these days you could just write it directly. I suspect that CSS bloat is not a real problem for most people. The value of Tailwind seems to be the ecosystem of styled components rather than Tailwind syntax itself.
Yes, I don't use Sass or LESS anymore.
It's a perfect framework for building a static website, love Tachyons
I don't know if this is maintained anymore. Last commits are from 3 years ago
Yeah, I remember liking tachyons but whats it doing on the front page?
Oh, damn, you are right, I had no idea. I just saw their front page, really liked its design and felt like you guys might like it as well. It's very much like Tailwind, but, unlike the latter one, it doesn't hide example components behind the paywall, which puts TACHYONS far ahead.
I'm not sure what "maintained" means for a CSS toolkit. Unless the CSS directives it uses are deprecated at some point, what maintenance is needed?
Dark mode would be a nice addition. Some utilities could be cleaned up or expanded etc.
always liked Tachyons, and honestly bootstrap. If HTMX catches on I could see both of these getting popular again on over Tailwind, since you won't need a build step
The version 5 branch is fully ongoing. I talked to Adam and it’s already in beta. You can check out the branch on GitHub.

A few minor things still to iron out but it’s the way to go. I also maintain a version with darkmode support based on v1 :)

Feature wise it has grid, css variables and a full color palette.