Skalowanie czcionek na podstawie szerokości pojemnika

1185

Trudno mi się zastanowić nad skalowaniem czcionek.

Obecnie mam tę stronę z font-size100% treścią. 100% czego? Wydaje się, że oblicza się przy 16 pikselach.

Miałem wrażenie, że 100% w jakiś sposób odnosi się do rozmiaru okna przeglądarki, ale najwyraźniej nie dlatego, że zawsze jest 16 pikseli, niezależnie od tego, czy okno jest zmniejszane do szerokości mobilnej, czy pełnego ekranu panoramicznego.

Jak mogę skalować tekst na mojej stronie w stosunku do kontenera? Próbowałem użyć em, ale to też nie jest skalowane.

Moje rozumowanie jest takie, że rzeczy takie jak moje menu stają się zgniecione podczas zmiany rozmiaru, więc muszę zmniejszyć px font-sizeliczbę .menuIteminnych elementów w stosunku do szerokości pojemnika. (Na przykład w menu na dużym pulpicie 22pxdziała idealnie. Zejdź na szerokość tabletu i 16pxjest bardziej odpowiedni.)

Wiem, że mogę dodawać punkty przerwania, ale naprawdę chcę, aby tekst był skalowany, a także mieć dodatkowe punkty przerwania, w przeciwnym razie skończę z setkami punktów przerwania na każde zmniejszenie szerokości 100 pikseli, aby kontrolować tekst.

Francesca
źródło
34
font-size: 100%;oznacza 100% rozmiaru tekstu, który byłby (tj. ten, który odziedziczy po rodzicu). Domyślnie jest to 16 pikseli. Więc jeśli użyjesz 50%, będzie to rozmiar czcionki: 8px
Andy
31
To, czego szukasz, nazywa się typografią responsywną lub wielkością okienka ekranu. css-tricks.com/viewport-sized-typography
gearsdigital 17.04.2013
8
Daj FitText wygląd.
Patsy Issa,
12
@Andy: W rzeczywistości „domyślnie” jest tym, co użytkownicy mają ustawiony rozmiar tekstu przeglądarki, co niekoniecznie musi mieć rozdzielczość 16px.
ScottS,
1
spójrz na tę odpowiedź stackoverflow.com/a/28485608/4251431
Basheer AL-MOMANI

Odpowiedzi:

1494

EDYCJA: Jeśli kontener nie jest ciałem Sztuczki CSS obejmują wszystkie opcje w Dopasowywanie tekstu do kontenera .

Jeśli kontenerem jest ciało, to czego szukasz, to długości procentowe rzutni :

Te długości wziernika-procentowe są w odniesieniu do wielkości początkowej, zawierającej bloku . Gdy wysokość lub szerokość początkowego bloku zawierającego zostanie zmieniona, są one odpowiednio skalowane. Jednak gdy wartość przepełnienia elementu głównego ma wartość automatyczną, zakłada się, że żadne paski przewijania nie istnieją.

Wartości są następujące:

  • vw (% szerokości rzutni)
  • vh (% wysokości rzutni)
  • vi (1% wielkości rzutni w kierunku wbudowanej osi elementu głównego)
  • vb (1% wielkości rzutni w kierunku osi bloku elementu głównego)
  • vmin(mniejszy z vwlub vh)
  • vmax(większy lub vwlub vh)

1 v * jest równy 1% początkowego bloku zawierającego.

Korzystanie z niego wygląda następująco:

p {
    font-size: 4vw;
}

Jak widać, wraz ze wzrostem szerokości rzutni należy to zrobić font-sizebez konieczności korzystania z zapytań o media.

Wartości te są jednostkami zmiany rozmiaru, podobnie jak pxlub em, więc można ich używać do wymiarowania również innych elementów, takich jak szerokość, margines lub wypełnienie.

Obsługa przeglądarek jest całkiem dobra, ale prawdopodobnie potrzebujesz rezerwy, takiej jak:

p {
    font-size: 16px;
    font-size: 4vw;
}

Sprawdź statystyki pomocy technicznej: http://caniuse.com/#feat=viewport-units .

Zobacz także CSS-Tricks, aby uzyskać szerszy wygląd: typografia wielkości rzutni

Oto fajny artykuł na temat ustawiania minimalnych / maksymalnych rozmiarów i wykonywania nieco większej kontroli nad rozmiarami: Precyzyjna kontrola nad responsywną typografią

A oto artykuł o ustawianiu rozmiaru za pomocą funkcji calc (), aby tekst wypełniał rzutnię: http://codepen.io/CrocoDillon/pen/fBJxu

Zobacz także ten artykuł, w którym zastosowano technikę nazwaną „stopionym prowadzeniem”, aby również dostosować wysokość linii. Stopiony wiodący w CSS

jbenjohnson
źródło
546
Ale co jeśli kontener nie jest rzutnią (ciałem)?
Alex
12
@Alex, to terytorium JS. Wypróbuj FitText.jsalternatywę podaną na dole artykułu @jbenjohnson.
Robbert,
10
W tym miejscu pojawiają się tak zwane zapytania o elementy. W przeciwieństwie do zapytań o media, zapytania o elementy rozmiarowałyby rzeczy na podstawie bloku zawierającego, a nie rzutni, co byłoby niesamowite! Ale niestety jeszcze nie istnieje. Jednak, jeśli jesteś zainteresowany, istnieją pewne polifilly i proof-of-concept: coding.smashingmagazine.com/2013/06/25/... i filamentgroup.com/lab/element_query_workarounds
jbenjohnson
139
Obniżona ocena, ponieważ to nie odpowiada na pytanie. Zapytał o pojemnik, a nie rzutnię. Zupełnie inny przypadek użycia.
SongBox,
6
„początkowy blok zawierający” odnosi się do elementu głównego. To nie jest poprawna odpowiedź na zadane pytanie.
Glyph
319

Ale co jeśli kontener nie jest rzutnią (ciałem)?

To pytanie zadaje Alex w komentarzu pod przyjętą odpowiedzią .

Fakt ten nie oznacza, że ​​nie vwmożna go w pewnym stopniu wykorzystać do wielkości tego pojemnika. Teraz, aby zobaczyć jakąkolwiek odmianę, trzeba założyć, że pojemnik w jakiś sposób ma elastyczny rozmiar. Czy poprzez bezpośredni procentwidth czy 100% minus marże. Punkt staje się „dyskusyjny”, jeśli kontener jest zawsze ustawiony na, powiedzmy, 200pxszeroki - wtedy wystarczy ustawić wartość, font-sizektóra działa dla tej szerokości.

Przykład 1

Jednak w przypadku kontenera o elastycznej szerokości należy zdać sobie sprawę, że w jakiś sposób pojemnik nadal jest wymiarowany poza okienkiem ekranu . W związku z tym chodzi o dostosowanie vwustawienia opartego na tej procentowej różnicy wielkości do rzutni, co oznacza wzięcie pod uwagę rozmiaru opakowań nadrzędnych. Weź ten przykład :

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       So if the container is 50% of viewport (as here)
       then factor that into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 2.5vw (5 * .5 [i.e. 50%])
    */
    font-size: 2.5vw;
}

Zakładając, że divjest to potomek body, ma on 50%100%szerokość, która jest rozmiarem rzutni w tym podstawowym przypadku. Zasadniczo chcesz ustawić taki, vwktóry będzie ci dobrze wyglądał. Jak widać w moim komentarzu w powyższej treści CSS, możesz „przemyśleć” to matematycznie w odniesieniu do pełnego rozmiaru rzutni, ale nie musisz tego robić. Tekst będzie „wyginał się” z kontenerem, ponieważ kontener zgina się przy zmianie rozmiaru rzutni. AKTUALIZACJA: oto przykład dwóch pojemników różnej wielkości .

Przykład 2

Możesz pomóc w określeniu rozmiaru rzutni, wymuszając na tej podstawie obliczenia. Rozważ ten przykład :

html {width: 100%;} /* Force 'html' to be viewport width */
body {width: 150%; } /* Overflow the body */

div {
    width: 50%;
    border: 1px solid black;
    margin: 20px;
    font-size: 16px;
    /* 100 = viewport width, as 1vw = 1/100th of that
       Here, the body is 150% of viewport, but the container is 50%
       of viewport, so both parents factor  into how you want it to size.
       Let's say you like 5vw if it were the whole width,
       then for this container, size it at 3.75vw
       (5 * 1.5 [i.e. 150%]) * .5 [i.e. 50%]
    */
    font-size: 3.75vw;
}

Rozmiary są nadal oparte na rzutni, ale w zasadzie są konfigurowane w oparciu o sam rozmiar kontenera.

Jeśli rozmiar kontenera zmieni się dynamicznie ...

Jeśli rozmiar elementu kontenera ostatecznie dynamicznie zmienia swój procentowy stosunek albo przez @mediapunkty przerwania, albo przez JavaScript, to bez względu na podstawowy „cel” trzeba będzie ponownie obliczyć, aby utrzymać tę samą „relację” do zmiany rozmiaru tekstu.

Weź przykład 1 powyżej. Jeśli divzmieniono na 25%szerokość za pomocą jednego @medialub JavaScript, to w tym samym czasie font-sizenależałoby dostosować zapytanie multimedialne lub JavaScript do nowego obliczenia 5vw * .25 = 1.25. Dzięki temu rozmiar tekstu byłby taki sam, jak w „szerokości” oryginału50% kontenera została zmniejszona o połowę w stosunku do rozmiaru rzutni, ale teraz została zmniejszona z powodu zmiany własnych obliczeń procentowych.

Wyzwanie

Gdy używana jest funkcja CSS3calc() , jej dynamiczne dostosowanie byłoby trudne, ponieważ ta funkcja obecnie nie działa do font-sizecelów. Więc nie możesz wykonać czystej regulacji CSS 3, jeśli twoja szerokość się zmienia calc(). Oczywiście niewielkie dostosowanie szerokości marginesów może nie być wystarczające, aby uzasadnić jakąkolwiek zmianę font-size, więc może nie mieć znaczenia.

ScottS
źródło
(Wystąpił błąd przeglądarki Chrome o procentowej długości okienka ekranu i zmianie rozmiaru okna: code.google.com/p/chromium/issues/detail?id=124331 )
trzydziesty
@ thirtydot: To niefortunne (ale dobrze wiedzieć, dzięki). Mam nadzieję, że błąd zostanie wkrótce rozwiązany, ale wygląda na to, że utrzymuje się od jakiegoś czasu.
ScottS,
20
Świetna odpowiedź, jednak nie zadziała, jeśli element zawierający ma maksymalną szerokość.
Himmators
3
@KristofferNolgren: Odnosi się to do dwóch punktów poruszonych w mojej odpowiedzi: (1) „zakładając, że pojemnik w jakiś sposób ma elastyczny rozmiar” (po osiągnięciu „maksymalnej szerokości” nie wygina się, więc pojawia się problem ). (2) Jeśli można ustalić, w którym punkcie zostanie osiągnięta „maksymalna szerokość”, to, jak zauważyłem, można ustawić @mediapunkt przerwania, aby zmienić rozmiar czcionki w tym punkcie (zasadniczo nadając jej stały rozmiar przy osiągnięciu max-width) . Po prostu myśl, aby poradzić sobie z max-widthsytuacją.
ScottS
Czy uważasz, że możesz rzucić skrzypce, gdy element kontenera zmienia się dynamicznie za pomocą zapytań o media? Nie jestem pewien, czy rozumiem.
J82
58

Rozwiązanie z SVG:

<div style="width: 60px;">  
  <svg width="100%" height="100%" viewBox="0 -200 1000 300"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <text font-size="300" fill="black">Text</text>
  </svg>
</div>

https://jsfiddle.net/qc8ht5eb/


Rozwiązanie z SVG i owijaniem tekstu za pomocą foreignObject:

<svg viewBox="0 0 100 100">
  <foreignObject width="100%" height="100%">
    <h1>heading</h1>

    lorem ipsum dolor sit amet
  </foreignObject>
</svg> 

https://jsfiddle.net/2rp1q0sy/

Dantio
źródło
1
Ten pomysł na początku wygląda ładnie. Wtedy zdajesz sobie sprawę, że nie możesz łatwo kontrolować czcionki w SVG wewnątrz <html>. Czcionka jest inna na urządzeniach mobilnych i stacjonarnych, co wpływa na końcową szerokość.
Stopi
@Stopi co sądzisz o rozwiązaniu iFrame? przykład
Dantio,
10
Możesz całkowicie stylizować SVG z HTML / CSS
gman
1
SVG może być stylizowany za pomocą css, jeśli plik svg jest wbudowany (nie używaj znacznika img).
8
To najlepsze, najbardziej przewidywalne rozwiązanie, które można skalować w oparciu o dynamiczny kontener.
JoshuaDavid
35

W jednym z moich projektów używam „mieszanki” między vw i vh, aby dostosować rozmiar czcionki do moich potrzeb, na przykład:

font-size: calc(3vw + 3vh);

Wiem, że to nie odpowiada na pytanie PO, ale może może być rozwiązaniem dla każdego innego.

lsblsb
źródło
3
Lepiej będzie użyć vmini / lub vmaxzamiast tego.
sebastian_k
4
chrome dev tools nazywa to niepoprawną wartością właściwości
phil294
29

Rozwiązanie Pure-CSS z calc()jednostkami CSS i matematyką

To nie jest dokładnie to, o co prosi OP, ale może uczynić czyjś dzień. Ta odpowiedź nie jest łatwa do karmienia łyżeczką i wymaga pewnych badań po stronie programisty.

Przyszedłem w końcu, aby uzyskać rozwiązanie czysto CSS do tego przy użyciu calc()różnych jednostek. Będziesz potrzebował trochę matematycznego zrozumienia formuł, aby wypracować swoje wyrażenie calc().

Kiedy to wymyśliłem, musiałem uzyskać responsywny nagłówek o pełnej szerokości strony z kilkoma dopełniaczami kilku rodziców w DOM. Użyję tutaj moich wartości, zastąpię je własnymi.

Do matematyki

Będziesz potrzebować:

  • Ładnie dostosowany współczynnik w niektórych rzutniach. Użyłem 320 pikseli, więc mam 24 piksele wysokości i 224 piksele, więc stosunek wynosi 9.333 ... lub 28/3
  • Szerokość pojemnika, którą miałem padding: 3emi pełną szerokość, więc to się stało100wv - 2 * 3em

X to szerokość kontenera, więc zastąp go własnym wyrażeniem lub dostosuj wartość, aby uzyskać tekst na całej stronie. Rto stosunek, który będziesz miał. Możesz to uzyskać, dostosowując wartości w niektórych rzutniach, sprawdzając szerokość i wysokość elementu i zastępując je własnymi wartościami. Poza tym jest width / heigth;)

x = 100vw - 2 * 3em = 100vw - 6em
r = 224px/24px = 9.333... = 28 / 3

y = x / r
  = (100vw - 6em) / (28 / 3)
  = (100vw - 6em) * 3 / 28
  = (300vw - 18em) / 28
  = (75vw - 4.5rem) / 7

I huk! Zadziałało! napisałem

font-size: calc((75vw - 4.5rem) / 7)

do mojego nagłówka i ładnie się dopasowało w każdej rzutni.

Ale jak to działa?

Potrzebujemy tutaj stałych. 100vwoznacza pełną szerokość rzutni, a moim celem było ustalenie nagłówka o pełnej szerokości z dopełnieniem.

Stosunek Uzyskanie szerokości i wysokości w jednej rzutni dało mi proporcję do zabawy, a ze współczynnikiem wiem, jaka powinna być wysokość w drugiej szerokości rzutni. Obliczenie ich ręcznie zajęłoby dużo czasu i przynajmniej zajęło dużo przepustowości, więc nie jest to dobra odpowiedź.

Wniosek

Zastanawiam się, dlaczego nikt tego nie wymyślił, a niektórzy nawet mówią, że nie można majstrować przy CSS. Nie lubię używać JavaScript w dostosowywaniu elementów, więc nie akceptuję odpowiedzi JavaScript (i zapominam o jQuery) bez kopania więcej. Podsumowując, to dobrze, że to wymyślono i jest to jeden krok do implementacji czysto CSS w projektowaniu stron internetowych.

Przepraszam za każdą nietypową konwencję w moim tekście, nie jestem native speakerem w języku angielskim, a także jestem całkiem nowy w pisaniu odpowiedzi na przepełnienie stosu.

Należy również zauważyć, że w niektórych przeglądarkach mamy złe paski przewijania. Na przykład, gdy korzystam z Firefoksa, zauważyłem, że 100vwoznacza to pełną szerokość okienka ekranu, rozciągającą się pod paskiem przewijania (gdzie zawartość nie może się rozwinąć!), Więc tekst o pełnej szerokości musi być ostrożnie marginesowany i najlepiej przetestowany na wielu przeglądarkach i urządzeniach.

hegez
źródło
13
To rozwiązanie działa tylko wtedy, gdy (1) znasz czcionkę, (2) czcionka jest dostępna na urządzeniu użytkownika i (3) tekst jest zawsze taki sam. To sprawia, że ​​jest to bardzo ograniczony przypadek użycia.
Andrei Volgin
nie rozumiem co, jeśli mój kontener jest naprawiony, na przykład: 640px i stosunek 16: 9. jakie cielęta powinienem napisać?
pery mimon
1
Twoja szerokość pojemnika xwynosi 640px i stosunek r16: 9, więc: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez
Uwaga: działa to tylko wtedy, gdy rzeczywiście masz tekst o rozmiarze 16: 9, co jest dziwną sytuacją. Być może przeczytanie odpowiedzi po raz drugi może pomóc. Działa to również tylko w przypadku jednowarstwowych.
hegez
Szczerze mówiąc, nie wyjaśniasz „Ładnie wyregulowany współczynnik w niektórych rzutniach. Użyłem 320 pikseli, więc mam 24 piksele wysokości i 224 piksele szerokości, więc współczynnik wynosi 9.333 ... lub 28/3” Sugeruję wyjaśnienie proporcji trochę więcej. Co reprezentuje ten stosunek?
Elimin4t0r
28

W tej kwestii istnieje wielka filozofia.

Najłatwiej jest nadać określony rozmiar czcionki ciału (zalecam 10), a następnie wszystkie inne elementy miałyby czcionkę w emlub rem. Dam ci przykład, aby zrozumieć te jednostki. Emjest zawsze względem swojego rodzica:

body{font-size: 10px;}
.menu{font-size: 2em;} /* That means 2*10 pixels  = 20 pixels */
.menu li{font-size: 1.5em;} /* That means 1.5*20 pixels = 30 pixels */

Rem jest zawsze względem ciała:

body{font-size: 10px;}
.menu{font-size: 2rem;} /* That means 2*10 pixels = 20 pixels */
.menu li{font-size: 1.5rem;} /* that means 1.5*10 pixels = 15 pixels */

Następnie możesz utworzyć skrypt, który zmodyfikowałby rozmiar czcionki względem szerokości pojemnika. Ale nie to poleciłbym. Ponieważ na przykład w pojemniku o szerokości 900 pikseli miałbyśp element o wielkości czcionki 12 pikseli, powiedzmy. I na twoim pomyśle, że stałby się pojemnikiem o szerokości 300 pikseli przy wielkości czcionki 4 piksele. Musi być dolny limit.

Inne rozwiązania dotyczyłyby zapytań o media, aby można było ustawić czcionkę dla różnych szerokości.

Ale rozwiązaniem, które poleciłbym, jest skorzystanie z biblioteki JavaScript, która Ci w tym pomoże. I fittext.js, które znalazłem do tej pory.

Dan Ovidiu Boncut
źródło
6
remUrządzenie jest w stosunku do elementu głównego, czyli htmlelement, a nie bodyelementu. Elementem głównym w DOM jest htmlznacznik. developer.mozilla.org/en-US/docs/Web/CSS/length .. remjest zawsze względny do htmlznacznika, który jest elementem głównym, a nie znacznikiem body .. ale dobrą odpowiedzią :)
Jonathan Marzullo
fittext.js sprawia, że ​​praca jest skończona, zaleciłem to rozwiązanie!
Jacek Dziurdzikowski
FitText był dla mnie zwycięzcą. Próbowałem kilku alternatyw, ale wydawało się to najprostsze i dobrze zintegrowane z Drupal / Backdrop CMS. github.com/davatron5000/FitText.js
Auxiliary Joel
23

Oto funkcja:

document.body.setScaledFont = function(f) {
  var s = this.offsetWidth, fs = s * f;
  this.style.fontSize = fs + '%';
  return this
};

Następnie przekonwertuj wszystkie rozmiary czcionek elementu podrzędnego dokumentów na em's lub %.

Następnie dodaj coś takiego do kodu, aby ustawić podstawowy rozmiar czcionki.

document.body.setScaledFont(0.35);
window.onresize = function() {
    document.body.setScaledFont(0.35);
}

http://jsfiddle.net/0tpvccjt/

tnt-rox
źródło
1
Jak dotąd jest to najlepsze rozwiązanie.
Krótkie
Złe praktyki i bardzo nieefektywne
Jack Giffin
@tntrox Choć dziś jest nieefektywny, 4 lata temu był o wiele bardziej nieefektywny. Odrzucam tę odpowiedź zamiast o wiele lepszych alternatyw. Tak, do obsługi IE potrzebny byłby Javascript. Ale nie potrzeba Javascript, który jest tak okropny.
Jack Giffin
3
Wydaje mi się, że moja ignorancja się tutaj pokazuje. Ale DLACZEGO powyższe jest okropne?
Nie sądzę, żeby to było okropne. Polecam kilka drobnych zmian formatowania, aby były bardziej czytelne. Umieściłbym każdy var przynajmniej w osobnej linii. Pod return thiskoniec funkcji może nie być konieczne . Aby uzyskać wydajność, możesz również ogłosić rozmiar onresize, aby nie przerysował podczas przeciągania. Jest to dość prosty kod, więc ktoś może bez trudu oprzeć na nim swoje ulepszone rozwiązanie.
Mnebuerquo,
19

Jest na to sposób bez JavaScript!

Możesz użyć wbudowanego obrazu SVG. Możesz użyć CSS na SVG, jeśli jest on wbudowany. Musisz pamiętać, że użycie tej metody oznacza, że ​​obraz SVG zareaguje na rozmiar pojemnika.

Spróbuj użyć następującego rozwiązania ...

HTML

<div>
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360.96 358.98" >
      <text>SAVE $500</text>
  </svg>
