Classless CSS на основі Tailwind

Ця стаття повинна починатися зі слів, що я звісно не справжній верстальщик, але я вам буду рекомендувати як сайти верстати :)

Classless CSS

— Що воно таке, та навіщо треба?

Почнемо з початку, classless CSS підхід – це методологія створення веб-сторінок, яка не вимагає від розробників використання класів у HTML для стилізації елементів. Замість цього, вона робить акцент на використанні стандартних HTML тегів і спадковості CSS для задання стилів сторінці. Це суттєво відрізняється від традиційних підходів, де для кожного елемента або компонента сторінки створюється унікальний набір класів.

Чому Classless?

Спрощення коду:
Одна з головних переваг полягає в спрощенні структури коду, HTML-код стає чистішим і легшим для читання.

Швидкість розробки:
Classless CSS може значно прискорити процес розробки простих сторінок, оскільки розробнику не потрібно витрачати час на створення і управління класами. Все, що потрібно, — це знання основних HTML тегів або мати приклади звідкіля взяти структуру сторінки.

Легше підтримувати:
Оскільки вся стилізація зосереджена навколо стандартних елементів HTML і загальних CSS правил, внесення змін або оновлень до дизайну стає простішим. Це знижує ризик помилок і полегшує утримання коду в довгостроковій перспективі.

Краща сумісність і доступність:
Використання стандартних HTML тегів забезпечує кращу сумісність з різними браузерами і пристроями. Також це сприяє доступності контенту для користувачів з обмеженими можливостями, оскільки багато тегів мають вбудовані атрибути доступності.

Знов таки повторюсь, все це за умови, що наш інтерфейс досить простий, а не apple.com там якийсь. Загалом, це виглядає так, що це непоганий вибір, якщо мова йде про розробку якогось прототипа, а у вас немає часу на те, щоб оті класи крутити, підключили файл стилів, та користуєтесь.

Для реалізації такого підходу є багато фреймворків, мені ліньки тут їх всіх розглядати, тим паче добра людина вже їх зібрала докупи на GitHub – https://github.com/dbohdan/classless-css.

Приклади

— Давай вже слайди приклади коду!

Давайте порівняємо декілька варіантів HTML коду (цей код з прикладів до мого підручника jQuery для початківців).

Ось приклад HTML коду, який я використовую, і який відповідає принципу classless:

<header>
  <h1>jQuery для початківців</h1>
  <p>«Живі» приклади як додаток до підручника</p>
  <a href="https://anton.shevchuk.name/jquery-book/">
    <img src="images/book.svg" width="24" height="24" alt="Book Icon" />
    Підручник
  </a>
  <a href="https://github.com/AntonShevchuk/jquery-for-beginners">
    <img src="images/github.svg" width="24" height="24" alt="GitHub Icon" />
    GitHub
  </a>
</header>

А ось так він виглядав, коли я використовував Bootstrap:

<header class="container-md my-4">
  <div class="row justify-content-center">
    <div class="bg-light border rounded p-4 col-11 col-md-11 col-lg-10 col-xl-9 col-xxl-8">
      <h1>jQuery для початківців</h1>
      <p>«Живі» приклади як додаток до підручника</p>
      <a class="btn btn-primary" href="https://anton.shevchuk.name/jquery-book/" role="button">
        <i class="bi bi-book"></i>
        Підручник
      </a>
      <a class="btn btn-success" href="https://github.com/AntonShevchuk/jquery-for-beginners" role="button">
         <i class="bi bi-github"></i>
         GitHub
      </a>
    </div>
  </div>
</header>

Варіант для Tailwind не сильно відрізняється:

