CSS Çoklu Akışkan Boyutlandırma ile Akışkan Duyarlı Tipografi
Yayınlanan: 2022-03-10Bu yazıda, onu başka bir seviyeye taşıyacağız. İyi desteklenen tarayıcı özellikleri ve bazı temel cebir kullanarak birden çok kesme noktasında ve önceden tanımlanmış yazı tipi boyutlarında ölçeklenebilir, akıcı tipografinin nasıl oluşturulacağını inceleyeceğiz. En iyi yanı, hepsini Sass kullanarak otomatikleştirebilmenizdir.
SmashingMag'de Daha Fazla Okuma :
- vh ve vw Birimleri ile Gerçekten Akışkan Tipografi
- HTML E-posta Haber Bülteni Tasarımında Tipografik Desenler
- Web Tipografisinin İyi, Kötü ve Harika Örnekleri
- Daha Anlamlı Bir Web Tipografisi İçin Araçlar ve Kaynaklar
Web sayfası tasarımlarında yaratıcı tasarımcılarla çalışırken, her kesme noktası için bir tane olmak üzere birden çok Sketch veya Photoshop çalışma yüzeyi/düzeni almak oldukça yaygındır. Bu tasarımda, öğeler ( h1
başlığı gibi) genellikle her kesme noktasında farklı boyutlarda olacaktır. Örneğin:
- Küçük düzendeki
h1
,22px
olabilir - Orta düzendeki
h1
,24px
olabilir - Büyük düzendeki
h1
,34px
olabilir
Bunun için minimum CSS, medya sorgularını kullanır:
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; } }

Bu iyi bir ilk adımdır, ancak font-size
yalnızca tasarımcı tarafından sağlanan kesme noktalarında belirtilenle sınırlandırıyorsunuz. Tasarımcı, "850 piksel genişliğindeki bir görüntü alanında font-size
ne olmalıdır?" diye sorsanız ne derdi? Çoğu durumda cevap, 24 piksel ile 34 piksel arasında bir yerde olacağıdır. Ama şu anda, CSS'nize göre sadece 24 piksel, muhtemelen tasarımcının öngördüğü bu değildi.
Bu noktada seçeneğiniz, bu boyutun ne olması gerektiğini hesaplamak ve başka bir kesme noktası eklemektir. Bu yeterince kolay. Peki ya diğer tüm kararlar? 800 piksel genişliğinde font-size
ne olmalıdır? 900 piksele ne dersin? 935px'e ne dersin? Açıkçası tasarımcı, olası her çözünürlük için size tam bir düzen sağlamayacaktır. Yapsalar bile, tasarımcı tarafından istenen tüm farklı font-sizes
için düzinelerce (veya yüzlerce) kesme noktası eklemeniz gerekir mi? Tabii ki değil.
Düzeniniz, görünüm alanınızın genişliğiyle zaten akıcı bir şekilde ölçekleniyor. Tipografinizin akıcı düzeninize göre tahmin edilebilir bir şekilde ölçeklenmesi güzel olmaz mıydı? Bunu geliştirmek için başka ne yapabiliriz?
Kurtarma için Görüntüleme Birimleri?
Görüntü alanı birimleri, doğru yönde atılan bir diğer adımdır. Metninizin mizanpajlarınızla akıcı bir şekilde yeniden boyutlandırılmasına izin verirler. Ve tarayıcı desteği bugünlerde harika.

Ancak Viewport birimlerinin uygulanabilirliği, bir web sayfasının orijinal yaratıcı tasarımlarına çok bağlıdır . font-size
vw
kullanarak ayarlamak ve yapmak harika olurdu:
h1 { font-size: 2vw; }

Ancak bu, yalnızca yaratıcı sanat panolarınız bunu hesaba katarsa işe yarar. Tasarımcı, sanat panolarının her birinin genişliğinin tam olarak %2'si olan bir metin boyutu mu seçti? Tabii ki değil. Her bir kesme noktamız için vw
değerinin ne olması gerektiğini hesaplayalım:
22px
boyut @ 576px
genişlik = 22 ⁄ 576 *100 = 3.82vw 24px
boyut @ 768px
genişlik = 24 ⁄ 768 *100 = 3.13vw 34px
boyut @ 992px
genişlik = 34 ⁄ 992 *100 = 3.43vw
Yakınlar ama hepsi aynı değil. Bu nedenle, metin boyutları arasında geçiş yapmak için yine de medya sorguları kullanmanız gerekecek ve yine de atlamalar olacaktır. Ve şu garip yan etkiyi düşünün:
@ 767 piksel, görüntü alanı genişliğinin %3.82'si 29 pikseldir. Görünüm alanı 1 piksel daha genişse, font-size
aniden 24 piksele düşer . Yeniden boyutlandırılan bir görünümün bu animasyonu, bu istenmeyen yan etkiyi gösterir:

Yazı tipi boyutundaki bu çarpıcı değişiklik, neredeyse kesinlikle tasarımcının öngördüğü şey değildi. Peki bu sorunu nasıl çözeceğiz?
İstatistiksel Doğrusal Regresyon?
Beklemek. Ne? Evet, bu CSS hakkında bir makale, ancak bazı temel matematik, sorunumuza zarif bir çözüme doğru uzun bir yol kat edebilir.
İlk olarak, çözünürlüklerimizi ve karşılık gelen metin boyutlarını bir grafik üzerinde çizelim:

font-size
ve karşılık gelen Görünüm alanı genişliğinin dağılım grafiği (Google E-Tablolar) (Büyük sürümü görüntüleyin) Burada, tasarımcının belirlediği metin boyutlarının tanımlanmış görünüm alanı genişliklerinde dağılım grafiğini görebilirsiniz. X ekseni görünüm alanı genişliğidir ve y ekseni font-size
. Şu satırı görüyor musun? Buna trend çizgisi denir. Sağlanan verilere dayalı olarak, herhangi bir görüntü alanı genişliği için enterpolasyonlu bir font-size
değeri bulmanın bir yolu.
Trend Çizgisi Tüm Bunların Anahtarıdır
font-size
bu eğilim çizgisine göre ayarlayabilseydiniz, tasarımcının amaçladığı şeye yakın olan tüm çözünürlüklerde sorunsuzca ölçeklenen bir h1'e sahip olurdunuz. Önce matematiğe bakalım. Düz çizgi bu denklemle tanımlanır:

- m = eğim
- b = y-kesişim noktası
- x = geçerli görüntü alanı genişliği
- y = elde edilen
font-size
Eğimi ve y-kesişimini belirlemek için çeşitli yöntemler vardır. Birden çok değer söz konusu olduğunda, yaygın bir yöntem En Küçük Kareler uyumudur:

Bu hesaplamaları çalıştırdığınızda, trend çizgisi denkleminiz elde edilir.
Bunu CSS'de Nasıl Kullanırım?
Tamam, bu matematik için oldukça ağır olmaya başladı. Bu şeyleri gerçekten ön uç web geliştirmede nasıl kullanırız? Cevap CSS calc()
! Bir kez daha, oldukça iyi desteklenen oldukça yeni bir CSS teknolojisi.

Trend çizgisi denklemini şu şekilde kullanabilirsiniz:
h1 { font-size: calc({slope}*100vw + {y-intercept}px); }
Eğiminizi ve y-kesişimini bulduğunuzda, onları takmanız yeterli!
Not: Viewport genişliğinin 1/100'ü olan vw
birimi olarak kullandığınız için eğimi 100
ile çarpmanız gerekir.
Bu Otomatik Olabilir mi?
En küçük karelere sığdırma yöntemini kullanımı kolay bir Sass işlevine taşıdım:
/// 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}); }
Bu gerçekten işe yarıyor mu? Bu CodePen'i açın ve tarayıcı pencerenizi yeniden boyutlandırın. İşe yarıyor! Yazı tipi boyutları, orijinal tasarımın istediğine oldukça yakın ve mizanpajınıza göre sorunsuz bir şekilde ölçekleniyor.

En Küçük Kareler Sığdır SCSS testi user="jakobud"]CodePen'de Jake Wilson (@jakobud) tarafından kaleme alınan En Küçük Karelere Sığdır SCSS testine bakın.
Şimdi, kuşkusuz, mükemmel değil. Değerler orijinal tasarıma yakın ancak tam olarak uyuşmuyor. Bunun nedeni, doğrusal bir eğilim çizgisinin, belirli görünüm alanı genişliklerinde belirli yazı tipi boyutlarının bir tahmini olmasıdır. Bu, doğrusal regresyonun kalıtımıdır. Sonuçlarınızda her zaman bazı hatalar vardır. Bu, basitliğe karşı doğruluk dengesidir. Ayrıca, metin boyutlarınız ne kadar çeşitli olursa, trend çizginizde o kadar fazla hata olacağını unutmayın.
Bundan daha iyisini yapabilir miyiz?
Polinom En Küçük Kareler Sığdır
Daha doğru bir trend çizgisi elde etmek için, şuna benzer bir polinom regresyon trend çizgisi gibi daha gelişmiş konulara bakmanız gerekir:

Şimdi bu daha çok benziyor! Bizim düz çizgimizden çok daha doğru. Temel bir polinom regresyon denklemi şöyle görünür:

Eğrinizi ne kadar doğru isterseniz, denklem o kadar karmaşık hale gelir. Ne yazık ki, bunu CSS'de yapamazsınız . calc()
bu tür ileri düzey matematik işlemlerini yapamaz. Özellikle, üsleri hesaplayamazsınız:
font-size: calc(3vw * 3vw); /* This doesn't work in CSS */
Dolayısıyla, calc()
bu tür doğrusal olmayan matematiği destekleyene kadar, yalnızca doğrusal denklemlere takılıp kalırız. Bunu geliştirmek için yapabileceğimiz başka bir şey var mı?
Kesme Noktaları ve Çoklu Doğrusal Denklemler
Ya her bir kesme noktası çifti arasında yalnızca düz bir çizgi hesaplıyor olsaydık? Bunun gibi bir şey:

Dolayısıyla bu örnekte 22px
ile 24px
arasındaki düz çizgiyi ve ardından 24px
ile 34px
arasındaki bir başka düz çizgiyi hesaplayacağız. Sass şöyle görünecek:
// SCSS h1 { @media (min-width:576px) { font-size: calc(???); } @media (min-width:768px) { font-size: calc(???); } }
Bu calc()
değerleri için en küçük karelere sığdırma yöntemini kullanabiliriz, ancak bu yalnızca 2 nokta arasında düz bir çizgi olduğundan, matematik büyük ölçüde basitleştirilebilir. Düz bir çizginin denklemini hatırlıyor musunuz?

Şimdi sadece 2 noktadan bahsettiğimize göre, eğimi (m) ve y-kesişimini (b) bulmak önemsizdir:

İşte bunun için bir Sass işlevi:
/// 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}); }
Şimdi, Sass'ınızdaki birden çok kesme noktasında doğrusal enterpolasyon işlevini kullanın. Ayrıca, bazı minimum ve maksimum font-sizes
da girelim:
// 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; } }
Ve bu CSS'yi oluşturur:
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; } }

CSS Boyutlandırmanın Kutsal Kasesi?
Tüm bunları güzel bir Sass karışımına saralım (tembel ve verimli için!). Bu yöntemi Poly Fluid Sizeing olarak adlandırıyorum :
/// 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)); } }
Bu Sass karışımı, aşağıdaki Github ana hatlarında birkaç Sass işlevi gerektirir:
- doğrusal enterpolasyon
- harita sıralama
- liste sıralama
- liste-kaldır
poly-fluid-sizing()
karışımı, her bir görüntü alanı genişliği çiftinde doğrusal enterpolasyon gerçekleştirecek ve bir minimum ve maksimum boyut ayarlayacaktır. Bunu herhangi bir Sass projesine aktarabilir ve arkasındaki matematiği bilmenize gerek kalmadan kolayca kullanabilirsiniz. İşte bu yöntemi kullanan son CodePen.
Doğrusal denklemler, görüntü alanı birimleri ve calc() kullanarak Çoklu Akışkan Boyutlandırma user="jakobud"]Doğrusal denklemler, görüntü alanı birimleri ve calc() kullanarak Kalem Çoklu Akışkan Boyutlandırma'ya bakın"] Doğrusal denklemler, görüntü alanı birimleri ve calc() kullanarak Çoklu Akışkan Boyutlandırma CodePen'de Jake Wilson (@jakobud) tarafından.
Birkaç Not
- Açıkçası, bu yöntem yalnızca
font-size
için değil, herhangi bir birim/uzunluk özelliği için de geçerlidir (margin
,padding
, vb.). İstenen özellik adını bir dizi olarak karışıma iletirsiniz. - Görünüm alanı genişliği + boyut değeri çiftlerinin Sass haritası, herhangi bir sırayla
poly-fluid-sizing()
karışımına geçirilebilir. Haritayı Viewport genişliğine göre en düşükten en yükseğe otomatik olarak sıralayacaktır . Böylece böyle bir haritayı geçebilirsin ve gayet iyi sonuç verir:
$map: (576px: 22px, 320px: 18px, 992px: 34px, 768px: 24px); @include poly-fluid-sizing('font-size', $map);
- Bu yöntemin bir sınırlaması, karışık birimler halinde karışıma geçememenizdir. Örneğin,
3em
@576px
genişlik. Sass orada matematiksel olarak ne yapacağını gerçekten bilemez.
Çözüm
Yapabileceğimizin en iyisi bu mu? Poly Fluid Boyutlandırma, CSS'de sıvı birimi boyutlandırmasının Kutsal Kase'si midir? Belki. CSS şu anda doğrusal olmayan animasyon ve geçiş zamanlama işlevlerini desteklemektedir, bu nedenle belki bir gün calc()
ın da desteklemesi için bir şans olabilir. Bu olursa, doğrusal olmayan polinom regresyonu tekrar gözden geçirilmeye değer olabilir. Ama belki de değil… Doğrusal ölçekleme zaten daha üstün olabilir.
Bu fikri 2017'nin başlarında keşfetmeye başladım ve sonunda yukarıdaki çözümü geliştirdim. O zamandan beri, birkaç geliştiricinin benzer fikirler ve bu yapbozun farklı parçalarıyla ortaya çıktığını gördüm. Yöntemimi ve oraya nasıl geldiğimi paylaşmanın zamanının geldiğini düşündüm. Görünüm birimleri. Hesap(). Sas. kırılma noktaları Bunların hiçbiri yeni değil. Bunların tümü, yıllardır var olan (değişen derecelerde destekle) tarayıcı özellikleridir. Onları sadece henüz tam olarak keşfedilmemiş bir şekilde birlikte kullandım. Her gün kullandığınız araçlara bakmaktan ve bunları nasıl daha iyi kullanabileceğinizi ve becerilerinizi nasıl geliştirebileceğinizi düşünmekten asla korkmayın.