Как стать автором
Обновить

Комментарии 51

Мне очень нравится TailwindCSS


  • на порядок проще и понятнее, чем css-in-js, без магии препроцессинга
  • работает для всех одинаково (актуально, если в коде живут две разные фронт либы или микс старого бекенда и нового фронта)
  • нет работы напрямую с пикселями, p-3 или p-4, а если нужна середина — иди разбирайся с дизайнерами. А если дизайнеры доказали свою точку зрения, то уже правка конфига или кастом css (обычно не доказывают)
И зачем?

Ну т.е. есть два десятка классов, которые реально что-то делают. Еще есть некие настройки, ок.

Но читаем документацию и, например: tailwindcss.com/docs/overflow
Каждый класс просто добавляет одно css свойство. И именно из таких классов состоит «фреймворк». В итоге вместо style=«font-weight:bold» вы будете писать class=«font-bold»

«Собери кнопку сам» — это не фича. Это CSS. Просто CSS. Я и так собираю кнопку, форму и все-все сам, из CSS свойств.

Вы правы. Это тот же самый CSS, только в другой обёртке.


Речь как раз о том, что такой способ написания того же самого по сути CSS значительно удобнее и нагляднее, отлично комбинируется с идеей о компонентах как переиспользуемых элементах, из которых собирается приложение.


Ваши стили всегда при вас, они не записаны в каком-то другом файле на чёрт знает какой строке.


Если вам нужно перенести какой-то элемент, например, из старого проекта в новый, вы просто копируете разметку и вуаля, он такой же, каким был и там.

Но перенос style в class — это прям так себе.
Само-собой для каких-то абстракций типа .btn это имеет смысл. Но не односложные же классы.
Да, но «bg-gray-400» это не тоже самое что «background-color: rgba(203,213,224,var(--bg-opacity))»
Не то же самое — как раз голый style тут будет удобнее, чем отдельный класс под каждый такой стиль.

Как удобнее пользоваться магическими строками вместо переменных и констант.


Всё-таки на любом проекте есть определенная база стилей, которая говорит, что синий у нас такой, а серый такой. Нельзя каждый раз использовать разный серый. Какой серый, вы можете решить сами.


Это к разговору об абстракциях. Тут как раз таки нужна такая абстракция.

Вы что-то полезли не в ту степь. Константы используют не по этому, а потому что ими удобнее оперировать и понимать что есть что. тем более константы-числа.

Вам никто не мешает сделать style=«color:var(--color);» — вот вам переменная.

Я просто не понимаю смысла перелопачивания css в отдельные классы на-каждое-свойство.
К примеру, у меня есть определенная кнопка, сформированная inline стилями, я решил добавить немного отступов — и теперь мне необходимо во всех N файлах изменить эти стили? С tailwind мы делаем это один раз через tailwind.config.js
Это конечно очень крутая фича. Но есть нюанс: htmlbook.ru/html/attr/class

Дело в том, что основное преимущество использования классов стилей — это создание высокоуровневых абстракций и сокрытие их реализации. Вам не надо знать, какого размера или цвета кнопка, если она по смыслу использования "btn-primary" — такой класс и используете. А уж какой там конкретно стиль "под капотом" — не суть важно.

С одной стороны, TailwindCSS никак не мешает писать вам такие абстракции. Другой вопрос, как много таких btn вы хотите создать.


Удобнее будет написать btn-primary-with-a-little-more-horisontal-paddings или btn-primary px-6?


С другой стороны, кто выигрывает от таких абстракций? Они безусловно удобны, когда нужно сделать однотипный интерфейс с помощью, например, Bootstrap. Но объясните мне, какое конкретно преимущество получает разработчик, когда видит btn-primary вместо конкретных стилей.


Вы скажете, что такая инкапсуляция позволяет быстро ориентироваться в больших объемах разметки. Это верно. Однако, по-моему, она сильно мешает при современном компонентом дроблении кода. Если я уже зашел в компонент <Button/>, я не хочу видеть class="btn-primary", я хочу видеть конкретные стили.

