Tailwind CSS: adiciona complexidade; não faz nada
Se você trabalha com front-end, provavelmente já ouviu falar muito sobre Tailwind CSS, uma biblioteca CSS muito parecida com o Bootstrap. Mas, diferentemente de Bootstrap, Tailwind tem uma abordagem diferente: baseia-se inteiramente classes de utilitários (utility classes).
Para os que ainda não sabem o que é uma classe de utilitário (utility class), aqui vai uma explicaçãozinha rápida.
Digamos que você tenha muitos componentes, e muitos deles precisam ter display: flex. Em vez de escrever isso várias vezes em seu CSS, você cria uma classe chamada “flex”:
.flex { display: flex;}Então, para cada componente que precisa ser flex, você adiciona essa classe flex.
Perceba que isso não é uma coisa ruim, em si. É até bem comum usar classes de utilitários, seja usando CSS puro ou, mesmo, com pré-processadores tipo Sass.
O que o Tailwind faz é levar esse conceito ao extremo, com a ideia de que você quase nunca precisa escrever CSS; apenas escrever classes diferentes com base nos estilos que precisa aplicar.
Estilo inline com passos extras

É isso. Escrever <div class="flex">foo</div> tem o mesmo exato efeito de escrever <div style="display: flex">foo</div> — só é ligeiramente diferente porque os estilos inline têm Especificidade maior que classes, mas isso não é realmente relevante neste contexto.
Então, com isso em mente, com exceção da priorização de CSS, qualquer argumento que possa surgir contra o uso de estilos inline na sua base de código também é um argumento contra o uso do Tailwind — como esse, esse e esse, só para citar alguns.
Pode parecer um pouco batido repetir críticas de outros sobre estilos inline para explicar o que há de errado com o Tailwind CSS, mas, na verdade, é um mapeamento 1-para-1: é apenas estilo inline com passos extras.
Problemas que Tailwind compartilha com estilos inline
E, como é disso que se trata, evidentemente, Tailwind vai sofrer dos mesmos problemas de quando se usa estilos inline.
Repetição (not DRY)
Quando é preciso alterar estilos de um projeto de uma forma mais abrangente, se classes de utilitários desse tipo estão sendo usadas, é preciso passar por cada uso delas e determinar visualmente o que precisa ser atualizado.
Por exemplo, digamos que a cor primária usada seja azul. Haverá muitas coisas azuis no site, marcadas como: “text-blue-500” ou “bg-blue-300” para determinar diferentes tons de azul. E tudo bem, até que o cliente decida alterar a marca e todos os botões (mas apenas os botões) no site precisem ser vermelhos.
Agora, você tem que passar por cada componente e alterar manualmente “text-blue-500” para “text-red-500”. E com 1000 edições vêm 1000 oportunidades para introduzir bugs.
Com CSS normal, o que provavelmente teria sido feito é criar uma classe chamada “button” e, nessa troca, simplesmente alterar 1 linha de código nessa classe: background-color: red. Qualquer elemento que usa essa definição de classe agora ficará vermelho.
O que leva ao próximo problema que Tailwind compartilha com estilos inline.
HTML deve se preocupar apenas com a estrutura da página, não com seu estilo
Fala-se em seperation of concerns no desenvolvimento Web, que é a premissa de que as 3 principais tecnologias do front-end devem estar divididas em “camadas”, cada uma sendo o mais independente da outra.

