Dinamik karakter sayısına göre yazı tipi boyutunu duyarlı hale getirmek için saf CSS


298

Bunun Javascript ile kolayca çözülebileceğini biliyorum, ama sadece saf bir CSS çözümü ile ilgileniyorum.

Her zaman sabit bir div içine sığacak şekilde metni dinamik olarak yeniden boyutlandırmak için bir yol istiyorum. İşte örnek işaretleme:

<div style="width: 200px; height: 1em; overflow: hidden;">
  <p>Some sample dynamic amount of text here</p>
</div>

Ems içinde kabın genişliğini belirterek ve bu değeri miras almak için yazı tipi boyutu alarak bu mümkün olabileceğini düşünüyordum?


1
Vay canına, bekle. Bir belirtim widthIn emler şey başka bir yol etrafında dolanıyor. Bu widthbağlıdır font-size. @JosephSilber Ben de öyle düşünmüştüm.
Ana

1
Bu soruyu merak ediyorum. Basit bir javascript işlevi yazmak yerine saf bir css çözümü kullanmak için sürücü nedir?
Austin Mullins

22
Bunun nedeni, problemin mevcut olması ve saf bir CSS çözümünün şaşırtıcı olmasıdır. Sadece birkaç stil uygulama ve dinamik içeriğinizin tasarımı asla kırmayacağını bilmenin olanaklarını düşünün.
DMTintner

4
Herkes bu soru karşısında tökezlemek ve JS kullanarak sakıncası yoksa
DMTintner

2
fitText'in sınırları vardır. Örneğin, sadece 500 piksel genişlikten daha küçük ekranlar için çalıştırmak istiyorum, başlıklarımın daha fazla patlamasını istemiyorum. Bunun için daha fazla JavaScript yazmanız gerekir. Düzen için JavaScript kullandığınızda endişelerin ayrılması çok hızlı bir şekilde bozulur. Asla sadece hızlı bir astar değildir.
Costa

Yanıtlar:


514

Bunun VW üniteleri kullanılarak mümkün olduğunu öğrendim. Bunlar, görüntü alanı genişliğini ayarlamakla ilişkili birimlerdir. Eski tarayıcı desteğinin olmaması gibi bazı dezavantajlar vardır, ancak bu kesinlikle kullanmayı ciddi bir şekilde dikkate almanız gereken bir şeydir. Ayrıca, aşağıdaki gibi eski tarayıcılar için yedekler de sağlayabilirsiniz:

p {
    font-size: 30px;
    font-size: 3.5vw;
}

http://css-tricks.com/viewport-sized-typography/ ve https://medium.com/design-ux/66bddb327bb1


30
Bunun için 2 ups verecekti. Kazanmak için CSS çözümleri!
Mihkel L.

34
Profesyonel ipucu: Metnin çok küçük olmasını önleyebilir ve bunu yaparak font-size:calc(100% + 2vw);veya benzer şekilde biraz kontrol sahibi olabilirsiniz . Bu biraz min-font-size. İçin tarayıcı desteği calcbenzer vw.
Prinzhorn

117
Oy verildi, ancak şimdi bunun orijinal soruyu gerçekten cevaplayıp yanıtlamadığını merak ediyorum. Anladığım kadarıyla, metin uzunluğunuz dinamik ve yazı tipi boyutunu her zaman div(200 piksel) genişliğinize uyacak şekilde değiştirmek istiyorsunuz . Bu sorunu nasıl çözer?
Floremin

26
@ Floremin'in hissine katılıyorum. Bu, TÜM font boyutlarını metnin genişlik / yüksekliğinin kabına değil, görünüm bağlantı noktası genişliğine / yüksekliğine göre ölçeklendirir.
Ocak 15:15 de MickJuice

24
@Floremin haklı, bu soruya değinmiyor. Bu, yazı tipi boyutunu, kap genişliği ile ilişkili olduğu için dize uzunluğunun bir fonksiyonu olarak değil, kap genişliğinin bir fonksiyonu olarak hesaplar
henry

113

CSS3 , görüntüleme bağlantı noktasına göre yeni boyutları destekler. Ama bu androidde çalışmıyor <4.4

  1. 3.2vw = görüş alanının genişliğinin% 3.2'si
  2. 3,2 vh = görüntü yüksekliğinin% 3,2'si
  3. 3.2vmin = 3.2vw veya 3.2vh daha küçük
  4. 3.2vmax = 3.2vw veya 3.2vh daha büyük

    body
    {
        font-size: 3.2vw;
    }

bkz. css-tricks.com / .... ve ayrıca caniuse.com / ....

veya

Ortam sorgusunu kullanın. En basit yolu boyutları% veya em olarak kullanmaktır. Sadece temel yazı tipi boyutunu değiştirin, her şey değişecektir.

@media (max-width: @screen-xs) {
    body{font-size: 10px;}
}

@media (max-width: @screen-sm) {
    body{font-size: 14px;}
}


h5{
    font-size: 1.4em;
}

