Buat Efek Gambar Responsif Dengan Gradien CSS Dan rasio aspek

Diterbitkan: 2022-03-10
Ringkasan cepat Masalah klasik dalam CSS adalah mempertahankan rasio aspek gambar di seluruh komponen terkait, seperti kartu. Properti aspect-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:

Satu kartu dengan gaya dasar yang dijelaskan sebelumnya diterapkan dan termasuk gambar dari Unsplash dari makanan penutup di piring kecil di sebelah minuman panas di cangkir
Satu kartu dengan gaya dasar yang dijelaskan sebelumnya diterapkan dan termasuk gambar dari Unsplash dari makanan penutup di piring kecil di sebelah minuman panas di cangkir. (Pratinjau besar)

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:

Tiga kartu ditampilkan secara berurutan karena gaya tata letak pembungkus kartu yang diterapkan. Setiap kartu memiliki gambar unik yang memiliki rasio aspek alami yang berbeda, dengan kartu terakhir memiliki gambar berorientasi vertikal yang lebih dari dua kali tinggi gambar kartu lainnya
Tiga kartu ditampilkan secara berurutan karena gaya tata letak pembungkus kartu yang diterapkan. Setiap kartu memiliki gambar unik yang memiliki rasio aspek alami yang berbeda, dengan kartu terakhir memiliki gambar berorientasi vertikal yang lebih dari dua kali tinggi gambar kartu lainnya. (Pratinjau besar)

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.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

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:

Gambar tiga kartu sekarang tampak memiliki ketinggian yang seragam dan konten gambar dipusatkan di dalam gambar seolah-olah itu adalah sebuah wadah
Gambar tiga kartu sekarang tampak memiliki ketinggian yang seragam dan konten gambar dipusatkan di dalam gambar seolah-olah itu adalah sebuah wadah. (Pratinjau besar)

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.

Gambar tiga kartu memiliki dimensi lebar dan tinggi yang identik, yang sedikit berbeda dari solusi kesesuaian objek sebelumnya
Gambar tiga kartu memiliki dimensi lebar dan tinggi yang identik, yang sedikit berbeda dari solusi kesesuaian objek sebelumnya. (Pratinjau besar)

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:

Setiap gambar kartu memiliki efek pencampuran gradien yang dimulai dengan warna biru muda di bagian atas, yang menyatu menjadi merah muda kemerahan, dan kemudian diakhiri dengan bulu menjadi putih sebelum konten teks kartu lainnya.
Setiap gambar kartu memiliki efek pencampuran gradien yang dimulai dengan biru muda di bagian atas, yang berpadu menjadi merah muda kemerahan, dan kemudian diakhiri dengan bulu menjadi putih sebelum konten teks kartu lainnya. (Pratinjau besar)

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:

Setiap gambar kartu memiliki warna oranye yang kuat dari gradien baru yang dimulai dari merah-oranye menjadi oranye murni. Area putih tetap putih dan area hitam tetap hitam
Setiap gambar kartu memiliki warna oranye yang kuat dari gradien baru yang dimulai dari merah-oranye menjadi oranye murni. Area putih tetap putih dan area hitam tetap hitam. (Pratinjau besar)

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 :

Sekarang setiap gambar kartu masih memiliki gradien oranye tetapi semua warna lain dihapus dan diganti dengan nuansa abu-abu
Sekarang setiap gambar kartu masih memiliki gradien oranye tetapi semua warna lain dihapus dan diganti dengan nuansa abu-abu. (Pratinjau besar)

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:

Tinggi gambar kartu dibatasi, tetapi setiap kartu memiliki ketinggian realisasi yang sedikit berbeda
Tinggi gambar kartu dibatasi, tetapi setiap kartu memiliki ketinggian realisasi yang sedikit berbeda. (Pratinjau besar)

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:

Lihat Pena [Efek Gambar Responsif dengan Gradien CSS dan rasio aspek](https://codepen.io/smashingmag/pen/WNoERXo) oleh Stephanie Eckles.

Lihat Efek Gambar Responsif Pena dengan Gradien CSS dan rasio aspek oleh Stephanie Eckles.

Mencari lebih? Pastikan Anda melihat Panduan CSS kami di sini di Smashing →