CSS Modules (especialmente, arquivos .vue) fizeram muito para dissipar a noção de que é preciso separar o conteúdo (ou estrutura), a apresentação e o comportamento do mesmo bloco de construção básico do site: cada parte do seu código deve ser “fracamente acoplada e altamente coesa” (loosely coupled and highly cohesive).
Em outras palavras, HTML não deve conter informações sobre quais devem ser os estilos; deve conter apenas informações sobre a estrutura/conteúdo da página.
De fato, a principal razão para a invenção de CSS, o objetivo de todo o empreendimento do CSS foi… Separar o conteúdo da apresentação.
E o método para fazer isso é por meio do atributo class.
O ponto principal de class é informar o que é um elemento, ou seja, descrever o conteúdo de um elemento — não da mesma maneira que semântica HTML, mas você entendeu. Depois de definir o conteúdo, decide-se como é sua aparência.
Isso não significa apenas que é possível alterar a aparência de um elemento sem se preocupar com a estrutura subjacente da página, mas, também, significa que se pode usar essas classes para se descrever o que é um elemento.
Lembre-se de que, quando um código é escrito, destina-se a 2 públicos: o primeiro é o próprio computador, que não se importa com a aparência do código, desde que seja executado, e, o outro, são os colegas desenvolvedores. Quanto mais fácil for para eles identificarem rapidamente quais são as partes do código e como se relacionam, mais rapidamente poderão corrigir bugs, adicionar recursos e aprimoramentos etc.
O que leva ao próximo problema de Tailwind.
É difícil de ler
Se você olhar para algum HTML que usa Tailwind, pode dizer a si mesmo que o HTML parece “ocupado” ou mesmo “feio”. Isso é verdade, mas não somente isso.
Diga o que quiser sobre estilos inline, mas eles, pelo menos, fornecem contexto suficiente para que você saiba o que está acontecendo. O código do Tailwind está cheio de abreviações semanticamente obscuras; a maioria dos quais são apenas redefinições de propriedades CSS já conhecidas.
Pior ainda, quando não são redefinições, podem se tornar totalmente enigmáticas. O Tailwind prefere usar nomes de classe prefixados em vez de media queries.
Por exemplo:
<div class="w-16 h-16 rounded text-white bg-black py-1 px-2 m-1 text-sm md:w-32 md:h-32 md:rounded-md md:text-base lg:w-48 lg:h-48 lg:rounded-lg lg:text-lg"> Lorem ipsum...</div>É o equivalente a:
.thing { width: 16px; height: 16px; color: white; background-color: black; padding: 0.25rem 0.5rem; margin: 0.25rem; border-radius: 0.25rem; font-size: 0.875rem; line-height: 1.25rem;}
@media screen and (min-width: 768px) { .thing { width: 32px; height: 32px; border-radius: 0.375rem; font-size: 1rem; line-height: 1.5rem; }}
@media screen and (min-width: 1024px) { .thing { width: 48px; height: 48px; border-radius: 0.5rem; font-size: 1.125rem; line-height: 1.75rem; }}<div class="thing">Yikes.</div>Evidentemente, o primeiro exemplo tem muito menos código e é mais rápido para escrever, mas veja como o segundo exemplo está definindo explicitamente a altura e a largura em breakpoints específicos.
Outra razão pela qual o último é mais fácil de ler do que o anterior: as classes do Tailwind são organizadas horizontalmente, enquanto o CSS é escrito verticalmente.
Quanto mais amplo for o texto, mais difícil será para os olhos do leitor pular para a próxima linha e mais difícil será encontrar a palavra específica que você está procurando em uma parede de texto horizontal.
Perda de muitos dos recursos nativos de CSS
Tailwind não permite que você use o poder de muitos dos recursos nativos/básicos de CSS.
Não é possível encadear seletores, como:
.foo:focus,.foo:active,.foo:hover {}Atualização: Atualmente, é possível lidar com estados no Tailwind.
Não é possível usar combinação de seletores CSS, como:
.foo p {}.foo > p {}.foo + p {}.foo ~ p {}Tailwind resolve um problema que não existe
Uma das coisas mais malucas é que há uma limitação óbvia para o paradigma de classe de utilitários do Tailwind. O que acontece se você quiser agrupar estilos relacionados?
Por exemplo, raramente display: flex é usado sem alguma propriedade de distribuição de conteúdos, como justify-content. CSS permite agrupar esses estilos em… Classes.
Também existe uma ferramenta para agrupar classes relacionadas ao Tailwind, chamada @apply. É uma sintaxe especial não-padrão que vai em seu arquivo CSS (uma diretiva) e permite combinar uma coleção de classes do tailwind sob um nome de classe específico.
Ou seja: destrói completamente o propósito por trás do paradigma da classe de utilidade…