А что делать, если у какого-нибудь компонента нужно поменять оформление с px-4 на px-6? Предположим, что нет никакого фреймворка. Как найти нужный html-шаблон в проекте? Если сделать поиск редакторе по px-4, то, боюсь, там будет 100500 совпадений.

Во-первых, сам автор TailwindCSS говорит в одной из статей, что если вы не готовы отказаться от семантических классов, можете их добавлять просто для удобства поиска. То есть для кнопки добавить класс button. У него нет никаких стилей, он просто для того, чтобы было легче ориентироваться.


Во-вторых, я согласен, что если писать простыню разметки, где всё в одном файле, TailwindCSS очень неудобен. Но проблема не в TailwindCSS, проблема в том, что не надо писать безкомпонентные простыни.


Если не хочется использовать фреймворки, а хочется писать простую статику, я предлагал одно из решений в этой моей статье

  1. Раз уж добавил класс .button, то почему бы и все нужные стили на него не навесить?
  2. Есть у меня компонент — в виде макроса для nunjucks:
    {% macro button() %}
    <button class="d-flex px-4 a-1 b-2 c-3 d-4">
    {{ caller() }}
    </button>
    {% endmacro %}

    Только как найти его в исходниках, глядя в инспектор браузера?


это проблема взятая из вакуума. В реальной жизни в 99.9% случаев будет использована комбинация из минимум 3-4 классов на элементе. Когда у вас тег имеет классы "min-h-75vh f-col-center relative text-center" найти его не составит труда, в большинстве случаев поиск по всему полю класс будет выдавать 2-3 совпадения для проекта с 1000+ компонентами. Я вообще отказался от генерации CSS SourceMaps именно с переходом на Tailwind т.к. стили стало очень легко находить банальным поиском по полю class

Когда название css-класса соответствует названию компонента, то искать тоже можно без sourcemap'ов. Плюс снимается когнитивная нагрузка, когда изучаешь интерфейс через инспектор, так как лучше видно назначение компонента.

можете тогда писать комментарии в компонентах если от утилитарных классов у вас появляется когнитивная нагрузка. При использовании логических классов вы должны точно знать что такой класс больше нигде не используется и БЭМ например подразумевает что вы будете писать такие логические классы не только к рутовому узлу компонента, а вообще к любому узлу компонента. Хорошо если вы единственный разработчик на проекте, а если с ним работают человек 30? Вы серьезно думаете кто то будет придерживаться одной и той же логики нейминга css классов? В реальности у вас будет просто мусорка из кучи подходов и легаси стилей которые перезаписываются через более высокую специфичность или important
Спасибо за статью, я сам сторонник TailwindCSS, планирую активно его использовать.

Думаю логично было добавить, что наряду с классическим применением CSS («Separation of Concerns» или «semantic») появилось новое направление — «CSS Utility Classes» (или «functional CSS», «Atomic CSS», «Utility-first CSS»).

И «functional CSS» — это просто другой подход, и в этой нише TailwindCSS конечно является самым популярным (список).

Надо понимать, что TailwindCSS это не проект-эксперимент, но это рабочий инструмент, который появился в результате многолетнего опыта по верстке.

По сути TailwindCSS — это продукт двух профессионалов своего дела — дизайнера (Steve Schoger) и верстальщика (Adam Wathan). И про них можно отдельно долго рассказывать — сколько сил они потратили для того, чтобы поделиться с людьми своим опытом (множество видео уроков) — как делать красивые и удобные сайты, и как делать верстку быстро и эффективно (этих красиво спроектированных сайтов).

Что же такое «Utility first», например в этой статье рассказано — critter.blog/2018/06/08/in-defense-of-functional-css

Так же вот статья от 2017 года, где разработчик Adam Wathan рассказывает про отличия — CSS Utility Classes and «Separation of Concerns»

Могу добавить что на текущий момент имхо WindiCSS обогнал Tailwind по всем направлениям. Так что я бы выбирал именно его для новых проектов, для меня это сейчас "Tailwind здорового человека" :) Хотя и радует наличие некоторой конкуренции между этими двумя проектами, они бустят друг друга

