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.
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.
Furthermore, styled buttons are such a common occurrence that TailwindCSS encourages users to extract common CSS patterns into component classes[0].
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!
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...
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.
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'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).
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.
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 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/
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.
[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...
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 still written in JS but there is nothing node-specific there. it easily runs in a browser, or any js environment.
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.
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.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.
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.
Good work!