% Veya em cinsinden boyutlar kullanın . Sadece temel yazı tipi boyutunu değiştirin, her şey değişecektir. Öncekinde, gövde yazı tipini her seferinde h1 değil, değiştirebilir veya temel yazı tipi boyutunu cihazın varsayılanına ayarlayabilir ve hepsini em'de bırakabilirsiniz.

em, px ve% hakkında daha fazla bilgi için kyleschaeffer.com / .... adresine bakın.


12
Soru, tüm bakış açısına göre değil, kaba göre ölçeklendirme ile ilgiliydi.
Arnaud Weil

6
... ve sorular karakter miktarına göre ölçeklendirme ile ilgiliydi
Bravo


14

Tek yol muhtemelen farklı ekran boyutları için farklı genişlikler ayarlamak olacaktır, ancak bu yaklaşım oldukça yanlıştır ve bir js çözümü kullanmalısınız.

h1 {
    font-size: 20px;
}

@media all and (max-device-width: 720px){
    h1 {
        font-size: 18px;
    }
}

@media all and (max-device-width: 640px){
    h1 {
        font-size: 16px;
    }
}

@media all and (max-device-width: 320px){
    h1 {
        font-size: 12px;
    }
}

12

Uzun ölü bir soruyu yeniden canlandırdığımı biliyorum, ama aynı sorum vardı ve bir şeyler eklemek istedim. Lütfen bunun için beni yasaklamayın, bu cevabı haklı çıkarmanın yeterince önemli olduğunu hissettim, gerekirse silerim. @Joseph Silber yanlıştır, tüm olasılıkları kodlamak aslında bunu yapmanın uygun bir yoludur. Bunun nedeni, aslında sonsuz olasılıkların olmamasıdır. Teknik olarak var, ancak ziyaretçilerinizin% 99'u standart bir çözünürlük kullanıyor olacak. Çoğu mobil işletim sistemi, pencereleri yeniden boyutlandırmadan uygulamaları tam ekran çalıştırdığından, bu, mobil cihazlar için iki kat doğrudur (duyarlı web tasarımının ana nedeni).

Ayrıca, kaydırma çubuğu nedeniyle yükseklik hemen hemen önemsizdir (bir noktaya kadar, hemen 4 veya 5 feet uzunluğunda bir web sayfası bırakırdım, ancak bu çoğunlukla doğrudur), bu yüzden sadece genişlik hakkında endişelenmeniz gerekir. Ve gerçekten, kodlamanız gereken tek genişlik şu şekildedir: 240, 320, 480 (daha eski iThings için), 640, 800, 1024, 1280, 1440, 1600, 1920, 2048, 2560. 4k, resimlerinizi çok şişirir ve% 100 genişliğe kadar uzanan 2560 boyutu, bir 4k monitörde iyi görünür (bunu test ettim). Ayrıca, bir önceki afişin önerdiği gibi 720 (720x480) ile uğraşmayın. Neredeyse tamamen dijital kameralar tarafından kullanılan bir çözünürlük ve o zaman bile çok nadir.

Birisi egzotik bir çözünürlük kullanıyorsa, son 15 yılda yapılan neredeyse tüm oluşturucular yuvarlanır, yani birinin ekran genişliği varsa, diyelim. 1100, 1024 CSS kuralını yükleyecek, siteniz bozulmamalıdır. Bu, duyarlı bir kural oluşturmaya gerek kalmadan egzotik çözünürlüklerin hesaplanmasını gereksiz kılar ve birileri sitenizi muhtemelen yüklemeyecek kadar eski bir web tarayıcısı kullanmadığı sürece, olası her kurulum pikseli için piksel kodlamanız gerektiği fikri saçmadır. her neyse.


1
Ve şimdi iPhone
6/6

SASS veya Compass kullanarak ve fonksiyonlara girerken potansiyel olarak daha da kolay. Bir işlev tüm CSS'nin sizin için çalışmasını sağlayabilir; yazmaya karşı-once kullanım-pek.
cjbarth

Yüksekliği, cihazı 90º yana doğru
çevirinceye

Bunun bir konteynerin genişliği ile hiçbir ilgisi yoktur - ki bu kolayca sonsuz olasılıklar vardır.
mcheah

8

Referans olarak, CSS olmayan bir çözüm:

Aşağıda, bir kaptaki metin uzunluğuna bağlı olarak yazı tipini yeniden boyutlandıran bazı JS'ler bulunmaktadır.

Codepen biraz değiştirilmiş kod, ancak aşağıda aynı fikirle:

function scaleFontSize(element) {
    var container = document.getElementById(element);

    // Reset font-size to 100% to begin
    container.style.fontSize = "100%";

    // Check if the text is wider than its container,
    // if so then reduce font-size
    if (container.scrollWidth > container.clientWidth) {
        container.style.fontSize = "70%";
    }
}

Benim için, bir kullanıcı bir açılır menüde bir seçim yaptığında ve sonra menümdeki bir div doldurulduğunda bu işlevi çağırırım (burası dinamik metnin oluştuğu yer).

    scaleFontSize("my_container_div");

Ayrıca, CSS elipslerini ("...") daha uzun metinleri de kısaltmak için kullanıyorum.

#my_container_div {
    width: 200px; /* width required for text-overflow to work */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