В чём видите преимущество WindiCSS ?

НЛО прилетело и опубликовало эту надпись здесь

TailwindCSS был бы костылем, если бы хоть как-то ограничивал обычный CSS. Но вы можете также продолжать им пользоваться, даже не заметив, что у вас подключен этот фреймворк.


Поэтому мне сложно представить, как "костыли смогут превратится в грабли".

Так хотелось бы как раз заметить, зачем он подключён-то в итоге :)

Tailwind — это не Bootstrap, но ниша и целевая аудитория у них одинаковая.
А именно ниша верстального фаст-фуда, для людей которые это не умеют/не любят, но им приходится.
Вполне приемлемо для прототипирования или proof of concept, но в долгой перспективе — говнокод и боль.

Хотелось бы поподробнее про последствия в долгой перспективе.


По-моему, проблемы с масштабируемостью возникают, когда код очень связан между собой, когда он раздувается и усложняется и каждое новое изменение может что-то сломать в ранее написанном.


Я ни одной из этих проблем с TailwindCSS не вижу. Код не связан вообще никак, количество классов и сложность не увеличивается.

Если опустить некоторые детали, то TW — это синтаксический сахар для инлайн-стилей.
Формула «инлайн-стили = говнокод» — давно общепринятая аксиома. И Atomic CSS туда же.
Так почему же г-но, присыпанное сахарной пудрой, должно быть чем-то принципиально лучше?

Знаете, сейчас популярна поговорка «миллениалы изобрели X». Это тот самый случай: кто-то переизобрел то, что давно было пережевано и выплюнуто. Обернул в красивый фантик, придумал прикольное название, написал инструменты для сборки и назвал это фреймворком — но основная-то суть осталась прежней.

Важно: я не считаю утилитарные классы абсолютным злом. Их вполне можно использовать понемногу, как приправу для частных случаев и локальных исключений. Или для набросков. И я нормально отнесся бы к TW, если бы его преподносили именно как библиотеку вспомогательных утилит. Но «фреймворк» и «новая парадигма», на которых предлагают строить всю вёрстку… увольте.

В статье у вас слишком стерильные примеры, оторванные от реальной жизни.

<button class="px-4 py-2 font-bold text-white bg-blue-500 rounded">Отправить</button>

Тут несколько проблем.

1. Всего 6 классов-свойств, а в глазах уже начинает рябить.
А ведь это очень упрощенная демо-кнопка. В реальной жизни понадобятся не 6, а ~15-20 свойств. А потом ещё 4 состояния — hover, active, focus, disabled. Вам понравятся 30-40 классов, из которых половина с префиксами состояний?

2. Магические числа. Я же знаю эту гениальную идею — «а давайте все отступы сведём к пяти размерам!». Практика говорит, что долго такая система не живет, обязательно находятся исключения, новые размеры, шкала сбивается, в ход идут костыли и так далее. Повторюсь, как вспомогательные утилиты это вполне годится. Но для фундамента компонентов предпочту что-то более осмысленное типа $button-small__paddings. Это ещё безобидный пример, в доке есть повеселее.

3. Смешаны стили самого блока и его позиционирование. В БЭМ-е их разделяют и поверьте, это не чья-то блажь, это действительно упрощает жизнь.

4. Как я должен следить за консистентностью всех кнопок?

Понятно, что писать всё это счастье в html можно только для прототипирования. Окей, выковыриваем классы из html и используем как примеси css-препроцессора.

<button class="btn">Отправить</button>
<button class="btn px-6 py-4 bg-red-500">Отправить</button>
По-моему, такой подход смотрится значительно интереснее того же самого БЭМ. Мы пишем основные свойства кнопки, а все модификации пишем не в отдельный класс, а просто поверх.

Удобно до тех пор, пока эти классы-заплатки не зависят от состояния кнопки (цвета зависят) и/или от медиа-запросов (размеры, отступы, позиционирование зависят). Как только да — снова получаем лапшу.

