Membuat komponen tombol

Ringkasan dasar tentang cara membangun komponen <button> yang adaptif warna, responsif, dan dapat diakses.

Dalam postingan ini saya ingin berbagi pendapat saya tentang cara membangun aplikasi warna-warni yang adaptif, elemen <button> yang responsif dan dapat diakses. Coba demo dan lihat sumber

Tombol berinteraksi melalui keyboard dan mouse dalam tema terang dan gelap.

Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:

Ringkasan

Dukungan Browser

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

Sumber

Tujuan <button> dibuat untuk interaksi pengguna. Peristiwa click terpicu dari keyboard, mouse, sentuhan, suara, dan lainnya, dengan aturan cerdas tentang waktu. Panduan ini juga dilengkapi dengan beberapa gaya {i>default<i} di setiap browser, sehingga Anda dapat langsung menggunakannya tanpa penyesuaian apa pun. Gunakan color-scheme untuk memilih juga ke dalam tombol terang dan gelap yang disediakan oleh browser.

Ada juga berbagai jenis tombol, yang ditunjukkan dalam sematan Codepen sebelumnya. <button> tanpa jenis akan beradaptasi agar berada dalam <form>, berubah menjadi jenis pengiriman.

<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>

<!-- button state -->
<button disabled></button>

<!-- input buttons -->
<input type="button" />
<input type="file">

Dalam Tantangan GUI bulan ini, setiap tombol akan mendapatkan {i>style<i} untuk membantu membedakan maksudnya secara visual. Reset tombol akan memiliki warna peringatan karena bersifat merusak, dan kirim tombol akan mendapatkan teks aksen biru sehingga tampak sedikit lebih dipromosikan daripada teks biasa tombol.

Pratinjau kumpulan akhir semua jenis tombol, ditampilkan dalam bentuk dan bukan dalam formulir, dengan tambahan yang bagus untuk tombol ikon dan tombol yang disesuaikan.
Pratinjau kumpulan akhir semua jenis tombol, yang ditampilkan dalam formulir dan bukan dalam formulir, dengan tambahan yang menarik untuk tombol ikon dan tombol yang disesuaikan

Tombol juga memiliki class semu yang digunakan CSS untuk penataan gaya. Class ini menyediakan hook CSS untuk menyesuaikan tombol: :hover ketika {i>mouse<i} ada di atas tombol, :active saat mouse atau {i>keyboard<i} menekan, dan :focus atau :focus-visible untuk membantu dalam gaya {i>assistive technology<i}.

button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
Pratinjau kumpulan akhir semua jenis tombol dalam tema gelap.
Pratinjau kumpulan akhir semua jenis tombol dalam tema gelap

Markup

Selain jenis tombol yang disediakan oleh spesifikasi HTML, saya telah menambahkan dengan ikon dan tombol dengan class kustom btn-custom.

<button>Default</button>
<input type="button" value="<input>"/>
<button>
  <svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
    <path d="..." />
  </svg>
  Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">

Kemudian, untuk pengujian, setiap tombol ditempatkan di dalam formulir. Dengan cara ini, saya bisa memastikan gaya diperbarui dengan tepat untuk tombol default, yang berperilaku sebagai tombol kirim. Saya juga mengganti strategi ikon, dari SVG inline menjadi SVG yang disamarkan, untuk memastikan bahwa keduanya bekerja dengan baik.

<form>
  <button>Default</button>
  <input type="button" value="<input>"/>
  <button>Icon <span data-icon="cloud"></span></button>
  <button type="submit">Submit</button>
  <button type="button">Type Button</button>
  <button type="reset">Reset</button>
  <button disabled>Disabled</button>
  <button class="btn-custom btn-large" type="button">Large Custom</button>
  <input type="file">
</form>

Matriks kombinasi saat ini cukup banyak. Tombol antar-tombol tipe, kelas semu, dan berada di dalam atau di luar bentuk, ada lebih dari 20 kombinasi dari tombol lainnya. Tentunya CSS dapat membantu kita memahami setiap mereka dengan jelas!

Aksesibilitas

Elemen tombol dapat diakses secara alami tetapi ada beberapa penyempurnaan.

Arahkan kursor dan fokus bersama

