Buat Efek Gambar Responsif Dengan Gradien CSS Dan rasio aspek
Diterbitkan: 2022-03-10aspect-ratio
baru didukung dalam kombinasi dengan object-fit
memberikan obat untuk sakit kepala di masa lalu ini! Mari belajar menggunakan properti ini, selain menciptakan efek gambar gradien responsif untuk bakat ekstra.Untuk mempersiapkan efek gambar kami di masa mendatang, kami akan menyiapkan komponen kartu yang memiliki gambar besar di bagian atas diikuti dengan judul dan deskripsi. Masalah umum dengan pengaturan ini adalah bahwa kita mungkin tidak selalu memiliki kontrol yang sempurna atas apa itu gambar, dan yang lebih penting untuk tata letak kita, apa dimensinya . Dan sementara ini dapat diselesaikan dengan memotong sebelumnya, kami masih dapat mengalami masalah karena wadah berukuran responsif. Akibatnya adalah posisi isi kartu yang tidak merata yang benar-benar menonjol saat Anda menyajikan deretan kartu.
Solusi lain sebelumnya selain memotong mungkin adalah menukar dari img
sebaris ke div
kosong yang hanya ada untuk menyajikan gambar melalui background-image
. Saya telah menerapkan solusi ini berkali-kali di masa lalu. Satu keuntungan yang dimilikinya adalah menggunakan trik lama untuk rasio aspek yang menggunakan elemen ketinggian nol dan menetapkan nilai padding-bottom
. Menetapkan nilai padding sebagai persen menghasilkan nilai akhir yang dihitung yang relatif terhadap lebar elemen. Anda mungkin juga menggunakan ide ini untuk mempertahankan rasio 16:9 untuk penyematan video, dalam hal ini nilai padding ditemukan dengan rumus: 9/16 = 0.5625 * 100% = 56.26%
. Tapi kita akan menjelajahi dua properti CSS modern yang tidak melibatkan matematika ekstra, memberi kita lebih banyak fleksibilitas, dan juga memungkinkan menjaga semantik yang disediakan dengan menggunakan img
asli alih-alih div
kosong.
Pertama, mari kita definisikan semantik HTML, termasuk penggunaan unordered list sebagai wadah kartu:
<ul class="card-wrapper"> <li class="card"> <img src="" alt=""> <h3>A Super Wonderful Headline</h3> <p>Lorem ipsum sit dolor amit</p> </li> <!-- additional cards --> </ul>
Selanjutnya, kita akan membuat satu set minimal gaya dasar untuk komponen .card
. Kami akan mengatur beberapa gaya visual dasar untuk kartu itu sendiri, pembaruan cepat untuk judul h3
yang diharapkan, kemudian gaya penting untuk mulai menata gambar kartu.
.card { background-color: #fff; border-radius: 0.5rem; box-shadow: 0.05rem 0.1rem 0.3rem -0.03rem rgba(0, 0, 0, 0.45); padding-bottom: 1rem; } .card > :last-child { margin-bottom: 0; } .card h3 { margin-top: 1rem; font-size: 1.25rem; } img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; } img ~ * { margin-left: 1rem; margin-right: 1rem; }
Aturan terakhir menggunakan kombinator saudara umum untuk menambahkan margin horizontal ke elemen apa pun yang mengikuti img
karena kami ingin gambar itu sendiri rata dengan sisi kartu.
Dan kemajuan kami sejauh ini membawa kami ke tampilan kartu berikut:
Terakhir, kita akan membuat gaya .card-wrapper
untuk tata letak responsif cepat menggunakan kisi CSS. Ini juga akan menghapus gaya daftar default.
.card-wrapper { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(30ch, 1fr)); grid-gap: 1.5rem; }
Catatan : Jika teknik grid ini asing bagi Anda, tinjau penjelasan dalam tutorial saya tentang solusi modern untuk grid 12 kolom.
Dengan ini diterapkan dan dengan semua kartu yang berisi gambar dengan jalur sumber yang valid, gaya .card-wrapper
kami memberi kami tata letak berikut:
Seperti yang ditunjukkan pada gambar pratinjau, gaya dasar ini tidak cukup untuk memuat gambar dengan benar mengingat dimensi alaminya yang bervariasi. Kami membutuhkan metode untuk membatasi gambar-gambar ini secara seragam dan konsisten.
Aktifkan Ukuran Gambar Seragam dengan object-fit
Seperti disebutkan sebelumnya, Anda mungkin sebelumnya telah membuat pembaruan dalam skenario ini untuk mengubah gambar yang akan ditambahkan melalui background-image
dan menggunakan background-size: cover
untuk menangani pengubahan ukuran gambar dengan baik. Atau Anda mungkin telah mencoba menerapkan pemotongan sebelumnya (masih merupakan tujuan yang layak karena pengurangan ukuran gambar apa pun akan meningkatkan kinerja!).
Sekarang, kami memiliki properti object-fit
yang memungkinkan tag img
bertindak sebagai wadah untuk gambar. Dan, itu datang dengan nilai cover
juga yang menghasilkan efek yang sama seperti solusi gambar latar belakang, tetapi dengan bonus mempertahankan semantik gambar sebaris. Mari kita terapkan dan lihat cara kerjanya.
Kita memang perlu memasangkannya dengan dimensi height
untuk panduan tambahan tentang bagaimana kita ingin wadah gambar berperilaku (ingat kita telah menambahkan width: 100%
). Dan kita akan menggunakan fungsi max()
untuk memilih 10rem
atau 30vh
tergantung mana yang lebih besar dalam konteks tertentu, yang mencegah ketinggian gambar menyusut terlalu banyak pada area pandang yang lebih kecil atau ketika pengguna telah menyetel zoom besar.
img { /* ...existing styles */ object-fit: cover; height: max(10rem, 30vh); }
Tip Aksesibilitas Bonus : Anda harus selalu menguji tata letak Anda dengan zoom 200% dan 400% di desktop. Meskipun saat ini tidak ada kueri media zoom
, fungsi seperti max()
dapat membantu menyelesaikan masalah tata letak. Konteks lain yang berguna dari teknik ini adalah jarak antar elemen.
Dengan pembaruan ini, kami benar-benar meningkatkan banyak hal, dan hasil visualnya seolah-olah kami menggunakan teknik gambar latar yang lebih lama:
Ukuran Gambar yang Konsisten Secara Responsif Dengan aspect-ratio
Saat menggunakan object-fit
dengan sendirinya, satu kelemahannya adalah kita masih perlu mengatur beberapa petunjuk dimensi.
Properti yang akan datang (saat ini tersedia di browser Chromium) aspect-ratio
akan meningkatkan kemampuan kami untuk mengukur gambar secara konsisten.
Dengan menggunakan properti ini, kita dapat menentukan rasio untuk mengubah ukuran gambar alih-alih menyetel dimensi eksplisit. Kami akan terus menggunakannya dalam kombinasi dengan object-fit
untuk memastikan dimensi ini hanya memengaruhi gambar sebagai wadah, jika tidak, gambar dapat tampak terdistorsi.
Berikut adalah aturan gambar terbaru kami:
img { border-radius: 0.5rem 0.5rem 0 0; width: 100%; object-fit: cover; aspect-ratio: 4/3; }
Kami akan mulai dengan rasio gambar 4 3 untuk konteks kartu kami, tetapi Anda dapat memilih rasio apa pun. Misalnya, 1 1 untuk persegi, atau 16 9 untuk penyematan video standar.
Berikut adalah kartu yang diperbarui, meskipun mungkin akan sulit untuk melihat perbedaan visual dalam contoh khusus ini karena rasio aspek sangat cocok dengan penampilan yang kami capai dengan menyetel height
untuk object-fit
saja.
Menyetel `aspect-ratio` menghasilkan rasio yang dipertahankan saat elemen tumbuh atau menyusut, sedangkan jika hanya menyetel `object-fit` dan `height`, rasio gambar akan terus berubah seiring perubahan dimensi container.
“
Menambahkan Efek Responsif Dengan Gradien dan Fungsi CSS
Oke, sekarang setelah kita tahu cara mengatur gambar berukuran konsisten, mari bersenang-senang dengannya dengan menambahkan efek gradien!
Tujuan kami dengan efek ini adalah membuatnya tampak seolah-olah gambar memudar ke dalam konten kartu. Anda mungkin tergoda untuk membungkus gambar dalam wadahnya sendiri untuk menambahkan gradien, tetapi berkat pekerjaan yang telah kami lakukan pada ukuran gambar, kami dapat mengetahui cara melakukannya dengan aman di .card
utama.
Langkah pertama adalah mendefinisikan gradien . Kita akan menggunakan properti kustom CSS untuk menambahkan warna gradien agar mudah menukar efek gradien, dimulai dengan biru hingga merah muda. Warna terakhir dalam gradien akan selalu putih untuk mempertahankan transisi ke latar belakang konten kartu dan membuat tepi "berbulu".
.card { --card-gradient: #5E9AD9, #E271AD; background-image: linear-gradient( var(--card-gradient), white max(9.5rem, 27vh) ); /* ...existing styles */ }
Tapi tunggu — apakah itu fungsi CSS max()
? Dalam gradien? Ya, itu mungkin, dan keajaibanlah yang membuat gradien ini efektif secara responsif!
Namun, jika saya menambahkan tangkapan layar, kami sebenarnya belum melihat gradien memiliki efek apa pun pada gambar. Untuk itu, kita perlu memasukkan properti mix-blend-mode
, dan dalam skenario ini kita akan menggunakan nilai overlay
:
img { /* ...existing styles */ mix-blend-mode: overlay; }
Properti mix-blend-mode
mirip dengan menerapkan gaya pencampuran lapisan yang tersedia dalam perangkat lunak manipulasi foto seperti Photoshop. Dan nilai overlay
akan memiliki efek memungkinkan nada medium pada gambar untuk berbaur dengan gradien di belakangnya, yang mengarah ke hasil berikut:
Sekarang, pada titik ini, kami mengandalkan nilai aspect-ratio
saja untuk mengubah ukuran gambar. Dan jika kita mengubah ukuran wadah dan menyebabkan tata letak kartu berubah, ketinggian gambar yang berubah menyebabkan inkonsistensi di mana gradien memudar menjadi putih.
Jadi kita juga akan menambahkan properti max-height
yang juga menggunakan fungsi max()
dan berisi nilai yang sedikit lebih besar daripada yang ada di gradien. Perilaku yang dihasilkan adalah bahwa gradien akan (hampir selalu) sejajar dengan bagian bawah gambar.
img { /* ...existing styles */ max-height: max(10rem, 30vh); }
Penting untuk diperhatikan bahwa menambahkan `max-height` akan mengubah perilaku `aspect-ratio`. Alih-alih selalu menggunakan rasio yang tepat, rasio ini hanya akan digunakan jika ada cukup ruang yang dialokasikan dengan batasan tambahan baru `max-height`.
“
Namun, aspect-ratio
masih akan terus memastikan gambar diubah ukurannya secara konsisten seperti manfaatnya dibandingkan hanya object-fit
. Coba komentari aspect-ratio
di demo CodePen terakhir untuk melihat perbedaannya di seluruh ukuran wadah.
Karena tujuan awal kami adalah mengaktifkan dimensi gambar yang responsif secara konsisten , kami masih mencapai sasaran. Untuk kasus penggunaan Anda sendiri, Anda mungkin perlu mengutak-atik rasio dan nilai tinggi untuk mencapai efek yang Anda inginkan.
Alternatif: mix-blend-mode
Dan Menambahkan Filter
Menggunakan overlay
sebagai nilai mix-blend-mode
adalah pilihan terbaik untuk efek fade-to-white yang kita cari, tetapi mari kita coba opsi alternatif untuk efek yang lebih dramatis.
Kami akan memperbarui solusi kami untuk menambahkan properti kustom CSS untuk nilai mix-blend-mode
dan juga memperbarui nilai warna untuk gradien:
.card { --card-gradient: tomato, orange; --card-blend-mode: multiply; } img { /* ...existing styles */ mix-blend-mode: var(--card-blend-mode); }
Nilai multiply
memiliki efek penggelapan pada nada tengah, tetapi tetap putih dan hitam apa adanya, menghasilkan tampilan berikut:
Sementara kami telah kehilangan fade dan sekarang memiliki tepi yang keras di bagian bawah gambar, bagian putih dari gradien kami masih penting untuk memastikan bahwa gradien berakhir sebelum konten kartu.
Satu modifikasi tambahan yang dapat kita tambahkan adalah penggunaan filter
dan, khususnya, menggunakan fungsi skala abu- grayscale()
untuk menghapus warna gambar dan oleh karena itu menjadikan gradien sebagai satu-satunya sumber pewarnaan gambar.
img { /* ...existing styles */ filter: grayscale(100); }
Menggunakan nilai skala abu- grayscale(100)
menghasilkan penghapusan lengkap warna alami gambar dan mengubahnya menjadi hitam putih. Berikut update untuk perbandingan dengan screenshot sebelumnya dari efeknya saat menggunakan gradien oranye kami dengan multiply
:
Gunakan aspect-ratio
Sebagai Peningkatan Progresif
Seperti yang disebutkan sebelumnya, aspect-ratio
saat ini hanya didukung di browser Chromium versi terbaru (Chrome dan Edge). Namun, semua browser mendukung object-fit
dan bersama dengan batasan height
kami menghasilkan hasil yang kurang ideal tetapi masih dapat diterima, terlihat di sini untuk Safari:
Tanpa fungsi aspect-ratio
, hasilnya di sini adalah bahwa pada akhirnya tinggi gambar dibatasi tetapi dimensi alami dari setiap gambar masih menyebabkan beberapa perbedaan antara ketinggian gambar kartu. Anda mungkin ingin mengubah untuk menambahkan max-height
atau menggunakan fungsi max()
lagi untuk membantu membuat max-height
lebih responsif di berbagai ukuran kartu.
Memperluas Efek Gradien
Karena kami mendefinisikan perhentian warna gradien sebagai properti kustom CSS, kami memiliki akses siap untuk mengubahnya dalam konteks yang berbeda. Misalnya, kita mungkin mengubah gradien untuk lebih menonjolkan salah satu warna jika kartu dilayangkan atau memiliki salah satu anaknya dalam fokus.
Pertama, kami akan memperbarui setiap kartu h3
untuk memuat tautan, seperti:
<h3><a href="">A Super Wonderful Headline</a></h3>
Kemudian, kita dapat menggunakan salah satu selektor terbaru yang tersedia — :focus-within
— untuk mengubah gradien kartu saat tautan dalam fokus. Untuk cakupan ekstra dari kemungkinan interaksi, kami akan memasangkan ini dengan :hover
. Dan, kami akan menggunakan kembali ide max()
kami untuk menetapkan satu warna untuk mengambil alih cakupan bagian gambar kartu. Kelemahan dari efek khusus ini adalah bahwa gradien berhenti dan perubahan warna tidak dapat dianimasikan dengan andal — tetapi akan segera terjadi berkat CSS Houdini.
Untuk memperbarui warna dan menambahkan perhentian warna baru, kita hanya perlu menetapkan kembali nilai --card-gradient
dalam aturan baru ini:
.card:focus-within, .card:hover { --card-gradient: #24a9d5 max(8.5rem, 20vh); }
Nilai max()
kami kurang dari aslinya digunakan untuk white
untuk mempertahankan tepi berbulu. Jika kita menggunakan nilai yang sama, itu akan memenuhi white
dan membuat pemisahan garis lurus yang jelas.
Dalam membuat demo ini, saya awalnya mencoba efek yang menggunakan transform
with scale
untuk efek zoom-in. Tetapi saya menemukan bahwa karena mix-blend-mode
yang diterapkan, browser tidak akan secara konsisten mengecat ulang gambar yang menyebabkan kedipan yang tidak menyenangkan. Akan selalu ada kompromi dalam meminta browser melakukan efek dan animasi khusus CSS, dan meskipun sangat keren apa yang bisa kami lakukan, selalu yang terbaik adalah memeriksa dampak kinerja dari efek Anda.
Selamat Bereksperimen!
CSS modern telah memberi kami beberapa alat luar biasa untuk memperbarui perangkat desain web kami, dengan aspect-ratio
sebagai tambahan terbaru. Jadi majulah, dan bereksperimenlah dengan object-fit
, aspect-ratio
, dan tambahkan fungsi seperti max()
ke dalam gradien Anda untuk beberapa efek responsif yang menyenangkan! Pastikan untuk memeriksa ulang hal-hal lintas-browser (untuk saat ini!) Dan di berbagai viewport dan ukuran container.
Berikut adalah CodePen termasuk fitur dan efek yang kami ulas hari ini:
Mencari lebih? Pastikan Anda melihat Panduan CSS kami di sini di Smashing →