Tipografi Responsif Cairan Dengan Ukuran Cairan Poli CSS

Diterbitkan: 2022-03-10
Ringkasan cepat Tata letak yang lancar telah menjadi bagian normal dari pengembangan front-end selama bertahun-tahun. Ide tipografi cair, bagaimanapun, relatif baru dan belum sepenuhnya dieksplorasi. Sampai sekarang, ide kebanyakan pengembang tentang tipografi cair hanya menggunakan unit Viewport mungkin dengan beberapa ukuran minimum dan maksimum. Pada artikel ini, kita akan membawanya ke level lain. Kami akan memeriksa cara membuat tipografi yang dapat diskalakan dan lancar di beberapa titik henti sementara dan ukuran font yang telah ditentukan sebelumnya menggunakan fitur browser yang didukung dengan baik dan beberapa aljabar dasar. Bagian terbaiknya adalah Anda dapat mengotomatiskan semuanya dengan menggunakan Sass.

Pada artikel ini, kita akan membawanya ke level lain. Kami akan memeriksa cara membuat tipografi yang dapat diskalakan dan lancar di beberapa titik henti sementara dan ukuran font yang telah ditentukan sebelumnya menggunakan fitur browser yang didukung dengan baik dan beberapa aljabar dasar. Bagian terbaiknya adalah Anda dapat mengotomatiskan semuanya dengan menggunakan Sass.

Bacaan Lebih Lanjut tentang SmashingMag:

  • Tipografi yang Benar-Benar Cair Dengan Unit vh Dan vw
  • Pola Tipografi Dalam Desain Buletin Email HTML
  • Contoh Tipografi Web Yang Baik, Buruk, dan Hebat
  • Alat Dan Sumber Daya Untuk Tipografi Web yang Lebih Berarti

Saat bekerja dengan desainer kreatif pada desain halaman web, cukup umum untuk menerima beberapa artboard/tata letak Sketch atau Photoshop, satu untuk setiap breakpoint. Dalam desain itu, elemen (seperti heading h1 ) biasanya akan memiliki ukuran yang berbeda di setiap breakpoint. Sebagai contoh:

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini
  1. h1 pada tata letak kecil bisa menjadi 22px
  2. h1 pada tata letak sedang bisa menjadi 24px
  3. h1 pada tata letak besar bisa menjadi 34px

CSS minimum untuk ini menggunakan kueri media:

 h1 { font-size: 22px; } @media (min-width:576px) { h1 { font-size: 22px; } } @media (min-width:768px) { h1 { font-size: 24px; } } @media (min-width:992px) { h1 { font-size: 34px; } }

Ini adalah langkah pertama yang baik, tetapi Anda membatasi font-size hanya pada apa yang ditentukan oleh desainer pada titik henti sementara yang disediakan. Apa yang akan dikatakan desainer jika Anda bertanya, “Berapa font-size pada viewport lebar 850px?” Jawabannya dalam banyak kasus adalah bahwa itu akan berada di antara 24px dan 34px. Namun saat ini, ukurannya hanya 24px menurut CSS Anda, yang mungkin tidak seperti yang dibayangkan oleh perancang.

Pilihan Anda saat ini adalah menghitung ukuran yang seharusnya dan menambahkan breakpoint lain. Itu cukup mudah. Tapi bagaimana dengan semua resolusi lainnya? Berapa font-size pada lebar 800px? Bagaimana dengan 900px? Bagaimana dengan 935px? Jelas perancang tidak akan memberi Anda tata letak penuh untuk setiap kemungkinan resolusi. Bahkan jika ya, haruskah Anda menambahkan lusinan (atau ratusan) titik henti sementara untuk semua font-sizes berbeda yang diinginkan oleh perancang? Tentu saja tidak.

Tata letak Anda sudah diskalakan dengan lancar dengan lebar viewport Anda. Bukankah lebih baik jika tipografi Anda dapat diprediksi diskalakan dengan tata letak cairan Anda? Apa lagi yang bisa kita lakukan untuk memperbaiki ini?

Unit Viewport Untuk Menyelamatkan?

Unit viewport adalah langkah lain ke arah yang benar. Mereka memungkinkan teks Anda untuk mengubah ukuran dengan lancar dengan tata letak Anda. Dan dukungan browser sangat bagus akhir-akhir ini.

Bisakah Saya Menggunakan Area Pandang?
(Lihat versi besar)

Tetapi kelangsungan hidup unit Viewport sangat bergantung pada desain kreatif asli untuk halaman web. Akan sangat bagus untuk mengatur font-size Anda menggunakan vw dan selesai:

 h1 { font-size: 2vw; } 

Tetapi ini hanya berfungsi jika papan seni kreatif Anda memperhitungkannya. Apakah perancang memilih ukuran teks yang tepat 2% dari lebar masing-masing papan seninya? Tentu saja tidak. Mari kita hitung berapa nilai vw yang dibutuhkan untuk setiap breakpoint kita:

Ukuran 22px @ lebar 576px = 22 576 *100 = 3.82vw Ukuran 24px @ lebar 768px = 24 768 *100 = 3.13vw Ukuran 34px @ lebar 992px = 34 992 *100 = 3.43vw

Mereka dekat tapi tidak semuanya sama. Jadi, Anda masih perlu menggunakan kueri media untuk transisi antara ukuran teks dan masih akan ada lompatan. Dan pertimbangkan efek samping yang aneh ini:

@ 767px, 3,82% dari lebar viewport adalah 29px. Jika area pandang lebih lebar 1 piksel, font-size tiba turun kembali ke 24 piksel . Animasi area pandang yang diubah ukurannya ini menunjukkan efek samping yang tidak diinginkan ini:

Perubahan dramatis dalam ukuran font ini hampir pasti tidak seperti yang dibayangkan oleh sang desainer. Jadi bagaimana kita memecahkan masalah ini?

Regresi Linier Statistik?

Tunggu. Apa? Ya, ini adalah artikel tentang CSS, tetapi beberapa matematika dasar dapat memberikan solusi yang elegan untuk masalah kita.

Pertama, mari kita plot resolusi kita dan ukuran teks yang sesuai pada grafik:

Plot sebar ukuran font dan lebar Viewport yang sesuai
Plot sebar font-size dan lebar Viewport yang sesuai (Google Spreadsheets) (Lihat versi besar)

Di sini Anda dapat melihat sebar plot ukuran teks yang ditentukan desainer pada lebar viewport yang ditentukan. Sumbu x adalah lebar viewport dan sumbu y adalah font-size . Lihat garis itu? Itu disebut garis tren . Ini adalah cara untuk menemukan nilai font-size yang diinterpolasi untuk lebar area pandang apa pun, berdasarkan data yang diberikan.

Garis Tren Adalah Kunci Dari Semua Ini

Jika Anda dapat mengatur font-size Anda sesuai dengan garis tren ini, Anda akan memiliki h1 yang dengan mulus menskalakan semua resolusi yang akan mendekati pencocokan apa yang dimaksudkan oleh perancang. Pertama, mari kita lihat matematikanya. Garis lurus didefinisikan oleh persamaan ini:

Definisi persamaan linear
Definisi persamaan linear
  • m = kemiringan
  • b = perpotongan y
  • x = lebar viewport saat ini
  • y = font-size yang dihasilkan

Ada beberapa metode untuk menentukan kemiringan dan perpotongan y. Ketika beberapa nilai terlibat, metode yang umum adalah kecocokan Kuadrat Terkecil:

kuadrat terkecil

Setelah Anda menjalankan perhitungan tersebut, Anda memiliki persamaan garis tren.

Bagaimana Saya Menggunakan Ini Di CSS?

Oke, ini menjadi cukup berat pada matematika. Bagaimana kita benar-benar menggunakan hal ini dalam pengembangan web front-end? Jawabannya adalah CSS calc() ! Sekali lagi, teknologi CSS yang cukup baru didukung dengan sangat baik.

Bisakah Saya Menggunakan Calc?
(Lihat versi besar)

Anda dapat menggunakan persamaan garis tren seperti ini:

 h1 { font-size: calc({slope}*100vw + {y-intercept}px); }