С классами типа .btn.btn-red стало получше — ну потому что движемся к принятым практикам. Но и смысл потихоньку ускользает. Если я все стили утащу в CSS, то зачем мне TW, какую проблему он решает?
Строчки короче? Плевать, скорость набора одинаковая, автокомплит. Важнее очевидность для рандомного разработчика.
Нагляднее? Черт знает. Конечно, есть очевидные вещи типа .font-bold, а скажем .flex-1 не имеет однозначной трактовки без доки.
Путаетесь в похожих цветах и шрифтах? Есть переменные в препроцессоре, есть нативные переменные.

Получается, нет никакой «новой парадигмы».
Есть параллельный язык CSS, который не привносит ничего нового. Это просто дополнительный слой, который дублирует уровень нативного CSS. И их к тому же придется смешивать, потому что для части свойств аналога нет. Вот семантические классы/миксины — это более высокие абстракции, а этот слой — дополнительный, но не другой (читай лишний).
3. Смешаны стили самого блока и его позиционирование.
Этот пункт снимается. Не туда посмотрел и подумалось, что там написано px-4 my-2.

Меня всегда удивляло как люди совершенно некомпетентные могут делать выводы на счёт вещей в которых они совершенно не разбираются. Я более чем уверен что вы не написали ни одного проекта, даже одностраничного, на TailwindCSS, но при этом уже мало того что сделали вывод о технологии, но ещё и высказали этот вывод окружающим.

Google -> Атомарный CSS. А потом расскажите нам, какая новая технология этот TailwindCSS.

А кто то говорил что она новая?

Использую этот фреймфорк уже достаточно давно. Из моих личных наблюдений:
1. Длина списка классов может быть огромная (на две строки). Пример: кнопка с бордерами, фоном, шрифтами, тд.:
2. Практически невозможный рефакторинг. Например, создаем кнопки и потом ее копипастим N раз:
3. Что бы использова CSS переменные, нужно переписать конфиг.

Но плюсов все же больше:
1. Проблемы 1 и 2 решаются выносом в компоненты;
2. Автоматическая генерация части дизайн системы;
3. Один язык между дизайнером и разработчиком (нет пикселей, есть имена);
4. Как следствие из п. 3 — абстракция от реальных значений цвета\размеров;
5. Реюзабельность через плагины.

На данный момент отказываться не планирую, очень удобный фреймворк для меня оказался.
Думал уже все переболели атомарным css несколько лет назад, а оказывается новый шаг эволюции.
Отличная вещь, не перестаю рекомендовать. Применяю у себя в средне-крупных проектах, коллеги из штатов тоже повнедряли, повысили скорость дизайна и верстки. Админка, личный кабинет пользователя, публичные каталоги и карточки, посадочные страницы, общая навигация.

Tailwind легко внедряется, легко сочетается с БЭМ и css-in-js подходами, не ограничивает в жестких рамках по стилю (как бутстрап и аналоги), но задает общие правила дизайн системы (кодеры могут набрасывать дизайн на местах, и он не будет тошнотворным)

ДД, прочёл пост, спс за информацию, концепция описанная заинтересовала, но большая беда с английским, нет ли на просторах рунета перевода документации, можно конечно скачать и ковыряться, но хотелось бы прочесть

Это не «фреймворк». Это набор хэлперов и сборщик для них.
Это не «новый шаг эволюции». Это попытка реинкарнировать методологию атомарного CSS, о которой уже успели основательно забыть.
Он не удобнее «ванильного CSS», потому что круг задач, которые он адекватно решает, достаточно мал.

Это нишевый инструмент, и чтобы его тянуть в проект, надо четко понимать зачем он там. В противном случае будет как с бутстрапом, который тянули везде, где надо и где нет, порождая хаос и бардак.
Интересует, реально ли его использование с cms, когда нужно будет править шаблон?
Как я понял, лишние стили удаляются перед билдом. Получается, нужно будет снова собирать проект, чтобы появились добавленные стили. Не знаю, это вообще реально будет, если вёрстка уже посажена на cms.