Saya suka mengelompokkan :hover dan :focus bersama dengan fungsi :is() pemilih pseudo. Ini membantu memastikan antarmuka saya selalu mempertimbangkan {i>keyboard<i} dan gaya teknologi pendukung.

button:is(:hover, :focus) {
  
}
Coba demo.

Lingkaran fokus interaktif

Saya suka menganimasikan lingkaran fokus untuk pengguna keyboard dan teknologi pendukung. diri dapat dilakukan dengan menganimasikan garis luar tombol sebesar 5px, tetapi hanya ketika tombol tidak aktif. Ini menciptakan efek yang membuat lingkaran fokus mengecilkan kembali ke ukuran tombol saat ditekan.

:where(button, input):where(:not(:active)):focus-visible {
  outline-offset: 5px;
}

Memastikan penerusan kontras warna

Setidaknya ada empat kombinasi warna berbeda di antara terang dan gelap yang membutuhkan pertimbangan kontras warna: tombol, tombol {i>submit<i}, tombol {i>reset<i}, dan dinonaktifkan. VisBug digunakan di sini untuk memeriksa dan menampilkan semua skor mereka sekaligus:

Menyembunyikan ikon dari orang-orang yang tidak dapat melihat

Saat membuat tombol ikon, ikon harus memberikan dukungan visual pada teks tombol. Hal ini juga berarti ikon tidak berharga bagi orang yang dapat melihat kerugian. Untungnya, {i>browser<i} menyediakan cara untuk menyembunyikan item dari {i>screen reader<i} teknologi sehingga orang dengan gangguan penglihatan tidak terganggu dengan tombol dekoratif gambar:

<button>
  <svg … aria-hidden="true">...</svg>
  Icon Button
</button>
Chrome DevTools menampilkan hierarki aksesibilitas untuk tombol. Hierarki mengabaikan gambar tombol karena memiliki aria-hidden yang disetel ke true.
Chrome DevTools menampilkan hierarki aksesibilitas untuk tombol. Hierarki mengabaikan gambar tombol karena memiliki aria-hidden yang disetel ke true

Gaya

Di bagian berikutnya ini, pertama-tama saya membuat sistem properti khusus untuk mengelola gaya adaptif tombol. Dengan properti khusus itu saya bisa mulai memilih elemen dan menyesuaikan tampilannya.

Strategi properti kustom adaptif

Strategi properti khusus yang digunakan di Tantangan GUI ini sangat mirip dengan yang yang digunakan dalam membangun skema warna. Sebagai sistem warna terang dan gelap adaptif, properti khusus untuk setiap tema adalah didefinisikan dan diberi nama sesuai dengan itu. Kemudian, satu properti khusus digunakan untuk menyimpan nilai tema saat ini dan ditetapkan ke properti CSS. Kemudian, single properti khusus dapat diperbarui ke nilai yang berbeda, kemudian memperbarui tombol gaya.

button {
  --_bg-light: white;
  --_bg-dark: black;
  --_bg: var(--_bg-light);

  background-color: var(--_bg);
}

@media (prefers-color-scheme: dark) {
  button {
    --_bg: var(--_bg-dark);
  }
}

Yang saya suka adalah tema terang dan gelap bersifat deklaratif dan jelas. Tujuan pengalihan dan abstraksi dialihkan ke properti khusus --_bg, yang sekarang merupakan satu-satunya properti; --_bg-light dan --_bg-dark adalah statis. Juga jelas untuk membaca bahwa tema terang adalah tema {i>default<i} dan gelap hanya diterapkan secara bersyarat.

Mempersiapkan konsistensi desain

Pemilih bersama

Pemilih berikut digunakan untuk menargetkan semua jenis tombol dan awalnya sedikit membingungkan. :where() sama dengan digunakan sehingga penyesuaian tombol tidak memerlukan kekhususan. Tombol sering kali diadaptasi untuk skenario alternatif dan pemilih :where() memastikan bahwa tugas itu mudah. Di dalam :where(), setiap jenis tombol dipilih, termasuk ::file-selector-button, yang tidak dapat digunakan di dalam :is() atau :where().

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  
}

Semua properti kustom akan dicakup dalam pemilih ini. Waktu peninjauan semua properti khusus! Ada beberapa properti khusus yang digunakan dalam tombol. Saya akan menjelaskan setiap kelompok saat kita bekerja, lalu membagikan kegelapan dan konteks gerakan di akhir bagian tersebut.