Setelah Anda menemukan kemiringan Anda dan y-intercept, Anda cukup mencolokkannya!

Catatan: Anda harus mengalikan kemiringan dengan 100 karena Anda menggunakannya sebagai unit vw yang merupakan 1/100 lebar Viewport.

Bisakah Ini Menjadi Otomatis?

Saya mem-porting metode kuadrat terkecil ke dalam fungsi Sass yang mudah digunakan:

 /// least-squares-fit /// Calculate the least square fit linear regression of provided values /// @param {map} $map - A Sass map of viewport width and size value combinations /// @return Linear equation as a calc() function /// @example /// font-size: least-squares-fit((576px: 24px, 768px: 24px, 992px: 34px)); /// @author Jake Wilson <[email protected]> @function least-squares-fit($map) { // Get the number of provided breakpoints $length: length(map-keys($map)); // Error if the number of breakpoints is < 2 @if ($length < 2) { @error "leastSquaresFit() $map must be at least 2 values" } // Calculate the Means $resTotal: 0; $valueTotal: 0; @each $res, $value in $map { $resTotal: $resTotal + $res; $valueTotal: $valueTotal + $value; } $resMean: $resTotal/$length; $valueMean: $valueTotal/$length; // Calculate some other stuff $multipliedDiff: 0; $squaredDiff: 0; @each $res, $value in $map { // Differences from means $resDiff: $res - $resMean; $valueDiff: $value - $valueMean; // Sum of multiplied differences $multipliedDiff: $multipliedDiff + ($resDiff * $valueDiff); // Sum of squared resolution differences $squaredDiff: $squaredDiff + ($resDiff * $resDiff); } // Calculate the Slope $m: $multipliedDiff / $squaredDiff; // Calculate the Y-Intercept $b: $valueMean - ($m * $resMean); // Return the CSS calc equation @return calc(#{$m*100}vw + #{$b}); }

Apakah ini benar-benar berfungsi? Buka CodePen ini dan ubah ukuran jendela browser Anda. Berhasil! Ukuran font cukup dekat dengan apa yang diminta oleh desain aslinya dan ukurannya sesuai dengan tata letak Anda.

Least Squares Fit SCSS test user="jakobud"]Lihat tes SCSS Pena Least Squares Fit oleh Jake Wilson (@jakobud) di CodePen.

Least Squares Fit SCSS test user=“jakobud”]Lihat tes SCSS Pen Least Squares Fit oleh Jake Wilson (@jakobud) di CodePen.

Sekarang, harus diakui, itu tidak sempurna. Nilainya mendekati desain aslinya tetapi tidak sesuai. Ini karena garis tren linier adalah perkiraan ukuran font tertentu pada lebar area pandang tertentu. Ini adalah pewarisan dari regresi linier. Selalu ada beberapa kesalahan dalam hasil Anda. Ini adalah trade-off dari kesederhanaan vs akurasi. Juga, perlu diingat, semakin bervariasi ukuran teks Anda, semakin banyak kesalahan yang akan terjadi di garis tren Anda.

Bisakah kita melakukan lebih baik dari ini?

Kuadrat Terkecil Polinomial Sesuai

Untuk mendapatkan garis tren yang lebih akurat, Anda perlu melihat topik yang lebih maju, seperti garis tren regresi polinomial yang mungkin terlihat seperti ini:

Garis tren regresi polinomial
Garis tren regresi polinomial (Google Spreadsheets) (Lihat versi besar)

Sekarang lebih seperti itu ! Jauh lebih akurat daripada garis lurus kita. Persamaan regresi polinomial dasar terlihat seperti ini:

Persamaan polinomial derajat 3
Persamaan polinomial derajat 3

Semakin akurat kurva yang Anda inginkan, semakin rumit persamaannya. Sayangnya, Anda tidak dapat melakukan ini di CSS . calc() tidak bisa melakukan jenis matematika tingkat lanjut ini. Secara khusus, Anda tidak dapat menghitung eksponen:

 font-size: calc(3vw * 3vw); /* This doesn't work in CSS */

Jadi sampai calc() mendukung jenis matematika non-linier ini, kita terjebak dengan persamaan linier saja . Apakah ada hal lain yang bisa kita lakukan untuk memperbaiki ini?