<header class="mx-auto my-4 max-w-md md:max-w-lg lg:max-w-xl xl:max-w-2xl">
  <div class="flex justify-center">
    <div class="bg-gray-100 border border-gray-200 rounded p-4 w-11/12 md:w-11/12 lg:w-10/12 xl:w-9/12 2xl:w-8/12">
      <h1 class="text-xl font-bold">jQuery для початківців</h1>
      <p class="mt-2">«Живі» приклади як додаток до підручника</p>
      <div class="flex gap-2 mt-4">
        <a class="inline-block px-4 py-2 bg-blue-600 text-white rounded leading-none hover:bg-blue-700" href="https://anton.shevchuk.name/jquery-book/" role="button">
          <svg class="bi bi-book inline-block w-4 h-4 mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> <!-- SVG icon content --> </svg>
          Підручник
        </a>
        <a class="inline-block px-4 py-2 bg-green-500 text-white rounded leading-none hover:bg-green-600" href="https://github.com/AntonShevchuk/jquery-for-beginners" role="button">
           <svg class="bi bi-github inline-block w-4 h-4 mr-2" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"> <!-- SVG icon content --> </svg>
           GitHub
        </a>
      </div>
    </div>
  </div>
</header>

Якби я створював версію згідно методології BEM (Block-Element-Modifier):

<header class="main-header my-4">
  <div class="main-header__content">
    <div class="main-header__inner light-bg border rounded p-4">
      <h1 class="main-header__title">jQuery для початківців</h1>
      <p class="main-header__description">«Живі» приклади як додаток до підручника</p>
      <a class="main-header__link main-header__link--primary" href="https://anton.shevchuk.name/jquery-book/" role="button">
        <i class="main-header__icon main-header__icon--book"></i>
        Підручник
      </a>
      <a class="main-header__link main-header__link--success" href="https://github.com/AntonShevchuk/jquery-for-beginners" role="button">
        <i class="main-header__icon main-header__icon--github"></i>
        GitHub
      </a>
    </div>
  </div>
</header>

Якби я б працював у Facebook, та генерував HTML за допомоги їх тулзів:

<div class="x1i10hfl">
  <div class="x1qjc9v5">
    <header class="xa49m3k">
      <div class="x9f619 xqeqjp1">
        <h1 class="x2hbi6w">jQuery для початківців</h1>
      </div>
      <div class="x9f619">
        <p class="x1ypdohk">«Живі» приклади як додаток до підручника</p>
      </div>
      <div class="xdl72j9 x9f619 x2lwn1j">
        <a href="https://anton.shevchuk.name/jquery-book/" class="x2lah0s">
          <div class="xe8uvvx">
            <img src="images/book.svg" width="24" height="24" alt="Book Icon" class="x2lwn1j" />
          </div>
          <span class="xeuugli">Підручник</span>
        </a>
      </div>
      <div class="x16tdsg8 x9f619 x1hl2dhg">
        <a href="https://github.com/AntonShevchuk/jquery-for-beginners" class="x1hl2dhg">
          <div class="xggy1nq">
            <img src="images/github.svg" width="24" height="24" alt="GitHub Icon" class="x1ja2u2z" />
          </div>
          <span class="x1t137rt">GitHub</span>
        </a>
      </div>
    </header>
  </div>
</div>

Результат «вражає»

— Виглядає так, що перший приклад дійсно виглядає непогано, а як з приводу візуальної складової?

Візуальна складова виглядає так само, як і у версії з Bootstrap:

— Щось тут не так, «цей єнот свистить»!

Так, це не зовсім classless, бо щоб отримати такий результат я використовую Tailwind CSS. Звісно Tailwind CSS на перший погляд може здатися протилежним classless підходу через його упор на використання утилітарних класів, але він може бути адаптований для підтримки classless методології.

Але давайте поступово.

Tailwind CSS як classless фреймворк

Мені подобається обидва підходи до розробки, я маю на увазі utility-first у Tailwind, та чистота кода у classless підході. Тож, не довго думаючи, я вирішив створити монстра гібридне рішення за допомоги Tailwind та їх CLI тулзи.

Я не буду детально описувати процес інсталяції Tailwind, бо на сайті розробників вже все є — https://tailwindcss.com/docs/installation, мене тут цікавить лише файл input.css, бо окрім нього нам більше нічого не треба (окрім нього та Tailwind CLI звісно).