Как я понял, основная идея подхода, как и сказал автор — "никаких лишних стилей". Это хорошо работает, когда в проекте есть достаточно строгая дизайн-система с ограниченным набором цветов, отступов и пр. В таком случае при создании новых компонентов, экранов (страниц) CSS не должен расти в размерах (или не на много прибавит веса).


Но все, сто может быть автоматизировано, должно быть автоматизировано. Создавать россыпь атомарных классов должен некий сборщик/компилятор, а не разработчик.


Мое видение работы:


  1. В режиме разработки пишем как обычно:
    <button class="button" />

    .button {
    display: inline-flex;
    padding: 12px 16px;
    color: #333;
    }
  2. В режиме тестирования отладки компилятор уже создал атомарные классы, но оставил возможность искать нужный компонент прямо в инспекторе браузера. Это удобно для разработчиков/дизайнеров.
    <button class="d-if py-3 px-4 c-text" data-original-class="button" />
  3. Для режима эксплуатации удаляем data-атрибуты (или можем оставить, если HTML не сильно раздувается).
    <button class="d-if py-3 px-4 c-text" />

Поэтому лучше взять что-то вроде CSS-blocks или Deterministic StyleSheets.

Ох, пытался я понять этот Tailwind, открыл его видеокурс и начал смотреть.

На первых десяти минутах всё казалось приятно и мило. Но потом, чтобы добиться хоть какого-то малейшего благообразия картинки и «флюидности», автор начал вписывать около двадцати классов на каждой строчке — я тут же закрыл и забыл.

Какие есть у TailwindCSS средства для темизации? Светлые, темные, контрастные темы.

Если делать темизацию, как например в Slack или на этом сайте, то такой способ явно не подходит.

Почему не подходит? В tailwind все цветовые схемы строятся на основе css переменных. Меняйте их js'ом и будут вам разные цветовые темы, хотя сайтов с такими требованиями процента 2 от всех проектов которые требуются. Чаще всего смена темы это намного больше чем цвета на странице поменять и такое обычно выносится на сервер, а клиенту отдают только одну тему ну и может ещё dark mode

Не представляю человека, который согласился бы писать так:


<div class="text-color-1 theme-1:text-color-1 theme-2:text-color-2 theme-N:text-color-N"></div> 

Как используются здесь custom properties, я не увидел.

а никто и не предлагает такое писать. Ещё раз повторяю, цвет определяется в конфиге и задаётся как custom property
<div class="text-color-1"></div> 

вот и всё что нужно написать, а когда пользователь выбирает другую тему — менять этот цвет на любой другой js'ом через root.style.setProperty
если немного погуглить можно даже видео урок найти по этому поводу www.youtube.com/watch?v=MAtaT8BZEAo

Попробовал поработать с Tailwinds на проекте, где предлагалось его использовать для компонентов Laravel.

Поначалу показалось, что очень удобная штука, можно все макро-стили писать прямо inline в HTML, а часто используемые наборы стилей использовать с @apply.

Но на практике получилось, что

  • для любого изменения верстки надо пересобирать проект через Laravel Mix. То есть всегда открыт терминал и вообще подразумевается, что у разработчика есть к нему доступ. Это нормально для программистов, но совершенно неочевидно для верстальщика или дизайнера. Да и просто это долго!

  • Код получается дико многословный. Если при использовании Bootstrap навешивать 3-4 класса это много, то здесь 10--15 классов это норма. Причем не для сложных сеток, а для простых элементов типа полей ввода.

  • Семантика очень лаконичная, очень много двухбуквенных классов, поэтому набор классов на элементе выглядит нечитаемо, выхватить взглядом где там в коде какой отступ очень сложно

  • В целом это очень сильно замусоривает HTML. Хуже получалось только у Svelte с его стопкой нечитаемых названий стилей! Но с HTML после этого работать нельзя. В целом, CSS изобрели для того, чтобы отделить отображение от структуры, а здесь всё получается вперемешку, как с использованием inline CSS (атрибута style). Ну, ладно, чуть лучше, макросы немного выручают и обещается оптимизация. Но грабли те же.

  • Как итог - получается очень вязкий код, который нужно держать постоянно в голове, и найти, почему у тебя где-то отступы не такие как надо, совершенно нереально.