Breakpoints Dan Beberapa Persamaan Linear

Bagaimana jika kita hanya menghitung garis lurus di antara setiap pasangan titik putus? Sesuatu seperti ini:

Garis tren Regresi Linier antara beberapa pasangan nilai
Garis tren Regresi Linier antara beberapa pasangan nilai (Google Spreadsheets) (Lihat versi besar)

Jadi dalam contoh ini kita akan menghitung garis lurus antara 22px dan 24px dan kemudian antara 24px dan 34px . Sass akan terlihat seperti ini:

 // SCSS h1 { @media (min-width:576px) { font-size: calc(???); } @media (min-width:768px) { font-size: calc(???); } }

Kita dapat menggunakan metode kuadrat terkecil yang sesuai untuk nilai calc() tersebut, tetapi karena hanya berupa garis lurus antara 2 titik, perhitungannya dapat sangat disederhanakan. Ingat persamaan garis lurus?

Definisi persamaan linear
Definisi persamaan linear

Karena kita berbicara tentang hanya 2 titik sekarang, menemukan kemiringan (m) dan perpotongan y (b) adalah sepele:

Menemukan kemiringan dan perpotongan y dari persamaan linier
Menemukan kemiringan dan perpotongan y dari persamaan linier

Berikut adalah fungsi Sass untuk ini:

 /// linear-interpolation /// Calculate the definition of a line between two points /// @param $map - A Sass map of viewport widths and size value pairs /// @returns A linear equation as a calc() function /// @example /// font-size: linear-interpolation((320px: 18px, 768px: 26px)); /// @author Jake Wilson <[email protected]> @function linear-interpolation($map) { $keys: map-keys($map); @if (length($keys) != 2) { @error "linear-interpolation() $map must be exactly 2 values"; } // The slope $m: (map-get($map, nth($keys, 2)) - map-get($map, nth($keys, 1)))/(nth($keys, 2) - nth($keys,1)); // The y-intercept $b: map-get($map, nth($keys, 1)) - $m * nth($keys, 1); // Determine if the sign should be positive or negative $sign: "+"; @if ($b < 0) { $sign: "-"; $b: abs($b); } @return calc(#{$m*100}vw #{$sign} #{$b}); }

Sekarang, cukup gunakan fungsi interpolasi linier pada beberapa breakpoint di Sass Anda. Juga, mari masukkan beberapa font-sizes min dan maks :

 // SCSS h1 { // Minimum font-size font-size: 22px; // Font-size between 576 - 768 @media (min-width:576px) { $map: (576px: 22px, 768px: 24px); font-size: linear-interpolation($map); } // Font-size between 768 - 992 @media (min-width:768px) { $map: (768px: 24px, 992px: 34px); font-size: linear-interpolation($map); } // Maximum font-size @media (min-width:992px) { font-size: 34px; } }

Dan itu menghasilkan CSS ini:

 h1 { font-size: 22px; } @media (min-width: 576px) { h1 { font-size: calc(1.04166667vw + 16px); } } @media (min-width: 768px) { h1 { font-size: calc(4.46428571vw - 10.28571429px); } } @media (min-width: 992px) { h1 { font-size: 34px; } } 

Cawan Suci Ukuran CSS?

Mari kita selesaikan ini semua dalam mixin Sass yang bagus (untuk yang malas dan efisien!). Saya menciptakan metode ini Poly Fluid Sizing :

 /// poly-fluid-sizing /// Generate linear interpolated size values through multiple break points /// @param $property - A string CSS property name /// @param $map - A Sass map of viewport unit and size value pairs /// @requires function linear-interpolation /// @requires function map-sort /// @example /// @include poly-fluid-sizing('font-size', (576px: 22px, 768px: 24px, 992px: 34px)); /// @author Jake Wilson <[email protected]> @mixin poly-fluid-sizing($property, $map) { // Get the number of provided breakpoints $length: length(map-keys($map)); // Error if the number of breakpoints is < 2 @if ($length < 2) { @error "poly-fluid-sizing() $map requires at least values" } // Sort the map by viewport width (key) $map: map-sort($map); $keys: map-keys($map); // Minimum size #{$property}: map-get($map, nth($keys,1)); // Interpolated size through breakpoints @for $i from 1 through ($length - 1) { @media (min-width:nth($keys,$i)) { $value1: map-get($map, nth($keys,$i)); $value2: map-get($map, nth($keys,($i + 1))); // If values are not equal, perform linear interpolation @if ($value1 != $value2) { #{$property}: linear-interpolation((nth($keys,$i): $value1, nth($keys,($i+1)): $value2)); } @else { #{$property}: $value1; } } } // Maxmimum size @media (min-width:nth($keys,$length)) { #{$property}: map-get($map, nth($keys,$length)); } }