Warna aksen tombol

Kirim tombol dan ikon adalah tempat yang tepat untuk menampilkan semburat warna:

--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);

Warna tombol teks

Warna teks tombol tidak putih atau hitam, tetapi versi lebih gelap atau lebih terang dari --_accent menggunakan hsl() dan tetap mengikuti hue 210:

--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);

Warna latar tombol

Latar belakang tombol mengikuti pola hsl() yang sama kecuali untuk tema terang tombol—diatur berwarna putih sehingga permukaannya membuatnya tampak dekat dengan pengguna, atau di depan platform lain:

--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);

Latar belakang tombol dengan baik

Warna latar belakang ini digunakan untuk membuat permukaan muncul di belakang permukaan lain, berguna untuk latar belakang input file:

--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);

Padding tombol

Spasi di sekitar teks dalam tombol dilakukan dengan menggunakan ch unit, panjang relatif terhadap ukuran font. Hal ini menjadi kritis ketika dapat dengan mudah meningkatkan font-size dan skala tombol secara proporsional:

--_padding-inline: 1.75ch;
--_padding-block: .75ch;

Batas tombol

Radius batas tombol disimpan ke dalam properti khusus sehingga input file dapat mencocokkan dengan tombol lainnya. Warna batas mengikuti warna adaptif yang ditetapkan sistem:

--_border-radius: .5ch;

--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);

Efek sorotan pengarahan kursor tombol

Properti ini menetapkan properti ukuran untuk transisi saat interaksi, dan warna sorotan mengikuti sistem warna adaptif. Kami akan membahas bagaimana berinteraksi nanti di postingan ini, tetapi pada akhirnya digunakan untuk box-shadow efek:

--_highlight-size: 0;

--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);

Bayangan teks tombol

Setiap tombol memiliki gaya bayangan teks yang halus. Ini membantu teks berada di atas tombol, meningkatkan keterbacaan dan menambahkan lapisan perbaikan presentasi.

--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);

Ikon tombol

Ikon memiliki ukuran dua karakter berkat satuan panjang relatif ch lagi, yang akan membantu ikon diskalakan secara proporsional dengan teks tombol. Tujuan warna ikon mengandalkan --_accent-color untuk tema adaptif dan dalam tema {i>color<i}.

--_icon-size: 2ch;
--_icon-color: var(--_accent);

Bayangan tombol

Agar bayangan dapat beradaptasi dengan benar terhadap terang dan gelap, mereka harus menggeser warna dan opasitas. Bayangan tema terang paling baik digunakan jika halus dan berwarna terhadap warna permukaan yang dilapisinya. Bayangan tema gelap harus lebih gelap dan lebih tersaturasi sehingga dapat menempatkan warna permukaan yang lebih gelap.

--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);

--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);

Dengan warna dan kekuatan adaptif, saya dapat menyusun dua kedalaman bayangan:

--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));

--_shadow-2: 
  0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
  0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));

Selain itu, untuk memberikan tampilan yang sedikit 3D pada tombol, gunakan bayangan kotak 1px menciptakan ilusi:

--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);

Transisi tombol

Dengan mengikuti pola warna adaptif, saya membuat dua properti statis untuk tahan pilihan sistem desain:

--_transition-motion-reduce: ;
--_transition-motion-ok:
  box-shadow 145ms ease,
  outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);

Semua properti secara bersamaan di pemilih

Semua properti kustom di pemilih

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  --_accent-light: hsl(210 100% 40%);
  --_accent-dark: hsl(210 50% 70%);
  --_accent: var(--_accent-light);

--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);

--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);

--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);

--_padding-inline: 1.75ch; --_padding-block: .75ch;

--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);

--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);

--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);

--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));

--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;

--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);

--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }

Tombol default ditampilkan dalam tema terang dan gelap secara berdampingan.

Adaptasi tema gelap

Nilai pola properti statis -light dan -dark menjadi jelas saat properti tema gelap disetel:

@media (prefers-color-scheme: dark) {
  :where(
    button,
    input[type="button"],
    input[type="submit"],
    input[type="reset"],
    input[type="file"]
  ),
  :where(input[type="file"])::file-selector-button {
    --_bg: var(--_bg-dark);
    --_text: var(--_text-dark);
    --_border: var(--_border-dark);
    --_accent: var(--_accent-dark);
    --_highlight: var(--_highlight-dark);
    --_input-well: var(--_input-well-dark);
    --_ink-shadow: var(--_ink-shadow-dark);
    --_shadow-depth: var(--_shadow-depth-dark);
    --_shadow-color: var(--_shadow-color-dark);
    --_shadow-strength: var(--_shadow-strength-dark);
  }
}

Ini tidak hanya terbaca dengan baik, tetapi konsumen tombol kustom ini juga dapat menggunakan properti polos dengan keyakinan bahwa properti tersebut akan beradaptasi dengan tepat sesuai preferensi pengguna.

Mengurangi adaptasi gerakan

Jika gerakannya sesuai untuk pengguna yang berkunjung ini, tetapkan --_transition ke var(--_transition-motion-ok):

@media (prefers-reduced-motion: no-preference) {
  :where(
    button,
    input[type="button"],
    input[type="submit"],
    input[type="reset"],
    input[type="file"]
  ),
  :where(input[type="file"])::file-selector-button {
    --_transition: var(--_transition-motion-ok);
  }
}

Beberapa gaya bersama

Font dan tombol harus disetel ke inherit agar cocok dengan font halaman lainnya; jika tidak, mereka akan ditata oleh browser. Hal ini juga berlaku untuk letter-spacing. Menyetel line-height ke 1.5 akan menetapkan kotak huruf untuk memberi teks beberapa ruang di atas dan di bawah:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  /* …CSS variables */

  font: inherit;
  letter-spacing: inherit;
  line-height: 1.5;
  border-radius: var(--_border-radius);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Menata gaya tombol

Penyesuaian pemilih

Pemilih input[type="file"] bukanlah bagian tombol input, elemen semu ::file-selector-button, jadi saya menghapus input[type="file"] dari daftar:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  
}

Penyesuaian kursor dan sentuhan

Pertama, saya memberi gaya kursor ke gaya pointer, yang membantu tombol menunjukkan agar pengguna diarahkan bahwa visualisasi itu interaktif. Lalu saya menambahkan touch-action: manipulation ke membuat klik tidak perlu menunggu dan mengamati potensi klik dua kali, sehingga akan terasa lebih cepat:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  cursor: pointer;
  touch-action: manipulation;
}

Warna dan batas

Selanjutnya saya menyesuaikan ukuran {i>font<i}, latar belakang, teks, dan warna batas, menggunakan beberapa properti khusus adaptif yang ditetapkan sebelumnya:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  font-size: var(--_size, 1rem);
  font-weight: 700;
  background: var(--_bg);
  color: var(--_text);
  border: 2px solid var(--_border);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Bayangan

Tombol-tombol tersebut menerapkan beberapa teknik yang hebat. Tujuan text-shadow sama dengan adaptif terhadap terang dan gelap, menciptakan tampilan tombol yang menyenangkan teks yang berada dengan baik di atas latar belakang. Untuk box-shadow, tiga bayangan ditetapkan. Yang pertama, --_shadow-2, adalah bayangan kotak biasa. Bayangan kedua adalah trik mata yang membuat tombol tampak sedikit miring. Bayangan terakhir adalah untuk sorotan pengarahan kursor, awalnya dengan ukuran 0, tetapi akan diberi ukuran nanti dan ditransisikan sehingga muncul untuk berkembang.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  box-shadow: 
    var(--_shadow-2),
    var(--_shadow-depth),
    0 0 0 var(--_highlight-size) var(--_highlight)
  ;
  text-shadow: var(--_ink-shadow);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Tata Letak

Saya memberi tombol tata letak flexbox, khususnya tata letak inline-flex yang sesuai dengan kontennya. Saya kemudian di tengah teks, serta meratakan turunan secara vertikal dan horizontal ke tengah. Ini akan membantu ikon dan lainnya elemen tombol agar disejajarkan dengan benar.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  display: inline-flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Spasi