Запускаємо консольну тулзу:

npx tailwindcss -i ./src/input.css -o ./css/output.css --watch

На HTML-сторінку підключаємо output.css:

<head>
  <meta charset="UTF-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Classless Tailwind CSS</title>
  <link rel="profile" href="https://gmpg.org/xfn/11"/>
  <link rel="shortcut icon" href="https://anton.shevchuk.name/favicon.ico"/>
  <link rel="stylesheet" href="css/output.css"/>
</head>
<body>
<header>
  <h1>jQuery для початківців</h1>
  <p>«Живі» приклади як додаток до підручника</p>
  <a href="https://anton.shevchuk.name/jquery-book/">
    <img src="images/book.svg" width="24" height="24" alt="Book Icon" />
    Підручник
  </a>
  <a href="https://github.com/AntonShevchuk/jquery-for-beginners">
    <img src="images/github.svg" width="24" height="24" alt="GitHub Icon" />
    GitHub
  </a>
</header>
</body>

За моїм задумом, я хочу створити базовий набір стилів, який буде автоматично застосовується до стандартних HTML елементів, мінімізуючи або навіть усуваючи потребу в додаткових класах. Для швидкої розробки таких стилів я буду використовувати стилі Tailwind з дерективою @apply, давайте я приведу приклад стилів для того шматочка HTML, що я вище додавав:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  header {
    @apply mx-auto max-w-4xl w-5/6 my-4 p-8;
    @apply bg-gray-100 border border-gray-200 rounded;
    h1 {
      @apply text-4xl;
    }
    p {
      @apply mt-2
    }
    a {
      @apply w-36 py-2 mt-4 rounded text-white leading-none inline-flex items-center justify-center;
      &:first-of-type {
        @apply bg-blue-600 hover:bg-blue-700 mr-1
      }
      &:last-of-type {
        @apply bg-green-700 hover:bg-green-800
      }
      img {
        @apply inline-block mr-2;
      }
    }
  }
}

В результаті, ми отримаємо досить об’ємний CSS, але HTML буде чистий, при чому ніяких нових стилів ми не прописали, а перевикористали все те що нам дає Tailwind. На мою думку, такий гібридний підхід підійде для швидкої розробки прототипів, або не занадто складних інтерфейсів, як той що я для підручника розробив.

Але тут головне не перестаратися, бо ось такі селектори як &:first-of-type та &:last-of-type то антіпатерн, у таких випадках краще таки використовувати саме класи для кнопок.

Окрім базового набору стилів я також створив декілька компонентів — це окреми шматочок коду, який в мене міг з’явитися у різних частинах сторінки, та у такому випадку я використовував класи:

@layer components {
  .events {
    @apply list-none p-0;
    li {
      @apply p-[2px];
    }

    li span {
      @apply rounded-full inline-block px-1 mx-1 mr-2 min-w-6 text-center bg-amber-400 text-white;
    }
  }
}

А ще чудернацький класс formatter як утиліту для форматування сторінки (ось тут приклад його роботи):

@layer utilities {
  .formatter {
    h1, h2, h3 {
      @apply text-lg text-slate-900 pt-2 pb-1 px-4;
    }

    h1 {
      &::before {
        content: "<h1>";
        @apply mx-2 text-base text-sky-700;
      }

      &::after {
        content: "</h1>";
        @apply mx-2 text-base text-sky-700;
      }
   }
}

Заголом, мені так сподобався цей підхід, що я навіть вирішив написати цю статтю :)

Повний код моїх classless CSS-стилів для Tailwind є на GitHub:

P.S.

Насправді, нічого нового я тут не розказав, бо насправді все це є у офіційній документації, просто не всі її читають, так буває.

One thought on “Classless CSS на основі Tailwind”

  1. Чудовий підхід, в документації він не був настільки зрозумілим, дякую

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.