Mixin Sass ini memerlukan beberapa fungsi Sass dalam inti Github berikut:

  • linear-interpolasi
  • pengurutan peta
  • pengurutan daftar
  • hapus daftar

Mixin poly-fluid-sizing() akan melakukan interpolasi linier pada setiap pasangan lebar viewport dan menetapkan ukuran minimum dan maksimum. Anda dapat mengimpor ini ke proyek Sass apa pun dan menggunakannya dengan mudah tanpa perlu mengetahui matematika apa pun di baliknya. Berikut adalah CodePen terakhir yang menggunakan metode ini.

Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc() user="jakobud"]Lihat Pen Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc()"] Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc() oleh Jake Wilson (@jakobud) di CodePen.

Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc() user=“jakobud”]Lihat Pen Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc()“] Poly Fluid Sizing menggunakan persamaan linier, unit viewport dan calc() oleh Jake Wilson (@jakobud) di CodePen.

Beberapa Catatan

  • Jelas metode ini tidak hanya berlaku untuk font-size tetapi untuk properti unit/panjang apa pun ( margin , padding , dll). Anda meneruskan nama properti yang diinginkan ke dalam mixin sebagai string.
  • Peta Sass dari pasangan nilai lebar + ukuran viewport dapat diteruskan dalam urutan apa pun ke dalam mixin poly-fluid-sizing() . Ini akan secara otomatis mengurutkan peta menurut lebar Viewport dari terendah ke tertinggi . Jadi Anda bisa melewati peta seperti ini dan itu akan berhasil dengan baik:
 $map: (576px: 22px, 320px: 18px, 992px: 34px, 768px: 24px); @include poly-fluid-sizing('font-size', $map);
  • Batasan untuk metode ini adalah Anda tidak dapat memasukkan unit campuran ke dalam mixin. Misalnya, lebar 3em @ 576px . Sass tidak akan benar-benar tahu apa yang harus dilakukan secara matematis di sana.

Kesimpulan

Apakah ini yang terbaik yang bisa kita lakukan? Apakah Ukuran Cairan Poli adalah Cawan Suci dari ukuran unit cairan dalam CSS? Mungkin. CSS saat ini mendukung animasi non-linear dan fungsi waktu transisi, jadi mungkin ada kemungkinan bahwa calc() juga akan mendukungnya suatu hari nanti. Jika itu terjadi, regresi polinomial non-linier mungkin layak untuk dilihat lagi. Tapi mungkin tidak… Penskalaan linier mungkin lebih unggul.

Saya mulai mengeksplorasi ide ini pada awal 2017 dan akhirnya mengembangkan solusi di atas. Sejak itu, saya telah melihat beberapa pengembang datang dengan ide-ide serupa dan potongan-potongan berbeda dari teka-teki ini. Saya pikir sudah waktunya bagi saya untuk membagikan metode saya dan bagaimana saya sampai di sana. Unit area pandang. Kal(). Kelancangan. Breakpoint. Tak satu pun dari hal-hal ini baru. Semuanya adalah fitur browser yang telah ada selama bertahun-tahun (dengan berbagai tingkat dukungan). Saya hanya menggunakannya bersama dengan cara yang belum sepenuhnya dieksplorasi. Jangan pernah takut untuk melihat alat yang Anda gunakan setiap hari dan berpikir out-of-the-box tentang bagaimana Anda dapat menggunakannya dengan lebih baik dan mengembangkan keahlian Anda.