Untuk spasi tombol, saya menggunakan gap untuk mempertahankan saudara kandung dari menyentuh dan logis properti untuk padding, jadi tombol spasi berfungsi untuk semua tata letak teks.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  gap: 1ch;
  padding-block: var(--_padding-block);
  padding-inline: var(--_padding-inline);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

UX sentuh dan mouse

Bagian berikutnya ini utamanya ditujukan untuk pengguna sentuh di perangkat seluler. Yang pertama properti, user-select, ditujukan untuk semua pengguna; mencegah teks menyoroti teks tombol. Ini sebagian besar terlihat pada perangkat sentuh ketika tombol diketuk dan dipegang dan sistem menyorot teks tombol.

Saya biasanya menemukan bahwa ini bukanlah pengalaman pengguna dengan tombol bawaan aplikasi, jadi saya menonaktifkannya dengan menyetel user-select ke tidak ada. Ketuk warna sorotan (-webkit-tap-highlight-color) dan menu konteks sistem operasi (-webkit-touch-callout) fitur tombol lainnya yang sangat berfokus pada web yang tidak sesuai dengan sesuai dengan ekspektasi pengguna, jadi saya menghapusnya juga.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  user-select: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

Transisi

Variabel --_transition adaptif ditetapkan ke properti transisi:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  transition: var(--_transition);
}

Setelah mengarahkan kursor, saat pengguna tidak menekan secara aktif, sesuaikan sorotan bayangan untuk memberikan tampilan fokus yang bagus, yang tampak tumbuh dari dalam tombol:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
):where(:not(:active):hover) {
  --_highlight-size: .5rem;
}

Saat fokus, tingkatkan offset garis batas fokus dari tombol, serta memberinya tampilan fokus yang bagus yang tampak tumbuh dari dalam tombol:

:where(button, input):where(:not(:active)):focus-visible {
  outline-offset: 5px;
}

Ikon