Sonuçta:

  • Kısa metin: örneğin "UYGULAMALAR"

    Tamamen işlenmiş, güzel büyük harfler.

  • Uzun metin: örneğin "UYGULAMALAR VE TURUNCULAR"

    Yukarıdaki JS ölçekleme işlevi ile% 70 oranında ölçeklendirilir.

  • Süper uzun metin: örneğin "UYGULAMALAR VE TURUNCULAR & BANAN ..."

    % 70 oranında küçültülür VE yukarıdaki JS ölçekleme işlevi ile birlikte CSS kuralı ile "..." elipsleri ile kesilir.

Aynı yazı tipi boyutunu korurken metni daraltmak için CSS harf aralığı ile oynamayı da keşfedebilirsiniz.


kullanıcı saf bir CSS çözümü isterken oy verdi
AnotherLongUsername

2

@ DMTinter'ın gönderisine yapılan yorumlarda belirtildiği gibi, OP karakterlerin sayısının ("miktar") değiştiğini soruyordu. Ayrıca CSS hakkında da soruyordu ama @Alexander'ın belirttiği gibi, "sadece CSS ile mümkün değil". Anlayabildiğim kadarıyla, bu şu anda doğru gibi görünüyor, bu yüzden insanların bir sonraki en iyi şeyi bilmek isteyecekleri mantıklı görünüyor.

Bununla özellikle gurur duymuyorum, ama işe yarıyor. Bunu başarmak için aşırı miktarda kod gibi görünüyor. Çekirdek bu:

function fitText(el){
  var text = el.text();
  var fsize = parseInt(el.css('font-size'));
  var measured = measureText(text, fsize);

  if (measured.width > el.width()){
    console.log('reducing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize );
      if(m.width > el.width()){
        el.css('font-size', --fsize + 'px');
      }
      else{
        break;
      }
    }
  }
  else if (measured.width < el.width()){
    console.log('increasing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize);
      if(m.width < el.width()-4){ // not sure why -4 is needed (often)
        el.css('font-size', ++fsize + 'px');
      }
      else{
        break;
      }
    }
  }
}

İşte bir JS Bin: http://jsbin.com/pidavon/edit?html,css,js,console,output
Lütfen olası iyileştirmeleri önerin (metni ölçmek için tuval kullanmakla gerçekten ilgilenmiyorum ... çok fazla havai gibi (?)).

Measure for Text işlevi için @Pete sayesinde: https://stackoverflow.com/a/4032497/442665


2

Bu çözüm ayrıca yardımcı olabilir:

$(document).ready(function () {
    $(window).resize(function() {
        if ($(window).width() < 600) {
            $('body').css('font-size', '2.8vw' );
        } else if ($(window).width() >= 600 && $(window).width() < 750) {
            $('body').css('font-size', '2.4vw');
        } 
         // and so on... (according to our needs)
        } else if ($(window).width() >= 1200) {
            $('body').css('font-size', '1.2vw');
        }
    }); 
  });

Benim için iyi çalıştı!


Bu, kelime kaydırmayı nasıl dikkate alır?
Leif Neland


2
calc(42px + (60 - 42) * (100vw - 768px) / (1440 - 768));

bu denklemi kullanın.

1440 ve 768'den daha büyük veya daha küçük herhangi bir şey için, ona statik bir değer verebilir veya aynı yaklaşımı uygulayabilirsiniz.

Vw çözümünün dezavantajı, bir ölçek oranı ayarlayamamanızdır, diyelim ki 1440 ekran çözünürlüğünde bir 5vw 60px yazı tipi boyutu, fikir yazı tipi boyutunuz olabilir, ancak pencere genişliğini 768'e küçülttüğünüzde, 12px olmak, istediğiniz minimal değil. Bu yaklaşımla, üst sınırınızı ve alt sınırınızı ayarlayabilirsiniz ve yazı tipi kendi aralarında ölçeklenir.


-2

İçindeki dizenin uzunluğuna göre yazı tipi boyutunu hesaplayan bir arama tablosu oluşturun <div>.

const fontSizeLookupTable = () => {
  // lookup table looks like: [ '72px', ..., '32px', ..., '16px', ..., ]
  let a = [];
  // adjust this based on how many characters you expect in your <div>
  a.length = 32;
  // adjust the following ranges empirically
  a.fill( '72px' ,     );
  a.fill( '32px' , 4 , );
  a.fill( '16px' , 8 , );
  // add more ranges as necessary
  return a;
}

const computeFontSize = stringLength => {
  const table = fontSizeLookupTable();
  return stringLength < table.length ? table[stringLength] : '16px';
}

Ampirik test ile tüm parametreleri ayarlayın ve ayarlayın.


Parametreler için ampirik test esasen zaman karmaşıklığı olan ikili bir aramadır: O (log n).
Let Me Tink About About

Aslında bu işlevi çağırmayı unuttun, ayrıca dizi uzunluğunun özelliğiyle erişilmesi gerekiyor.
lukk

@lukk: Geri bildiriminiz için teşekkürler. Şimdi düzeltildi.
Let Me Tink About About
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.