</div>

CSS

div {
  width: 50%; /* Set your container width */
  height: 50%; /* Set your container height */

}

svg {
  width: 100%;
  height: auto;

}

text {
  transform: translate(40px, 202px);
  font-size: 62px;
  fill: #000;
}

Przykład: https://jsfiddle.net/k8L4xLLa/32/

Chcesz coś bardziej efektownego?

Obrazy SVG pozwalają także robić fajne rzeczy z kształtami i śmieciami. Sprawdź ten świetny przypadek użycia skalowalnego tekstu ...

https://jsfiddle.net/k8L4xLLa/14/

Peter Mortensen
źródło
4
To rozwiązanie nie różni się od przyjętego rozwiązania z vwdoborem. jeśli zmienisz tekst, wszystko wychodzi poza granice.
N69S,
14

Może to nie być zbyt praktyczne, ale jeśli chcesz, aby czcionka była bezpośrednią funkcją rodzica, bez kodu JavaScript, który nasłuchuje / zapętla (interwał), aby odczytać rozmiar div / strony, istnieje sposób, aby to zrobić . Ramki iframe

Wszystko w elemencie iframe będzie traktować rozmiar iframe jako rozmiar rzutni. Zatem sztuczka polega na utworzeniu elementu iframe, którego szerokość jest maksymalną szerokością tekstu, a wysokość jest równa maksymalnej wysokości * proporcji danego tekstu.

Pomijając ograniczenie, że jednostki rzutni nie mogą również towarzyszyć jednostkom nadrzędnym dla tekstu (ponieważ w, ponieważ rozmiar% zachowuje się jak wszyscy inni), jednostki rzutni zapewniają bardzo potężne narzędzie: możliwość uzyskania wymiaru minimalnego / maksymalnego . Nie możesz tego zrobić nigdzie indziej - nie możesz powiedzieć ... aby wysokość tego div była szerokością rodzica * coś.

Biorąc to pod uwagę, sztuczka polega na użyciu vmin i ustawieniu rozmiaru elementu iframe tak, aby [ułamek] * całkowita wysokość była dobrym rozmiarem czcionki, gdy wysokość jest wymiarem ograniczającym, i [ułamek] * całkowita szerokość, gdy szerokość jest wymiar ograniczający. Dlatego wysokość musi być iloczynem szerokości i współczynnika kształtu.

W moim konkretnym przykładzie masz

.main iframe{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: calc(3.5 * 100%);
  background: rgba(0, 0, 0, 0);
  border-style: none;
  transform: translate3d(-50%, -50%, 0);
}

Niewielka irytacja tą metodą polega na tym, że trzeba ręcznie ustawić CSS iframe. Jeśli dołączysz cały plik CSS, zajęłoby to dużo przepustowości dla wielu obszarów tekstowych. Więc to, co robię, to dołączenie reguły, którą chcę bezpośrednio z mojego CSS.

var rule = document.styleSheets[1].rules[4];
var iDoc = document.querySelector('iframe').contentDocument;
iDoc.styleSheets[0].insertRule(rule.cssText);

Możesz napisać małą funkcję, która pobierze regułę CSS / wszystkie reguły CSS, które miałyby wpływ na pole tekstowe.

Nie mogę wymyślić innego sposobu, aby to zrobić bez korzystania z JavaScript w trybie cyklicznym / słuchania. Prawdziwym rozwiązaniem byłoby, aby przeglądarki zapewniały sposób skalowania tekstu jako funkcję kontenera nadrzędnego, a także zapewniały tę samą funkcjonalność typu vmin / vmax.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (kliknij raz, aby zablokować czerwony kwadrat myszy, i kliknij ponownie, aby zwolnić)

Większość JavaScript w skrzypcach to tylko moja niestandardowa funkcja przeciągania.

Roman Rekhler
źródło
@ quemeful Nie tak, kiedy wprowadzamy atrybut „nowy” i „błyszczący” (bęben proszę ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin
9

Korzystanie vw, em& CO. działa na pewno, ale IMO zawsze potrzebuje dotyku człowieka, aby dostroić.

Oto skrypt Właśnie napisałem na podstawie @ TNT rox” odpowiedź , która stara się zautomatyzować, że ludzki dotyk za:

$('#controller').click(function(){
    $('h2').each(function(){
        var
            $el = $(this),
            max = $el.get(0),
            el = null
        ;
        max =
            max
            ? max.offsetWidth
            : 320
        ;
        $el.css({
            'font-size': '1em',
            'display': 'inline',
        });
        el = $el.get(0);

        el.get_float = function(){
            var
                fs = 0
            ;
            if (this.style && this.style.fontSize) {
                fs = parseFloat(this.style.fontSize.replace(/([\d\.]+)em/g, '$1'));
            }
            return fs;
        };

        el.bigger = function(){
            this.style.fontSize = (this.get_float() + 0.1) + 'em';
        };

        while (el.offsetWidth < max) {
            el.bigger();
        }

        // Finishing touch.
        $el.css({
            'font-size': ((el.get_float() -0.1) +'em'),
            'line-height': 'normal',
            'display': '',
        });
    });  // end of (each)
});    // end of (font scaling test)
div {
  width: 50%;
  background-color: tomato;
  font-family: 'Arial';
}

h2 {
  white-space: nowrap;
}

h2:nth-child(2) {
  font-style: italic;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="button" id="controller" value="Apply" />
<div>
  <h2>Lorem ipsum dolor</h2>
  <h2>Test String</h2>
  <h2>Sweet Concatenation</h2>
  <h2>Font Scaling</h2>
</div>

Zasadniczo zmniejsza rozmiar czcionki, 1ema następnie zaczyna zwiększać o 0,1, aż osiągnie maksymalną szerokość.

JSFiddle

WoodrowShigeru
źródło
1
+1 tylko dla kogoś, kto uznaje, że emswymaga ludzkiego dotyku, a pionowy rytm nie jest jakimś rodzajem magii.
serraosays
7

100% odnosi się do podstawowego rozmiaru czcionki, który, jeśli go nie ustawiłeś, byłby domyślnym klientem przeglądarki.

Aby uzyskać oczekiwany efekt, użyłbym kawałka kodu JavaScript, aby dostosować podstawowy rozmiar czcionki w stosunku do wymiarów okna.

scoota269
źródło
7

W swoim CSS spróbuj dodać to u dołu, zmieniając szerokość 320 pikseli, tam gdzie twój projekt zaczyna się psuć:

    @media only screen and (max-width: 320px) {

        body { font-size: 1em; }

    }

Następnie podaj rozmiar czcionki w „px” lub „em”, jak chcesz.

Grube
źródło
7

Moje własne rozwiązanie, oparte na jQuery, polega na stopniowym zwiększaniu rozmiaru czcionki, aż do momentu, gdy kontener osiągnie duży wzrost wysokości (co oznacza, że ​​nastąpiło przerwanie linii).

Jest dość prosty, ale działa dość dobrze i jest bardzo łatwy w użyciu. Nie musisz nic wiedzieć o używanej czcionce, wszystko załatwia przeglądarka.

Możesz grać z nim na http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

Magia dzieje się tutaj:

var setMaxTextSize=function(jElement) {
    // Get and set the font size into data for reuse upon resize
    var fontSize=parseInt(jElement.data(quickFitFontSizeData)) || parseInt(jElement.css("font-size"));
    jElement.data(quickFitFontSizeData, fontSize);

    // Gradually increase font size until the element gets a big increase in height (i.e. line break)
    var i = 0;
    var previousHeight;
    do
    {
        previousHeight=jElement.height();
        jElement.css("font-size", "" + (++fontSize) + "px");
    }
    while(i++ < 300 && jElement.height()-previousHeight < fontSize/2)

    // Finally, go back before the increase in height and set the element as resized by adding quickFitSetClass
    fontSize -= 1;
    jElement.addClass(quickFitSetClass).css("font-size", "" + fontSize + "px");

    return fontSize;
};
Vincent
źródło
1
Ponieważ ten skrypt będzie działał przy każdym zdarzeniu zmiany rozmiaru i / lub zmianie orientacji, nie polecam go używać. Zamiast używać rozwiązania opartego na javascript, poszukaj rozwiązania opartego na css, jak podano powyżej.
Pilatus,
1
Zmiany rozmiaru i orientacji są „rzadkimi” zdarzeniami, nie występują tutaj problemy z wydajnością. Jeśli wolisz, nie łącz się ze zdarzeniami (jeśli nie zmieniają one rozmiarów kontenerów, na przykład w przypadku witryn internetowych, które nie odpowiadają). Rozwiązania CSS nie działają we wszystkich przypadkach bez konieczności myślenia o czymkolwiek (np. O szerokości czcionki), tak jak to rozwiązanie.
Vincent
Zawarłem twoją odpowiedź jako funkcję jQuery. Otrzymuje maksymalną dozwoloną wysokość, minimalny i maksymalny rozmiar czcionki. Zobacz jsfiddle.net/oriadam/qzsy760k
oriadam
6

Ten komponent internetowy zmienia rozmiar czcionki, więc wewnętrzna szerokość tekstu odpowiada szerokości kontenera. Sprawdź wersję demo .

Możesz użyć tego w następujący sposób:

<full-width-text>Lorem Ipsum</full-width-text>
pomber
źródło
6

Przygotowałem prostą funkcję skalowania przy użyciu transformacji CSS zamiast rozmiaru czcionki. Możesz go używać wewnątrz dowolnego kontenera, nie musisz ustawiać zapytań o media itp. :)

Wpis na blogu: Skalowalny nagłówek CSS i JS o pełnej szerokości

Kod:

function scaleHeader() {
  var scalable = document.querySelectorAll('.scale--js');
  var margin = 10;
  for (var i = 0; i < scalable.length; i++) {
    var scalableContainer = scalable[i].parentNode;
    scalable[i].style.transform = 'scale(1)';
    var scalableContainerWidth = scalableContainer.offsetWidth - margin;
    var scalableWidth = scalable[i].offsetWidth;
    scalable[i].style.transform = 'scale(' + scalableContainerWidth / scalableWidth + ')';
    scalableContainer.style.height = scalable[i].getBoundingClientRect().height + 'px';
  }
}

Działające demo: https://codepen.io/maciejkorsan/pen/BWLryj

Maciej Korsan
źródło
Myślę, że OP szuka rozwiązania CSS.
m02ph3u5
5

Używaj zmiennych CSS

Nikt jeszcze nie wspomniał o zmiennych CSS, a to podejście działało dla mnie najlepiej, więc:

Załóżmy, że masz kolumnę na swojej stronie, która ma 100% szerokości ekranu użytkownika mobilnego, ale ma max-width800 pikseli, więc na pulpicie jest trochę miejsca po obu stronach kolumny. Umieść to u góry strony:

<script> document.documentElement.style.setProperty('--column-width', Math.min(window.innerWidth, 800)+'px'); </script>

A teraz możesz użyć tej zmiennej (zamiast wbudowanej vwjednostki), aby ustawić rozmiar swojej czcionki. Na przykład

p {
  font-size: calc( var(--column-width) / 100 );
}

To nie jest czysto CSS, ale jest całkiem blisko.


źródło
5

Spróbuj http://simplefocus.com/flowtype/ . To jest to, czego używam w moich witrynach i działało idealnie.

Pixel Reaper
źródło
Linki są niestabilne. Proszę wyjaśnić rozwiązanie bezpośrednio w swojej odpowiedzi. Nie chcę też klikać losowego linku z dowolną zawartością.
lilalinux
5

Mój problem był podobny, ale związany ze skalowaniem tekstu w nagłówku. Próbowałem Fit Font, ale musiałem przełączyć kompresor, aby uzyskać jakiekolwiek wyniki, ponieważ rozwiązał on nieco inny problem, podobnie jak Text Flow.

Więc napisałem mój własny mały plugin, który przyczynia się do zmniejszenia rozmiaru czcionki w celu dopasowania do pojemnika, zakładając, że masz overflow: hiddeni white-space: nowraptak, że nawet jeśli zmniejszenie czcionki do minimum nie pozwala pokazując pełny nagłówek, po prostu odcina co można pokazać.

(function($) {

  // Reduces the size of text in the element to fit the parent.
  $.fn.reduceTextSize = function(options) {
    options = $.extend({
      minFontSize: 10
    }, options);

    function checkWidth(em) {
      var $em = $(em);
      var oldPosition = $em.css('position');
      $em.css('position', 'absolute');
      var width = $em.width();
      $em.css('position', oldPosition);
      return width;
    }

    return this.each(function(){
      var $this = $(this);
      var $parent = $this.parent();
      var prevFontSize;
      while (checkWidth($this) > $parent.width()) {
        var currentFontSize = parseInt($this.css('font-size').replace('px', ''));
        // Stop looping if min font size reached, or font size did not change last iteration.
        if (isNaN(currentFontSize) || currentFontSize <= options.minFontSize ||
            prevFontSize && prevFontSize == currentFontSize) {
          break;
        }
        prevFontSize = currentFontSize;
        $this.css('font-size', (currentFontSize - 1) + 'px');
      }
    });
  };
})(jQuery);
Aram Kocharyan
źródło
5

Artystycznie, jeśli chcesz dopasować dwa lub więcej wierszy tekstu w tej samej szerokości, niezależnie od liczby znaków, masz dobre opcje.

Najlepiej jest znaleźć rozwiązanie dynamiczne, więc bez względu na wprowadzony tekst otrzymamy ładny wyświetlacz.

Zobaczmy, jak możemy się zbliżyć.

var els     = document.querySelectorAll(".divtext"),
refWidth    = els[0].clientWidth,
refFontSize = parseFloat(window.getComputedStyle(els[0],null)
                               .getPropertyValue("font-size"));

els.forEach((el,i) => el.style.fontSize = refFontSize * refWidth / els[i].clientWidth + "px")
#container {
  display: inline-block;
  background-color: black;
  padding: 0.6vw 1.2vw;
}
.divtext {
  display: table;
  color: white;
  font-family: impact;
  font-size: 4.5vw;
}
<div id="container">
  <div class="divtext">THIS IS JUST AN</div>
  <div class="divtext">EXAMPLE</div>
  <div class="divtext">TO SHOW YOU WHAT</div>
  <div class="divtext">YOU WANT</div>