В итоге я замучился это поддерживать, выкинул всё, что связано с Tailwinds и перевел проект на Bootstrap. Это было не очень больно, зато потом сэкономил кучу времени.

В общем, для прототипов это и правда удобно, но для реальной работы я бы его никому не посоветовал.

очень много двухбуквенных классов

например? Двухбуквенные только отсутпы

В целом это очень сильно замусоривает HTML

А лучше замусоривать CSS и перезаписывать килотонны стилей в легаси проектах?

и найти, почему у тебя где-то отступы не такие как надо, совершенно нереально.

очень странное заявление. Нет, серьёзно, когда нет каскада, специфичности, сложных селекторов, когда любой отступ определяется одним классом на конкретном элементе, я серьезно не понимаю в чём сложность взять Inspect Element и кликнуть по элементу на котором нужно увидеть отступ. Это действительно настолько сложно?

<a class="btn btn-primary btn-spinner btn-sm pull-right m-b-0" href="{{ url('admin/users/create') }}" role="button">{{ trans('admin.user.actions.create') }}</a>

Реальный пример одной единственной кнопки в админке с максимально простым интерфейсом.


То есть мы последовательно говорим:


  • это кнопка
  • это основная кнопка
  • это кнопка-спиннер
  • это маленькая кнопка
  • это элемент, который должен висеть справа
  • это элемент с нулевым нижним отступом

То есть это такой конструктор, и где-то это удобно, где надо по ходу создавать дизайн из маленьких блочков. Но если дизайн прорисован заранее, это становится излишне: описание того, как выглядит кнопка, занимает почти столько же места, сколько всё остальное.


Гибкость? Да. Но управлять всем этим, когда проект разрастётся, мне совершенно не хочется. По мне, так в проде тут должно быть 1-2 класса, не больше.


А уж если это более сложный элемент, или кнопка не в админке, а во фронте...

а где здесь TailwindCSS? Вы тут показали свою личную логическую разбивку на составляющие при чём используя как раз что то больше напоминающее БЭМ. Из Tailwind тут только пара классов по позиционированию которые вообще не должны быть частью компонента т.к. относятся к его позиционированию в родителе и должны назначаться снаружи в зависимости от ситуации. Не знаю с чем вы используете Tailwind но скорее всего это какой то фреймворк из большой тройки который как раз и должен опеределять логику поведения компонента. Возьмём как пример вашу логику и реализуем её в рамках Vue:
<my-btn variant="primary" size="sm" class="pull-right mb-0" :loading="isLoading">{{ trans('admin.user.actions.create') }}<my-btn/>

это то что мы получаем при использовании компонента — всё очень компактно, всего 2 класса определяющие позиционирование, в родителе сразу понятно где эта кнопка находится, для этого даже браузер открывать не надо.
Что у нас внутри:
<template>
    <a :class="`btn btn-${variant} btn-${size}`"><slot/></a>
</template>
<style scoped>
    .btn {
         @apply ...
     }

     .btn-sm {
         @apply ...
      }

      .btn-loading {
          @apply ...
       }
</style>

Вот пример с apply для тех кого пугают 40 классов (хотя я не помню чтобы столько было хотя бы на одном компоненте). Но в большинстве случаев даже apply не нужен т.к. обычно хватает 2-3 класса для описания на одном узле. При этом о том что кнопка должна быть с загрузкой или маленькая знает не только css, а и js что даёт возможность полноценной модификации поведения на всех уровнях. Добавления класса это лишь частный случай.

Видел этот "фреймворк" очень-очень давно (либо что-то с такой же концепцией), ну это детский сад конечно. Если у бутстрапа бывает многовато классов на тег, то это вообще трындец тотальный. Все "проблемы" которые тут описаны решает sass/scss

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории