Teknik CSS untuk efek riak material

Panduan ke berbagai teknik untuk efek riak menggunakan CSS dan JavaScript

Baru-baru ini saya harus menerapkan efek riak dari desain material ke dalam aplikasi web. Dan kemudian saya menyadari bahwa saya tidak tahu bagaimana itu diterapkan. Ini membawa saya ke sebuah perjalanan untuk mempelajari implementasi yang ada, dan bahkan datang dengan teknik baru yang mungkin berguna bagi Anda.

Apa efek riak ini?

Tunggu, Anda tidak tahu efek riak dari Desain Material Google? Sudah berapa tahun kamu tinggal di gua?

Efek riak digunakan ketika Anda menekan tombol. Ini bekerja dengan cara yang sama untuk interaksi mouse atau sentuh.

Posisi yang Anda klik atau sentuh pada tombol disebut titik kontak. Dari sana, riak dikirim bergerak ke luar, kehilangan opacity saat itu tumbuh lebih besar sampai mengisi seluruh tombol. Maka menghilang sepenuhnya.

Dinamika efek riak ini mirip dengan riak yang Anda dapatkan saat menyentuh permukaan cair, atau ketika Anda menjatuhkan batu ke danau.

Riak yang akan Anda temukan di web

Setelah melakukan riset, saya bisa menemukan dua teknik utama yang digunakan untuk menerapkan efek riak pada aplikasi web.

Menggunakan :: after pseudo-element

Menggunakan teknik ini, elemen :: after pseudo dari tombol ditata sebagai lingkaran semi-transparan, dan dianimasikan untuk tumbuh dan memudar. Tombol wadah harus memiliki luapan: disembunyikan sehingga lingkaran tidak pernah meluap di luar permukaan tombol, dan posisi: relatif untuk memudahkan posisi lingkaran di dalam tombol. Anda dapat membaca lebih detail tentang teknik ini pada artikel ini oleh Ionuț Colceriu.

Salah satu hal hebat tentang teknik ini adalah bahwa itu adalah solusi CSS murni untuk efek riak. Namun, efek riak selalu dimulai dari tengah tombol, bukan dari titik kontak. Itu bukan umpan balik yang paling alami.

Ini dapat ditingkatkan dengan menggunakan JavaScript untuk menyimpan titik kontak, dan menggunakannya untuk memposisikan riak. Itulah yang dilakukan material.io untuk komponen riak web mereka. Ini menggunakan variabel CSS untuk menyimpan titik kontak, dan elemen :: after pseudo menggunakan variabel ini untuk penentuan posisi.

Menggunakan elemen anak

Intinya, teknik ini menggunakan strategi yang sama seperti sebelumnya. Tetapi alih-alih elemen pseudo, ia menambahkan elemen rentang di dalam tombol, yang kemudian dapat diposisikan melalui JavaScript. Teknik ini dijelaskan pada artikel ini oleh Jhey Tompkins.

Implementasi paling sederhana menciptakan rentang untuk setiap klik pada tombol, dan menggunakan posisi mouse pada acara klik untuk mengubah posisi rentang. Animasi CSS membuat rentang tumbuh dan memudar hingga menjadi sepenuhnya transparan. Kita dapat memilih untuk menghapus rentang dari DOM setelah animasi selesai, atau tinggalkan saja di bawah karpet - tidak ada yang akan benar-benar melihat rentang transparan berkeliaran.

Saya memang menemukan variasi lain dari ini, di mana elemen anak adalah svg bukan span, dan svg dianimasikan melalui JavaScript. Variasi ini dijelaskan oleh Dennis Gaebel, tetapi pada dasarnya tampaknya sama, dan mungkin memungkinkan untuk menggunakan bentuk dan efek SVG yang kompleks.

Masalah dengan mengirim input

Kedua teknik yang dijelaskan di atas tampak hebat. Tapi inilah yang terjadi ketika saya mencoba menerapkannya pada elemen input dengan tipe = kirim:

Kenapa mereka tidak bekerja?

Elemen input adalah elemen yang diganti. Singkatnya, itu berarti sangat sedikit yang dapat Anda lakukan dengan elemen-elemen itu, berkenaan dengan DOM dan CSS. Secara khusus, mereka tidak dapat memiliki elemen anak, dan tidak ada elemen pseudo juga. Sekarang sudah jelas mengapa teknik ini gagal.

Jadi, jika Anda menggunakan Desain Material, lebih baik menjauh dari input [type = kirim], dan tetap berpegang pada elemen tombol. Atau terus membaca.

Menambahkan riak untuk mengirim input

Pada aplikasi web yang sedang saya kerjakan, kami sudah memiliki banyak tombol kirim. Mengubah semuanya untuk menjadi elemen yang berbeda akan membutuhkan banyak pekerjaan, dan risiko tinggi melanggar stylesheet dan logika JavaScript. Jadi saya harus mencari cara menambahkan riak ke tombol kirim yang ada.

Menggunakan wadah pembungkus

Saya segera menyadari bahwa saya bisa membungkus tombol kirim di dalam elemen blok-inline, dan menggunakan elemen blok-inline sebagai permukaan riak. Ini demo cepat:

Meskipun saya menyukai solusi ini karena kesederhanaannya, masih diperlukan saya untuk mengubah markup di terlalu banyak tempat. Dan saya tahu itu akan menjadi solusi yang rapuh - pengembang baru akan datang ke proyek, dan membuat tombol kirim tanpa membungkusnya dengan benar di permukaan riak. Jadi saya terus mencari solusi lain yang tidak perlu mengubah DOM.

Gradien radial

Sintaks gradien radial memungkinkan saya untuk mengontrol pusat dan ukuran gradien. Tentu saja, ini juga memungkinkan saya untuk mengontrol warna gradien, termasuk warna semi-transparan. Dan itu tidak pernah melebihi elemen yang diterapkannya. Jadi sepertinya sudah melakukan semua yang saya butuhkan!

Tidak terlalu cepat ... ada satu hal yang hilang: properti background-image tidak dapat dianimasikan. Saya tidak bisa membuat gradien tumbuh dan memudar menjadi transparan menggunakan animasi CSS. Saya berhasil membuatnya tumbuh dengan menghidupkan properti ukuran latar belakang, tapi hanya itu yang bisa saya lakukan.

Saya mencoba beberapa hal lain, seperti memiliki lingkaran pudar sebagai gambar animasi (menggunakan format apng), dan menerapkannya sebagai gambar latar. Tapi kemudian saya tidak bisa mengontrol kapan loop gambar dimulai dan berakhir.

Akhirnya, solusi dengan JavaScript

Apa yang tidak bisa Anda lakukan dalam CSS, Anda bisa melakukannya dalam JavaScript. Setelah menghabiskan lebih banyak waktu daripada yang mau saya akui mencoba membuat efek ini bekerja menggunakan animasi CSS, saya menyerah dan memutuskan untuk menulis animasi dalam JavaScript.

Saya mulai dengan solusi gradien radial di atas, dan menggunakan window.requestAnimationFrame untuk membuat animasi fluida gradien radial, tumbuh dan memudar. Inilah solusi terakhir saya:

Kesimpulan

Jadi dimungkinkan untuk memiliki efek riak pada tombol kirim, hanya saja tidak dengan CSS saja.

Saya tidak dapat menemukan teknik ini didokumentasikan di mana pun di web, jadi saya menyebutnya milik saya. Teknik riak Leonardo tidak memerlukan perubahan pada DOM, dan berfungsi untuk elemen apa pun karena tidak bergantung pada elemen semu atau elemen anak. Namun, ini bukan solusi sempurna.

Pertama, ada kinerja. Dengan menghidupkan gradien dengan JavaScript, Anda kehilangan banyak optimasi browser. Tetapi, karena satu-satunya properti yang diubah adalah gambar latar belakang, saya menduga bahwa browser tidak perlu melakukan reflow, dan hanya perlu menerapkan kembali gaya dan mengecat ulang elemen. Dalam praktiknya, itulah yang terjadi, dan kinerja sangat bagus. Pengecualian untuk pernyataan itu adalah Firefox Mobile, yang karena alasan tertentu tidak mengikuti animasi. (sunting: animasi lancar di versi Firefox Mobile modern)

Kedua, teknik ini menggunakan properti gambar latar belakang tombol. Jika desain Anda mengharuskan tombol Anda untuk menerapkan gambar ke latar belakangnya, efek riak akan menimpanya. Jika Anda benar-benar membutuhkan gambar itu pada desain Anda, maka JavaScript dapat dimodifikasi untuk menggambar gradien radial di atas gambar latar belakang yang ada.

Ketiga, ini sepertinya tidak berfungsi di Internet Explorer. Namun, saya tidak melihat alasan mengapa itu tidak bisa bekerja dengan IE10 dan di atas. Mungkin itu karena IE menggunakan sintaks yang berbeda untuk radial-gradient. Tapi, siapa yang peduli dengan IE saat ini? (edit: metode ini berfungsi tanpa masalah di Internet Explorer 11)