</div>

Wszystko, co robimy, to pobrać szerokość ( els[0].clientWidth) i rozmiar czcionki ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) pierwszego wiersza jako odniesienie, a następnie po prostu odpowiednio obliczyć rozmiar czcionki kolejnych wierszy.

Redu
źródło
4

Spróbuj użyć wtyczki fitText , ponieważ rozmiary rzutni nie są rozwiązaniem tego problemu.

Po prostu dodaj bibliotekę:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

I zmień rozmiar czcionki, aby poprawić, ustawiając współczynnik tekstu:

$("#text_div").fitText(0.8);

Możesz ustawić maksymalne i minimalne wartości tekstu:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });
krolovolk
źródło
Jest to przydatne tylko w przypadku dużego wyświetlanego tekstu i nie jest zalecane w przypadku akapitów.
Shiv
3

Spójrz na mój kod. To sprawia, że font size smalleraby fitcokolwiek tam.

Ale myślę, że nie prowadzi to do dobrego wrażenia użytkownika

var containerWidth = $("#ui-id-2").width();
var items = $(".quickSearchAutocomplete .ui-menu-item");
var fontSize = 16;

items.each(function(){
    // Displaying a value depends sometimes on your case. You may make it block or inline-table instead of inline-block or whatever value that make the div take overflow width.
    $(this).css({"whiteSpace": "nowrap", "display": "inline-block"});
    while ($(this).width() > containerWidth){
         console.log("$(this).width()" + $(this).width() + "containerWidth" + containerWidth)
         $(this).css("font-size", fontSize -= 0.5);
    }
});

Wynik

Basheer AL-MOMANI
źródło
2

Jako awarię JavaScript (lub twoje jedyne rozwiązanie) możesz użyć mojej wtyczki jQuery Scalem , która umożliwia skalowanie względem elementu nadrzędnego (kontenera) poprzez przekazanie referenceopcji.

thdoan
źródło
2

W przypadku gdy jest to pomocne dla kogoś, większość rozwiązań w tym wątku polegała na zawijaniu tekstu w wiele wierszy, np. E.

Ale potem to znalazłem i zadziałało:

https://github.com/chunksnbits/jquery-quickfit

Przykładowe użycie:

$('.someText').quickfit({max:50,tolerance:.4})

pk1557
źródło
2

Zawsze miej swój element z tym atrybutem:

JavaScript: element.style.fontSize = "100%";

lub

CSS: style = "font-size: 100%;"

Kiedy idziesz na dużym formacie, powinny masz już skala zmienna obliczana (skala> 1 lub skala = 1). Następnie na pełnym ekranie:

document.body.style.fontSize = (scale * 100) + "%";

Działa ładnie z niewielkim kodem.

marirena
źródło
2

