murtaza

Halo! Sudah atau mau mencoba Tailwind CSS? pas banget kesini! saya akan membagikan beberapa hal yang cukup penting seputar Tailwind CSS.

Sebenarnya bukan 'best practices' juga sih. Lebih ke coding style dan beberapa tips yang membuat saya nyaman dalam menggunakan Tailwind CSS.

Opiniated sih jatuhnya, tapi siapa tau ada yang bisa diambil, positifnya, ya kan.


Coding Style

Berikut coding style untuk penulisan Tailwind CSS classes yang sering saya gunakan, dibagi menjadi 3 point penting: sorting, splitting dan grouping.

Sorting

Coba liat dulu contoh komponen Button berikut, panjang banget classnya 😂

<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  Button Text
</button>

Karena berurusan dengan nama class yang akan sangat banyak hanya untuk sebuah element, sorting class cukup penting.

Untungnya, Tailwind CSS sendiri sudah menyiapkan plugin Prettier untuk menghandle urusan ini.

Konsistensi urutan class akan memudahkan dalam proses maintenance kedepannya.

Misal, yang ada dalam contoh, dengan class yang sudah di sortir, kita bisa dengan mudah mengubah border dan border-transparent karena saling berdampingan.

Atau dapat dengan mudah mengubah styles hover: atau breakpoints karena biasanya muncul di bagian akhir class.

Splitting

Untuk membuatnya lebih rapi, kita bisa split classnya jadi beberapa string atau line (agar tidak terlihat terlalu panjang). Kalau saya sih biasa pake clsx.

Contoh sebuah komponen Button yang sudah menggunakan clsx:

function Button({ children }) {
  return (
    <button
      className={clsx(
        'inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 md:rounded-xl',
        'dark:bg-purple-600 dark:hover:bg-purple-500'
      )}
    >
      {children}
    </button>
  );
}

Grouping

Setelah classnya terpisah, kita bisa 'grouping' untuk membuatnya lebih rapi dan juga nyaman dibaca.

Biasanya, pattern yang saya terapkan adalah:

  • group 1: default utilites
  • group 2: breakpoints utilities
  • group 3: dark mode utilites
  • group 4: other variants utilites

Kita implementasikan menggunakan komponen Button tadi:

function Button({ children }) {
  return (
    <button
      className={clsx(
        // group 1
        'inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150',
        // group 2
        'md:rounded-xl',
        // group 3
        'dark:bg-purple-600 dark:hover:bg-purple-500',
        // group 4
        'hover:bg-purple-700'
      )}
    >
      {children}
    </button>
  );
}

Sama halnya dengan komponen CSS:

.button {
  /* group 1 */
  @apply inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150;
  /* group 2 */
  @apply md:rounded-xl;
  /* group 3 */
  @apply dark:bg-purple-600 dark:hover:bg-purple-500;
  /* group 4 */
  @apply hover:bg-purple-700;
}

Group 2,3 dan 4 sebenarnya masih bisa di improve atau disesuaikan lagi sesuai keinginan, hanya pastikan untuk membuatnya konsisten di setiap penulisan.


Tips

Gunakan Komponen

Jika dirasa beberapa element mempunyai styles yang sama, bisa di split jadi komponen tersendiri, seperti button yang biasanya memiliki styles yang sama.

Karena saya menggunakan React, saya bisa saja membuat komponen seperti:

function Button({ children }) {
  return (
    <button
      className={clsx(
        'inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150',
        'md:rounded-xl',
        'dark:bg-purple-600 dark:hover:bg-purple-500',
        'hover:bg-purple-700'
      )}
    >
      {children}
    </button>
  );
}

Gunakan Class Component

Sama seperti komponen, tapi cara ini digunakan untuk optimasi ukuran atau output file html, khususnya untuk static site.

Karena nama class yang banyak dari Tailwind CSS akan menambahkan beban juga pada HTML.

Coba lihat contoh sederhana, penggunaan set utility yang sama pada button pagination berikut:

<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  Previous
</button>
<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  1
</button>
<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  2
</button>
<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  3
</button>
<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  4
</button>
<button
  class="inline-flex h-10 items-center justify-center gap-1.5 rounded-md border border-transparent bg-purple-600 px-4 text-center text-sm font-bold text-white transition duration-150 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-500 md:rounded-xl"
>
  Next
</button>

Bayangkan jika dalam satu file HTML memiliki beberapa pagination juga, ukuran file HTMLnya pasti akan lebih besar!

Untuk mengurangi ukuran file size dari HTML, kita bisa ubah jadi class component. Kurang lebih penggunaannya seperti ini:

<button class="pagination-button">Previous</button>
<button class="pagination-button">1</button>
<button class="pagination-button">2</button>
<button class="pagination-button">3</button>
<button class="pagination-button">4</button>
<button class="pagination-button">Next</button>

Sudah pernah saya bahas disini (point "Beban ke HTML makin berat").

Penggunaan !important

Layaknya CSS pada umumnya, sebisa mungkin hindari penggunaan !important.

Di Tailwind CSS, !important sendiri bisa dengan menambahkan prefix ! pada setiap utility class, contoh !p-2 !px-3.

Sebisa mungkin hindari! Sekali terjebak menggunakan, mungkin semua utility kita akan berakhir dengan banyaknya !important dan sangat sulit untuk melakukan perubahan styles kedepannya.

Conditional Class

Don't
<div className={`text-black ${dark && 'text-white'}`}>
  Hello, World!
</div>
Do
<div className={dark ? 'text-white' : 'text-black'}>
  Hello, World!
</div>

Let me explain a bit.

Katakanlah kita pake cara yang pertama dan dark nilainya true, maka classnya akan jadi seperti ini text-black text-white.

Dalam beberapa kasus, mungkin hasilnya ya sesuai harapan. Tapi, ketika beberapa kasus juga, mungkin bisa jadi masalah!

Bisa saja, teks tetap berwarna hitam meski nilai darknya true.

Ko bisa? Let the code speak:

<!-- Some elements within the project. -->

<div class="text-white">White!</div>
<div class="text-black">Black!</div>

<!-- 
  The above elements will generate CSS in the following order:

  .text-white {
    ...
  }
  .text-black {
    ...
  }
-->

<!--
  Imagine that "dark" is set to true, and use a class defined as follows for conditional class:
      class={`text-black ${dark && 'text-white'}`}
-->
<div class="text-black text-white">Still black? CSS Specificity!</div>

<!-- 
  That's because, in this example, both "text-black" and "text-white" have the same CSS properties and specificity.
  
  On the other hand, the last one defined in the CSS file (in the previously generated CSS) will take precedence!
-->

Tailwind Play