CSS Çoklu Akışkan Boyutlandırma ile Akışkan Duyarlı Tipografi

Yayınlanan: 2022-03-10
Hızlı özet ↬ Değişken düzenler, yıllardır ön uç geliştirmenin normal bir parçası olmuştur. Bununla birlikte, akışkan tipografi fikri nispeten yenidir ve henüz tam olarak keşfedilmemiştir. Şimdiye kadar, çoğu geliştiricinin akışkan tipografi fikri, yalnızca bazı minimum ve maksimum boyutlarda Viewport birimlerini kullanmaktı. Bu 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.

Bu 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:

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓
  1. Küçük düzendeki h1 , 22px olabilir
  2. Orta düzendeki h1 , 24px olabilir
  3. 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.

Viewport'u Kullanabilir miyim?
(Büyük versiyonu görüntüle)

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 = 22576 *100 = 3.82vw 24px boyut @ 768px genişlik = 24768 *100 = 3.13vw 34px boyut @ 992px genişlik = 34992 *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:

Yazı tipi boyutu ve karşılık gelen Görünüm Alanı genişliğinin dağılım grafiği
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:

Doğrusal denklem tanımı
Doğrusal denklem tanımı
  • 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:

En Küçük Kareler

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.

Calc Kullanabilir miyim?
(Büyük versiyonu görüntüle)

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.

En Küçük Karelere 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:

Polinom regresyon trend çizgisi
Polinom regresyon trend çizgisi (Google E-Tablolar) (Geniş versiyonu görüntüleyin)

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

3. dereceden bir polinom denklemi
3. dereceden bir polinom denklemi

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:

Birden çok değer çifti arasındaki Lineer Regresyon trend çizgileri
Birden çok değer çifti arasındaki Doğrusal Regresyon eğilim çizgileri (Google E-Tablolar) (Büyük sürümü görüntüleyin)

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?

Doğrusal denklem tanımı
Doğrusal denklem tanımı

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

Doğrusal bir denklemin eğimini ve y-kesişimini bulma
Doğrusal bir denklemin eğimini ve y-kesişimini bulma

İş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.

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ırmaya 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.