W przypadku tekstu dynamicznego ta wtyczka jest całkiem przydatna:

http://freqdec.github.io/slabText/

Po prostu dodaj CSS:

.slabtexted .slabtext
{
    display: -moz-inline-box;
    display: inline-block;
    white-space: nowrap;
}
.slabtextinactive .slabtext
{
    display: inline;
    white-space: normal;
    font-size: 1em !important;
    letter-spacing: inherit !important;
    word-spacing: inherit !important;
    *letter-spacing: normal !important;
    *word-spacing: normal !important;
}
.slabtextdone .slabtext
{
    display: block;
}

I skrypt:

$('#mydiv').slabText();
pajouk
źródło
2

To działało dla mnie:

Staram się przybliżać rozmiar czcionki na podstawie szerokości / wysokości uzyskanej z ustawienia `font-size: 10px`. Zasadniczo chodzi o to, że „jeśli mam 20 pikseli szerokości i 11 pikseli wysokości z` font-size: 10px`, to jaki byłby maksymalny rozmiar czcionki do matematyki dla kontenera o szerokości 50 pikseli i wysokości 30 pikseli? ”

Odpowiedź jest systemem podwójnych proporcji:

{20: 10 = 50: X, 11: 10 = 30: Y} = {X = (10 * 50) / 20, Y = (10 * 30) / 11}

Teraz X to rozmiar czcionki, który będzie pasował do szerokości, a Y to rozmiar czcionki, który będzie pasował do wysokości; weź najmniejszą wartość

function getMaxFontSizeApprox(el){
    var fontSize = 10;
    var p = el.parentNode;

    var parent_h = p.offsetHeight ? p.offsetHeight : p.style.pixelHeight;
    if(!parent_h)
        parent_h = 0;

    var parent_w = p.offsetHeight ? p.offsetWidth : p.style.pixelWidth;
    if(!parent_w)
        parent_w = 0;

    el.style.fontSize = fontSize + "px";

    var el_h = el.offsetHeight ? el.offsetHeight : el.style.pixelHeight;
    if(!el_h)
        el_h = 0;

    var el_w = el.offsetHeight ? el.offsetWidth : el.style.pixelWidth;
    if(!el_w)
        el_w = 0;

    // 0.5 is the error on the measure that JavaScript does
    // if the real measure had been 12.49 px => JavaScript would have said 12px
    // so we think about the worst case when could have, we add 0.5 to 
    // compensate the round error
    var fs1 = (fontSize*(parent_w + 0.5))/(el_w + 0.5);
    var fs2 = (fontSize*(parent_h) + 0.5)/(el_h + 0.5);

    fontSize = Math.floor(Math.min(fs1,fs2));
    el.style.fontSize = fontSize + "px";
    return fontSize;
}

Uwaga: argument funkcji musi być elementem rozpiętym lub elementem, który jest mniejszy niż jego element nadrzędny, w przeciwnym razie, jeśli elementy podrzędne i nadrzędne mają tę samą funkcję szerokości / wysokości, zawiodą.

Maurizio Ricci
źródło
1

Nie widzę żadnej odpowiedzi w odniesieniu do właściwości flex CSS, ale może być również bardzo przydatna.

Smart Coder
źródło
2
Czy możesz rozwinąć?
Peter Mortensen
1

Aby dopasować rozmiar czcionki do jego kontenera, a nie okna, zobacz resizeFont()funkcję, którą udostępniłem w tym pytaniu (kombinacja innych odpowiedzi, z których większość jest już tutaj linkowana). Jest uruchamiany za pomocą window.addEventListener('resize', resizeFont);.

Waniliowy JavaScript: zmiana rozmiaru czcionki-niesamowite, aby dopasować pojemnik

JavaScript:

function resizeFont() {
  var elements  = document.getElementsByClassName('resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _len = elements.length;
  for (_i = 0; _i < _len; _i++) {
    var el = elements[_i];
    el.style.fontSize = "100%";
    for (var size = 100; el.scrollHeight > el.clientHeight; size -= 10) {
      el.style.fontSize = size + '%';
    }
  }
}

Być może możesz użyć vw / vh jako rezerwowego, więc dynamicznie przypisujesz emlubrem jednostki za pomocą JavaScript, upewniając się, że czcionki są skalowane do okna, jeśli JavaScript jest wyłączony.

Zastosuj .resizeklasę do wszystkich elementów zawierających tekst, który chcesz skalować.

Uruchom funkcję przed dodaniem detektora zdarzeń zmiany rozmiaru okna. Następnie każdy tekst, który nie pasuje do jego kontenera, zostanie przeskalowany w dół podczas ładowania strony, a także podczas zmiany rozmiaru.

UWAGA: Wartość domyślna font-sizemusi być ustawiona na albo em, remalbo w %celu uzyskania właściwych wyników.

Powódź Jozuego
źródło
1

HTML

<div style="height:100px; width:200px;">
  <div id='qwe'>
    test
  </div>
</div>

Kod JavaScript dla maksymalizacji rozmiaru czcionki:

var fontSize, maxHeight, maxWidth, textElement, parentElement;
textElement = document.getElementById('qwe');
parentElement = textElement.parentElement;    
maxHeight = parentElement.clientHeight;
maxWidth = parentElement.clientWidth;
fontSize = maxHeight;
var minFS = 3, maxFS = fontSize;
while (fontSize != minFS) {
  textElement.style.fontSize = `${fontSize}px`;
  if (textElement.offsetHeight < maxHeight && textElement.offsetWidth <= maxWidth) {
    minFS = fontSize;
  } else{
    maxFS = fontSize;
  }
  fontSize = Math.floor((minFS + maxFS)/2);
}
textElement.style.fontSize = `${minFS}px`;
Ramil Gilfanov
źródło