Untuk menangani ikon, pemilih memiliki pemilih :where() tambahan untuk SVG langsung turunan atau elemen dengan atribut khusus data-icon. Ukuran ikon disetel dengan properti khusus menggunakan properti logis inline dan blok. Warna guratan telah ditetapkan, serta drop-shadow untuk mencocokkan text-shadow. flex-shrink disetel ke 0 sehingga ikon tidak pernah menjadi pas. Terakhir, saya memilih ikon bergaris dan saya menetapkan gaya tersebut di sini dengan Batas baris dan gabungan baris fill: none dan round:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
) > :where(svg, [data-icon]) {
  block-size: var(--_icon-size);
  inline-size: var(--_icon-size);
  stroke: var(--_icon-color);
  filter: drop-shadow(var(--_ink-shadow));

  flex-shrink: 0;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Menyesuaikan tombol kirim

Saya ingin tombol kirim memiliki tampilan yang sedikit dipromosikan, dan saya mencapai ini dengan membuat warna teks tombol menjadi warna aksen:

:where(
  [type="submit"], 
  form button:not([type],[disabled])
) {
  --_text: var(--_accent);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Menyesuaikan tombol reset

Saya ingin tombol {i>reset<i} memiliki beberapa tanda peringatan bawaan untuk memperingatkan pengguna tentang perilaku mereka yang berpotensi merusak. Saya juga memilih untuk menata gaya tema terang dengan lebih banyak aksen merah daripada tema gelap. Penyesuaian dilakukan dengan mengubah warna dasar terang atau gelap yang sesuai, dan tombol akan memperbarui gayanya:

:where([type="reset"]) {
  --_border-light: hsl(0 100% 83%);
  --_highlight-light: hsl(0 100% 89% / 20%);
  --_text-light: hsl(0 80% 50%);
  --_text-dark: hsl(0 100% 89%);
}

Saya juga berpikir akan lebih baik jika warna garis batas fokus agar sesuai dengan merah. Warna teks menyesuaikan merah gelap menjadi merah terang. Saya membuat warna garis batas cocokkan ini dengan kata kunci currentColor:

:where([type="reset"]):focus-visible {
  outline-color: currentColor;
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Sesuaikan tombol yang dinonaktifkan

Sangat umum jika tombol yang dinonaktifkan memiliki kontras warna yang buruk selama mencoba menaklukkan tombol yang dinonaktifkan sehingga tampak kurang aktif. Saya menguji setiap set warna dan memastikannya lulus, sehingga menggeser nilai kecerahan HSL sampai skor yang diteruskan di DevTools atau VisBug.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
)[disabled] {
  --_bg: none;
  --_text-light: hsl(210 7% 40%);
  --_text-dark: hsl(210 11% 71%);

  cursor: not-allowed;
  box-shadow: var(--_shadow-1);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Menyesuaikan tombol input file

Tombol input file adalah penampung untuk span dan tombol. CSS dapat sedikit menata gaya penampung input, serta tombol bertingkat, tetapi tidak {i>span<i} itu. Penampung diberikan max-inline-size sehingga tidak akan bertambah besar dari perlu, sementara inline-size: 100% akan menyusut sendiri dan sesuai container yang lebih kecil darinya. Warna latar belakang disetel ke warna adaptif yang lebih gelap dari permukaan lain, sehingga terlihat di balik tombol {i>file selector<i}.

:where(input[type="file"]) {
  inline-size: 100%;
  max-inline-size: max-content;
  background-color: var(--_input-well);
}

Tombol pemilih file dan tombol jenis input diberikan secara khusus appearance: none untuk menghapus gaya yang disediakan browser yang tidak ditimpa oleh gaya tombol lain.

:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
  appearance: none;
}

Terakhir, margin ditambahkan ke inline-end tombol untuk mendorong teks span di luar tombol, sehingga membuat ruang.

:where(input[type="file"])::file-selector-button {
  margin-inline-end: var(--_padding-inline);
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Pengecualian tema gelap khusus

Saya memberikan latar belakang yang lebih gelap untuk tombol tindakan utama agar kontrasnya lebih tinggi teks, memberi mereka tampilan yang sedikit lebih dipromosikan.

@media (prefers-color-scheme: dark) {
  :where(
    [type="submit"],
    [type="reset"],
    [disabled],
    form button:not([type="button"])
  ) {
    --_bg: var(--_input-well);
  }
}

Screenshot yang menampilkan tombol setelah gaya sebelumnya diterapkan.

Membuat varian

Karena praktis, saya memilih untuk menunjukkan cara membuat beberapa pada semua varian. Satu varian sangat cerah, mirip dengan seberapa sering tombol utama lihat. Varian lain berukuran besar. Varian terakhir memiliki ikon berisi gradien.

Tombol warna cerah

Untuk mencapai gaya tombol ini, saya mengganti properti dasar langsung dengan warna biru warna. Meskipun cepat dan mudah, cara ini menghilangkan properti adaptif dan terlihat sama dalam tema terang dan gelap.

.btn-custom {
  --_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
  --_border: hsl(228 89% 63%);
  --_text: hsl(228 89% 100%);
  --_ink-shadow: 0 1px 0 hsl(228 57% 50%);
  --_highlight: hsl(228 94% 67% / 20%);
}

Tombol kustom ditampilkan dalam warna terang dan gelap. Warna birunya sangat cerah seperti tombol tindakan utama pada umumnya.

Tombol besar

Gaya tombol ini diperoleh dengan memodifikasi properti khusus --_size. Padding dan elemen ruang lainnya relatif terhadap ukuran ini, diskalakan secara proporsional dengan ukuran yang baru.

.btn-large {
  --_size: 1.5rem;
}

Tombol besar ditampilkan di samping tombol kustom, yang berukuran sekitar 150 kali lebih besar.

Tombol ikon

Efek ikon ini tidak ada hubungannya dengan gaya tombol kita, tetapi memang menunjukkan cara mencapainya hanya dengan beberapa properti CSS, dan seberapa baik tombol menangani ikon yang bukan SVG inline.

[data-icon="cloud"] {
  --icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;

  -webkit-mask: var(--icon-cloud);
  mask: var(--icon-cloud);
  background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}

Tombol dengan ikon ditampilkan dalam tema terang dan gelap.

Kesimpulan

Sekarang setelah Anda tahu bagaimana saya melakukannya, bagaimana Anda akan 🙂

Mari kita diversifikasi pendekatan kami dan mempelajari semua cara untuk membangun di web.

Buat demo, link tweet saya, dan saya akan menambahkannya ke bagian remix komunitas di bawah ini.

Remix komunitas

Belum ada apa-apa di sini.

Resource