Show HN: Tailwind.run – An Online Playground for Tailwind CSS
tailwind.run
tailwind.run
It's an interesting idea to entertain as a thought, and some utility classes certainly hold value in general, but I don't see how you would ever reasonably want to use this in a project. It has all the same drawbacks as writing inline styles on elements, not to mention the large size.
Say you have a number of views and decide (or a client decides) you want all of the buttons to have a bit more padding. If anything else happens to completely accidentally also use the same padding class you're always left with manually checking every single instance just for a small change like this.
From a size perspective, compression takes care of the repetition pretty well. Utility classes allow for better reuse, meaning the overall page often is, in fact, lighter.
Nowadays most pages are put together using some kind of components anyway, so changes are that your button is already defined in one place. Otherwise you can extract your own button class.
Also see my reply to bbmario.
My smallish sites don't use build pipelines and post-generators and so on, I'd just like a reasonably-sized CSS file to include.
(I realize that's a niche use of those frameworks)
Oh, and if I may dream, https://caniuse.com/#feat=css-apply-rule throughout all browsers would be great!
https://tabatkins.github.io/specs/css-apply-rule/ https://www.xanthir.com/b4o00
Furthermore, styled buttons are such a common occurrence that TailwindCSS encourages users to extract common CSS patterns into component classes[0].
You'd often use something like a component based JS framework or a server rendered templating language, making it easy to contain all utilities with shared logic in one place.
I suggest trying it out & reading more about it. It's the only way utility CSS frameworks like this seem to click.
In my opinion, Tailwind works best when being used to create template components. In your button case you would just modify your reusable button component or the reusable base button component if you have multiple button components.
You get the best of all worlds.
* You avoid writing a lot of CSS.
* You don't have to worry about thinking of CSS class names or name pollution
* I find it faster & easier to style components with a utility CSS framework in something like Storybook than it is with CSS.
* I recommend adding a plugin to your editor to help with the names of Tailwinds classes. VS Code has a couple that will suggest the right class name based on what you type.
Using utility classes to build a UI is much more like building something with SwiftUI, where no one seems to argue about this silly "separation of concerns" thing we talk about on the web.
I'm still not convinced — using only utility classes has very clear downsides, while using what's reasonably one of the most common approaches in the industry right now avoids those downsides while also providing additional benefits.
Yes, you probably will need to create some custom classes from time to time. Ideally those might be done in a utility fashion though.
It is similar to inline styles in how atomic it is but provides responsive classes which adapt to screen sizes.
It also provides predefined defaults for sizes and colors to prevent codebase rot and design inconsistencies.
Allows combining framework classes into nameable classes (requires using their building tool).
As someone who uses scss and know css myself I will not use it but I can see how it can be useful for devs who don’t want to learn css.
I just can’t get over the inefficiency of learning all their styles and typing them as classes feels gross compared to BEM. But I get it.
CSS however is very much like drawing rather than engineering. Some aspects are just not scalable. You can draw many things in vector by conbining shapes for example but a pen or pencil is still very necessary for many parts of both exploratory creation as well as something polished.
The same goes for HTML and Javascript to an extent. While it’s great to build railroad tracks, you can’t take a train everywhere... any abstraction has to also have the ability to easily break out of it to handle edge cases. Clean and Pure abstractions almost never have the grittiness necessary to reflect a fractally complex problem.
1: https://developers.google.com/speed/docs/insights/OptimizeCS...
There is however one thing that prevents me from using it for everything and I'm curious if anyone knows a solution for this. If I am pulling a chunk of rich text from a CMS/backend/whatever, how can I style this?
I tend to use Django for my backend, so in my template files I just put in a chunk like <div class="container">{{ body }}</div>. If that chunk has h2,p, etc. none of those are getting styled.
In normal css I could just define what those h2, p, etc look like under a specific class. But besides using some js magic to inject those classes, I'm at a loss.
The best trade-off I've found is to give a unique CSS classname for the container which has user-generated content, and then style it using nested selectors. Here you can use Tailwind's @apply so you're still able to rely on Tailwind's design system.
I didn't consider using the @apply, good idea. I'll have to give that a go, thanks!
I've used it and it is easy to use. It will generate a base.html file for you which pulls the built css from the static directory and you can extend that in your templates.
The generated content is wrapped in a div with the class "markdown" (defined in the repo above). So it looks like: <div class="markdown">{{ .Content }}</div>
I wrapped up the stylesheet around 2AM this morning, but I plan on expanding the README and un-nesting the class (it was nested for postcss-nesting).
I am just starting a personal site and it is still very much under construction, but I do have a Markdown example page publicly available that I have been using to test the styles. Here is the link in case anyone wants to take a look at the end result: https://iandinwoodie.github.io/blog/markdown-syntax-guide/
Here are the markdown styles for my own personal website for example:
https://gist.github.com/adamwathan/d257699f16ec7cc1b002b5fb7...
I tweeted a video of the app in action here: https://twitter.com/utkarshkukreti/status/115832371651577856...
I made this TailwindCSS Playground over the last two weeks. I really like the core idea of Tailwind and the productivity gains it gives and would like to build more stuff with it in the future!
Features:
* Compile custom @tailwindcss config and CSS in the browser
* Live preview in 5 screen sizes
* Class name autocompletion with CSS definition preview
* Save code online or export .zip
* Vim/Emacs/Sublime key bindings + Emmet
thanks!
It's a design system with constraints, which automatically gives me fewer and better options.
Using something like Bootstrap is probably easier and quicker if you're unfamiliar with writing CSS though.
All in all, quite far from styling with inline `style` (but it takes a bit of learning on the thought process behind it).
Who does this? It sounds like an exercise in pain and futility.
It's less theming in the sense of css zen garden and more encoding variations of style in css instead of relying on more class names.
The TLDR is that you don't lose anything by starting out this way, because at any point you can extract (think @apply) higher level utilities or semantic classes, but gain that you can get a good looking design in place quickly by having useful constraints, not needing to switch context all the time, and not being forced to make up names for everything. While few sites need to conform to the "Zen Garden principle", Tailwind won't stop them from doing so, if you put in the work that it makes optional.
I'd agree this seemingly takes the idea of semantic styling to an extreme (although I haven't gone too deep into the framework).
It is very liberating to use Tailwind instead of creating unique CSS classes for every div in a page. The code is much more maintainable - in a single stroke Tailwind gets rid of selector specificity issues, design inconsistency, and naming woes.
From a programming perspective, the conventional style of "semantic" CSS classes creates deep and fragile coupling between markup and CSS. It goes against everything good code is supposed to be - when you change the structure of the HTML you're forced to change the CSS, and if you truly use the power of CSS selectors, then modifying CSS becomes a difficult enterprise: one change can create multiple unrelated changes at a distance.
Tailwind solves all this, with just two downsides: until you spend a few hours mucking with it, the markup look will look unwieldy, and you have to be ready to really think about semantic CSS and "separation of concerns" dogma we've taken for granted for so long.
Hence "separation of concerns" - to the extent that it's a good idea in the first place - doesn't work for html+css, and similar concerns mean it doesn't work very well for html+scripts.
Put another way, leaky abstractions are worse than no abstractions. Better to keep things transparent and merely expose helpers, instead of pretending you can hide complexity when you cannot really hide it.
So, if I'm making a theme, and I want a different color for the text, I have to replace "text-gray-900" with my hex code for purple?
Also, what if my theme is about making the design more compact, or increasing density? How do I customize thousands of elements with different combinations of class="ml-6 pt-1"?
Oh, and don't get me started on "bg-white rounded-lg". God forbid your theme wants squared boxes on black background.
If you want to change density of the design, you can change the spacings centrally in the configuration itself. But if you need a non-proportional change, then it isn't any different than BEM+SASS environment where you'd have to go into every CSS class and make the change. I think it is even better than BEM here because you only need to change classnames in HTML, which is co-located with the style, and it doesn't cause cascading changes due to specificity etc.
To me the opinions you hold seem to come from not having tried it in good faith, which was how I used to judge functional CSS as well. If the current CSS style you use serves you well, that's fine you don't have to explore. But if you've wondered whether there is something wrong with the way we do CSS today, then Tailwind could be an eye-opener.
I have been hosting a CouchDB instance myself on a VPN but considered moving to Firebase while prototyping since it seems easier to use. Considering Firebase since it offers offline-first support. However, only today I was made aware of Blockstack and I have seen it mentioned multiple places.
How do you like working with Blockstack and what made you choose it? Does your app work offline? Does it synchronize automatically between devices?
I also want to take data privacy very seriously, since I am dealing with personal and sensitive data (just like a person's journal is very sensitive to them).
About offline-mode, I am about to implement it by my side as this feature is not part of the Blockstack SDK for now.
I am happy that you are taking data privacy very seriously and I guess Blockstack is a good solution to go.
[1] https://acss.io/
The problem with the latter is you’ve coupled the styles to names embedded in the HTML which means a whole lot of grep and replace when things change.
Taking that further with actual custom values being applied in the class names in the view the way Atomic sounds like it’s taking that idea too far. Those values should be constrained the way it’s done in https://rebassjs.org/ where customization of base values is handled with CSS in JS.
The removal of unused classes can be achieved using tools like PurgeCSS https://www.purgecss.com/
Ultimately I’ve found Tailwind to have the best balance between a composable utility class base approach, with consistent base values, and a mature and good looking parent framework. Otherwise I’d go with one of the smaller utility kits mentioned above for simple projects.
I just checked one of our more recent projects and the resulting CSS is 2.4KB, about half of which is actually an SVG that's used in a background.
faster and more thorough than PurgeCSS (and all others).
specifically for handling TailWind's weird classnames:
https://github.com/leeoniya/dropcss#special--escaped-sequenc...
For those interested in Functional CSS, I've made a Scss/Sass framework too, with different approach. https://github.com/meerita/utilcss here is the article related http://minid.net/2019/04/07/the-css-utilitarian-methodology/
Once you start using funcional CSS, you don't want to go back.
Have we though? I firmly disagree with the premise. I agree that like anything else, css can be abused and misused, and the example cited of Newspapers fits the narrative perfectly. I've worked at a major regional Newspaper in the past and their website was one of the worst sites I've seen. The lead developer at that time (10 years ago) switched to using a functional/semantic css pattern much like tailwind/UCSS, and I found it to be terrible.
Any experienced FE developer should and will know css, whereas they will not know some random css framework dsl, nor should they have to learn it.
Most modern js frameworks are moving towards web-components and scope css to a component, which eliminates much of the past structural ambiguity and reasons for seeing e.g. !important (if implemented properly).
The argument about file size is not strong imo. You are trading css file size for html file size. How many modern web apps are slow due to their css file size? I doubt many. The Newspaper websites were always slow due to churn & many people touching the code, often with lower experience, leading to spaghetti.
If it works for a team then more power to them, but I'm sticking with css :)
Of course functional CSS is not the solution to all, there are situations where, componetize everything will make more sense. But the more you work on, the more useful you see it becomes.
The file size is strong for one reason: most connections to CSS resources are blocked by the queue of priorities, HTML files are downloaded between 12ms-100ms range and that means it's already done, plus, if you use reactive HTML, things speed up even more. Most of the CSS made with BEM or other metodologies don't end up with that much HTML saving too, they're quite verbose. You cannot control the verbosity since it's human made. With UCSS or other funcional frameworks, you can control the verbosity of the outputs, etc.
HTML is faster, by default, as I state in the article. It's the first document and it's the first one processed. If you have a CSS file of 10kb gziped your chances will be huge in comparison with the averaga ~160kb of some projects.
The problem with inline-css (how the modern js framework are handling) is that clashes with the responsive world and cannot be preprocessed so easily as other projects.
Besides the file size factor, give a check to the other points in the arguments: amount of rules slows the loading speed, rendering and painting, etc.
You're sticking to CSS, we also stick too :)
This doesn't stop you to code small and repetitive components like "buttons". There's an article where you can see how it works.
Perhaps one day I will try again but personally I want to minimize extra stuff to learn, especially related to css and styling.
.btn {
@apply cursor-pointer bg-blue border-blue-darker text-white;
}
When developing a web app, this allows you to have a central style configuration and reusability.Aside from the benefits of "functional CSS" that others have mentioned, one thing I really love about it is I don't have to constantly be looking up CSS rules or properties; I just reference the docs of whatever framework I'm using to get what I want. You might say I could do this with Bootstrap as well -- and yeah, I can, but I much prefer the piece-meal approach of atomic CSS. The times I've used Bootstrap, I found myself fighting their styles constantly, or giving up and resulting with a site that looks like every other Bootstrap page.
Say, I have a class:
foo {
color: #FF0000;
}
I want to now apply this class to another class: bar(foo) {
background-color: #000000;
}
I want to be able to inherit from foo, but I can't do that and that's why we have these shenanigans of composable UI frameworks... there are some advantages to doing everything in the HTML but now we have repeating patterns in the HTML, such as in the OP's link <a class="px-4 py-2 border-b-2 hover:border-purple-500 hover:bg-purple-100">Tutorials</a>
<a class="px-4 py-2 border-b-2 hover:border-purple-500 hover:bg-purple-100">Plugins</a>
<a class="px-4 py-2 border-b-2 hover:border-purple-500 hover:bg-purple-100">Features</a>
<a class="px-4 py-2 border-b-2 hover:border-purple-500 hover:bg-purple-100">Blog</a>
which is not extensible and creates duplicate code. You'd still have duplicate class names but I just have to change it once in the css instead of N different places in HTML.For example, all those packages say "npm install packagename" to install, but it didn't work for me. It seems I have to (sometimes?) do a "npm init" first. No install instructions ever tell you that.
I'm sure when you're in the ecosystem, that's a given. For me it's hurdle after hurdle.
That's why I named Go and Ruby as examples. The former because you usually get a standalone executable, the latter because I already have that toolchain installed, and I know how to navigate it.
Unfortunately, everything in webdev is now node.js. Just look at any CSS framework docs (including Tailwinds, which I really like): it's an endless stream of pre-processors and post-processors, multiplied with all kinds of ES versions, Babel, yarn-or-npm, this build tool or that. It just doesn't end.
Rant over. :-)
Nothing to feel bad about, as I said, I'm an outsider, but still annoying to get it wrong in my comment.
And then I read the second part and am simply astonished. I wasn't wrong? I just happened to stumble upon a quirk that changed recently? That's something.
...and update packages with caution. SemVer doesn't always save you and neither will static analysis (because there really isn't any).
it's still written in JS but there is nothing node-specific there. it easily runs in a browser, or any js environment.
Good work!
It's an excellent description in of it's own, but if I were to attempt to put it in other terms, it allows you to compose css components and classes out of other smaller, essentially one liner css classes, while maintaining a consistent styling and spacing across the different utilities, which you define up front using the config but also comes with good defaults out of the box.
It is excellent and now my preferred method for hacking up a new site. It also helps you think about your design system overall so now I find myself paying attention to things up front I would normally wouldn't and it ends up saving me time in the long run. It also pairs really well with the excellent Refactoring UI book.