Penskalaan font berdasarkan lebar kontainer

1189

Saya mengalami kesulitan mendapatkan kepala saya di sekitar scaling font.

Saat ini saya memiliki situs ini dengan tubuh font-size100%. 100% dari apa? Ini tampaknya dihitung pada 16 piksel.

Saya mendapat kesan bahwa 100% entah bagaimana akan merujuk pada ukuran jendela browser, tetapi tampaknya bukan karena itu selalu 16 piksel apakah jendela diubah ukurannya menjadi lebar ponsel atau desktop layar lebar penuh.

Bagaimana saya bisa membuat teks pada skala situs saya sehubungan dengan wadahnya? Saya mencoba menggunakan em, tetapi ini tidak skala baik.

Penalaran saya adalah bahwa hal-hal seperti menu saya menjadi squished ketika Anda mengubah ukuran, jadi saya perlu untuk mengurangi px font-sizedari .menuItemantara unsur-unsur lain dalam kaitannya dengan lebar wadah. (Misalnya, dalam menu di desktop besar, 22pxberfungsi dengan sempurna. Turun ke lebar tablet dan 16pxlebih sesuai.)

Saya sadar saya dapat menambahkan breakpoint, tapi saya benar-benar ingin teks untuk skala serta memiliki breakpoint tambahan, jika tidak, saya akan berakhir dengan ratusan breakpoint untuk setiap penurunan 100 piksel lebar untuk mengontrol teks.

Francesca
sumber
34
font-size: 100%;berarti 100% dari ukuran teks seharusnya (yaitu yang diwarisi dari induknya). Secara default yaitu 16px. Jadi jika Anda menggunakan 50%, itu akan menjadi ukuran font: 8px
Andy
31
Apa yang Anda cari disebut tipografi responsif atau ukuran viewport. css-tricks.com/viewport-sized-typography
gearsdigital
8
Berikan FitText lihat.
Patsy Issa
12
@Andy: Sebenarnya, "secara default" adalah apa pun yang pengguna atur ukuran teks browsernya, yang mungkin belum tentu mencapai 16px.
ScottS
1
lihat jawaban ini stackoverflow.com/a/28485608/4251431
Basheer AL-MOMANI

Jawaban:

1496

EDIT: Jika wadah bukan badan Trik CSS mencakup semua opsi Anda di Pas Teks ke Wadah .

Jika wadahnya adalah bodi, yang Anda cari adalah panjang persentase Viewport :

Panjang viewport-persentase relatif terhadap ukuran blok berisi awal . Ketika tinggi atau lebar blok yang mengandung awal diubah, mereka diskalakan sesuai. Namun, ketika nilai overflow pada elemen root adalah otomatis, bilah gulir mana pun diasumsikan tidak ada.

Nilai-nilainya adalah:

  • vw (% dari lebar viewport)
  • vh (% dari tinggi viewport)
  • vi (1% dari ukuran viewport ke arah sumbu inline elemen root)
  • vb (1% dari ukuran viewport ke arah sumbu blok elemen root)
  • vmin(lebih kecil dari vwatau vh)
  • vmax(lebih besar atau vwatau vh)

1 v * sama dengan 1% dari blok yang berisi awal.

Menggunakannya terlihat seperti ini:

p {
    font-size: 4vw;
}

Seperti yang Anda lihat, ketika lebar viewport bertambah, demikian juga font-size, tanpa perlu menggunakan kueri media.

Nilai-nilai ini adalah satuan ukuran, persis seperti pxatau em, sehingga mereka dapat digunakan untuk mengukur elemen lain juga, seperti lebar, margin, atau padding.

Dukungan peramban cukup bagus, tetapi kemungkinan Anda akan membutuhkan mundur, seperti:

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

Lihat statistik dukungan: http://caniuse.com/#feat=viewport-units .

Juga, periksa Trik CSS-untuk tampilan yang lebih luas: Tipografi Berukuran Viewport

Inilah artikel yang bagus tentang pengaturan ukuran minimum / maksimum dan melakukan kontrol lebih besar atas ukuran: Kontrol yang tepat atas tipografi responsif

Dan inilah artikel tentang mengatur ukuran Anda menggunakan calc () sehingga teks memenuhi viewport: http://codepen.io/CrocoDillon/pen/fBJxu

Juga, silakan lihat artikel ini, yang menggunakan teknik yang dijuluki 'memimpin cair' untuk menyesuaikan ketinggian garis juga. Memimpin dalam CSS

jbenjohnson
sumber
548
Tetapi bagaimana jika wadah itu bukan viewport (badan)?
Alex
12
@ Alex, itu wilayah JS. Coba FitText.jsalternatif yang disediakan di bagian bawah artikel yang disediakan @jbenjohnson.
Robbert
10
Di sinilah elemen yang disebut kueri masuk. Tidak seperti kueri media, kueri elemen akan mengukur berbagai hal berdasarkan blok yang berisi, bukan viewport, yang akan luar biasa! Namun sayangnya belum ada. Namun, beberapa polyfill dan proof-of-konsep ada jika Anda tertarik: coding.smashingmagazine.com/2013/06/25/… dan filamentgroup.com/lab/element_query_workarounds
jbenjohnson
139
Diturunkan karena ini tidak menjawab pertanyaan. Dia bertanya tentang wadah, bukan viewport. Kasus penggunaan yang sangat berbeda.
SongBox
6
"blok awal yang mengandung" mengacu pada elemen root. Ini bukan jawaban yang benar untuk pertanyaan yang diajukan.
Glyph
320

Tetapi bagaimana jika wadah itu bukan viewport (badan)?

Pertanyaan ini ditanyakan dalam komentar oleh Alex di bawah jawaban yang diterima .

Fakta itu tidak berarti vwtidak dapat digunakan sampai batas tertentu untuk ukuran wadah itu. Sekarang untuk melihat variasi sama sekali, kita harus mengasumsikan bahwa wadah itu fleksibel. Baik melalui persentase langsung widthatau melalui 100% minus margin. Intinya menjadi "dapat diperdebatkan" jika wadah selalu diatur ke, katakanlah, 200pxlebar - lalu tetapkan font-sizeyang berfungsi untuk lebar itu.

Contoh 1

Namun, dengan wadah lebar yang fleksibel, harus disadari bahwa dalam beberapa hal kontainer tersebut masih berukuran di luar viewport . Karena itu, masalah menyesuaikan vwpengaturan berdasarkan perbedaan ukuran persentase ke viewport, yang berarti memperhitungkan ukuran pembungkus induk. Ambil contoh ini :

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;
}

Dengan asumsi di sini divadalah anak dari body, itu adalah 50%dari 100%lebar itu, yang merupakan ukuran viewport dalam kasus dasar ini. Pada dasarnya, Anda ingin menetapkan vwyang akan terlihat bagus untuk Anda. Seperti yang Anda lihat dalam komentar saya di konten CSS di atas, Anda dapat "memikirkan" secara matematis sehubungan dengan ukuran viewport penuh, tetapi Anda tidak perlu melakukan itu. Teks akan "melentur" dengan wadah karena wadah melentur dengan mengubah ukuran viewport. PEMBARUAN: inilah contoh dua wadah dengan ukuran berbeda .

Contoh 2

Anda dapat membantu memastikan ukuran viewport dengan memaksa penghitungan berdasarkan itu. Pertimbangkan contoh ini :

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;
}

Ukurannya masih berdasarkan dari viewport, tetapi pada dasarnya diatur berdasarkan ukuran kontainer itu sendiri.

Haruskah Ukuran Kontainer Berubah Secara Dinamis ...

Jika ukuran elemen kontainer akhirnya berubah secara dinamis, persentase hubungannya baik melalui @media breakpoints atau melalui JavaScript, maka apa pun "target" dasar akan perlu perhitungan ulang untuk mempertahankan "hubungan" yang sama untuk ukuran teks.

Ambil contoh # 1 di atas. Jika divdiubah menjadi 25%lebar oleh salah satu @mediaatau JavaScript, maka pada saat yang sama, font-sizeperlu menyesuaikan dalam permintaan media atau dengan JavaScript ke perhitungan baru 5vw * .25 = 1.25. Ini akan menempatkan ukuran teks pada ukuran yang sama seperti jika "lebar" 50%wadah asli dikurangi setengah dari ukuran viewport, tetapi sekarang telah berkurang karena perubahan dalam perhitungan persentase sendiri.

Sebuah tantangan

Dengan fungsi CSS3 yangcalc() digunakan, akan menjadi sulit untuk menyesuaikan secara dinamis, karena fungsi itu tidak berfungsi untuk font-sizetujuan saat ini. Jadi Anda tidak bisa melakukan penyesuaian CSS 3 murni jika lebar Anda berubah calc(). Tentu saja, penyesuaian kecil lebar untuk margin mungkin tidak cukup untuk menjamin perubahan apa pun font-size, jadi mungkin tidak masalah.

ScottS
sumber
(Ada bug Chrome dengan panjang viewport-persentase dan mengubah ukuran jendela: code.google.com/p/chromium/issues/detail?id=124331 )
fiftydot
@ thirtydot: Sangat disayangkan (tapi bagus untuk diperhatikan, terima kasih). Semoga bug ini segera teratasi, tetapi sepertinya sudah ada beberapa saat.
ScottS
20
Jawaban yang bagus, bagaimanapun, itu tidak akan berfungsi jika elemen yang mengandung memiliki lebar maksimum.
Himmators
3
@KristofferNolgren: Itu berhubungan dengan dua poin yang dibuat dalam jawaban saya: (1) "dengan asumsi bahwa wadah dalam beberapa cara fleksibel dalam ukuran" (sekali 'max-width' tercapai, tidak lagi melentur, sehingga kemudian ada masalah ). (2) Jika seseorang dapat menentukan pada titik mana 'max-width' akan tercapai, maka seperti yang saya catat, Anda dapat mengatur @mediabreak point untuk mengubah bagaimana ukuran font pada saat itu (pada dasarnya memberikan ukuran tetap saat mencapai max-width) . Hanya pemikiran untuk bekerja dengan suatu max-widthsituasi.
ScottS
Apakah Anda pikir Anda bisa melempar ketika elemen wadah berubah secara dinamis melalui pertanyaan media? Saya tidak yakin saya mengerti.
J82
59

Solusi dengan 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/


Solusi dengan SVG dan pembungkus teks menggunakan 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
sumber
1
Ide ini terlihat bagus, pada awalnya. Maka Anda sadar bahwa Anda tidak dapat dengan mudah mengontrol font pada SVG di dalam <html>. Font berbeda pada ponsel dan desktop, yang memengaruhi lebar akhir.
Stopi
@Stopi apa pendapat Anda tentang solusi iFrame? contoh
Dantio
10
Anda benar-benar dapat menata SVG dari HTML / CSS
gman
1
SVG dapat ditata dengan css jika svg inline (jangan gunakan tag img).
8
Ini adalah solusi terbaik dan paling dapat diprediksi yang berskala berdasarkan pada wadah dinamis.
JoshuaDavid
35

Dalam salah satu proyek saya, saya menggunakan "campuran" antara vw dan vh untuk menyesuaikan ukuran font dengan kebutuhan saya, misalnya:

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

Saya tahu ini tidak menjawab pertanyaan OP, tapi mungkin itu bisa menjadi solusi bagi orang lain.

lsblsb
sumber
3
Anda mungkin lebih baik menggunakan vmindan / atau vmaxsebagai gantinya.
sebastian_k
4
alat dev krom menyebut ini nilai properti tidak valid
phil294
31

Solusi murni-CSS dengan calc(), unit CSS dan matematika

Ini bukan apa yang diminta OP, tetapi mungkin membuat hari seseorang. Jawaban ini tidak mudah untuk memberi makan dan perlu penelitian pada pengembang.

Akhirnya saya datang untuk mendapatkan solusi murni-CSS untuk penggunaan ini calc()dengan unit yang berbeda. Anda akan membutuhkan pemahaman matematika dasar tentang rumus untuk menentukan ekspresi Anda calc().

Ketika saya mengatasinya, saya harus mendapatkan header responsif selebar satu halaman dengan beberapa orang tua di DOM. Saya akan menggunakan nilai saya di sini, menggantinya dengan nilai Anda sendiri.

Untuk matematika

Anda akan perlu:

  • Rasio yang disesuaikan dengan baik di beberapa viewport. Saya menggunakan 320 piksel, jadi saya mendapat tinggi 24 piksel dan lebar 224 piksel, jadi rasionya adalah 9.333 ... atau 28/3
  • Lebar kontainer, saya punya padding: 3emdan lebar penuh jadi ini harus100wv - 2 * 3em

X adalah lebar wadah, jadi gantilah dengan ekspresi Anda sendiri atau sesuaikan nilainya untuk mendapatkan teks satu halaman penuh. Radalah rasio yang akan Anda miliki. Anda bisa mendapatkannya dengan menyesuaikan nilai di beberapa viewport, memeriksa lebar dan tinggi elemen dan menggantinya dengan nilai Anda sendiri. Juga, itu 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

Dan bang! Berhasil! saya menulis

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

ke header saya dan itu disesuaikan dengan baik di setiap viewport.

Tetapi bagaimana cara kerjanya?

Kita butuh konstanta di sini. 100vwberarti viewport lebar penuh, dan tujuan saya adalah untuk membangun header lebar penuh dengan beberapa padding.

Rasio. Memperoleh lebar dan tinggi dalam satu viewport memberi saya rasio untuk bermain, dan dengan rasio saya tahu berapa tinggi seharusnya dalam lebar viewport lainnya. Menghitungnya dengan tangan akan membutuhkan banyak waktu dan setidaknya membutuhkan banyak bandwidth, jadi itu bukan jawaban yang baik.

Kesimpulan

Saya bertanya-tanya mengapa tidak ada yang tahu ini dan beberapa orang bahkan mengatakan bahwa ini tidak mungkin untuk bermain-main dengan CSS. Saya tidak suka menggunakan JavaScript dalam menyesuaikan elemen, jadi saya tidak menerima jawaban JavaScript (dan lupakan jQuery) tanpa menggali lebih banyak. Semua dalam semua, ada baiknya untuk mengetahui ini dan ini adalah satu langkah untuk implementasi murni-CSS dalam desain situs web.

Saya minta maaf atas konvensi yang tidak biasa dalam teks saya, saya bukan penutur asli dalam bahasa Inggris dan saya juga cukup baru untuk menulis jawaban Stack Overflow.

Perlu juga dicatat bahwa kita memiliki scrollbar jahat di beberapa browser. Misalnya, ketika menggunakan Firefox, saya perhatikan bahwa itu 100vwberarti lebar penuh viewport, membentang di bawah scrollbar (di mana konten tidak dapat diperluas!), Sehingga teks bandwidth penuh harus dibatasi dengan hati-hati dan lebih disukai diuji dengan banyak browser dan perangkat.

hegez
sumber
13
Solusi ini hanya berfungsi JIKA (1) Anda tahu font, (2) font tersedia pada perangkat pengguna, dan (3) teks selalu sama. Ini menjadikannya case-use yang sangat terbatas.
Andrei Volgin
saya tidak mengerti bagaimana jika kontainer saya diperbaiki dengan contoh: 640px dan rasio 16: 9. kalori apa yang harus saya tulis?
pery mimon
1
Lebar kontainer Anda xadalah 640px dan perbandingan r16: 9, jadi: x = 640px, r = 16 / 9, y = x / r = 640px / (16 / 9) = 360px
hegez
Catatan: ini hanya berfungsi jika Anda benar-benar memiliki teks berukuran 16: 9, yang merupakan situasi aneh. Mungkin membaca jawabannya kedua kalinya dapat membantu. Juga, ini hanya berfungsi untuk satu-liners.
hegez
Sejujurnya Anda tidak menjelaskan "Rasio yang disesuaikan dengan baik di beberapa viewport. Saya menggunakan 320 piksel, jadi saya mendapat tinggi 24 piksel dan lebar 224 piksel, jadi rasionya adalah 9.333 ... atau 28/3" Saya sarankan menjelaskan rasio tersebut. sedikit lagi. Apa yang diwakili oleh rasio?
3limin4t0r
28

Ada filosofi besar untuk masalah ini.

Hal termudah untuk dilakukan adalah memberikan ukuran font tertentu ke badan (saya sarankan 10), dan kemudian semua elemen lain akan memiliki font mereka di ematau rem. Saya akan memberi Anda contoh untuk memahami unit-unit itu. Emselalu relatif terhadap induknya:

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 selalu relatif terhadap tubuh:

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 */

Dan kemudian Anda bisa membuat skrip yang akan memodifikasi ukuran font relatif terhadap lebar kontainer Anda. Tapi ini bukan yang saya sarankan. Karena dalam wadah selebar 900 piksel misalnya Anda akan memiliki pelemen dengan ukuran font 12 piksel katakanlah. Dan menurut ide Anda itu akan menjadi wadah 300 piksel dengan ukuran font 4 piksel. Harus ada batas bawah.

Solusi lain akan dengan permintaan media, sehingga Anda dapat mengatur font untuk lebar yang berbeda.

Tetapi solusi yang saya sarankan adalah menggunakan perpustakaan JavaScript yang membantu Anda. Dan fittext.js yang saya temukan sejauh ini.

Dan Ovidiu Boncut
sumber
6
The remunit relatif terhadap elemen root, yang berarti htmlelemen, bukan bodyelemen. Elemen root di DOM adalah htmltag. developer.mozilla.org/en-US/docs/Web/CSS/length .. remselalu relatif terhadap htmltag, yang merupakan elemen root, bukan body tag .. tapi jawaban yang bagus :)
Jonathan Marzullo
fittext.js membuat pekerjaan selesai, saya menyarankan solusi itu!
Jacek Dziurdzikowski
FitText adalah pemenang untuk saya. Mencoba beberapa alternatif tetapi ini tampaknya yang paling sederhana dan terintegrasi dengan baik dengan Drupal / Backdrop CMS. github.com/davatron5000/FitText.js
Auxiliary Joel
23

Inilah fungsinya:

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

Lalu, konversi semua ukuran font elemen elemen anak Anda ke ematau %.

Kemudian tambahkan sesuatu seperti ini ke kode Anda untuk mengatur ukuran font dasar.

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

http://jsfiddle.net/0tpvccjt/

tnt-rox
sumber
1
Sejauh ini ini adalah solusi terbaik.
Siswa
Praktik buruk dan sangat tidak efisien
Jack Giffin
@tntrox Tidak efisien seperti saat ini, itu jauh lebih tidak efisien 4 tahun yang lalu. Saya menolak jawaban ini sebagai pengganti alternatif yang jauh lebih baik. Ya, untuk dukungan IE, orang perlu Javascript. Tapi, orang tidak perlu Javascript yang mengerikan ini.
Jack Giffin
3
Saya kira ketidaktahuan saya muncul di sini. Tapi MENGAPA hal di atas mengerikan?
Saya tidak berpikir itu mengerikan. Saya akan merekomendasikan beberapa perubahan format kecil agar lebih mudah dibaca. Saya akan menempatkan masing-masing var pada baris yang terpisah setidaknya. Mungkin tidak perlu return thisdi akhir fungsi. Untuk kinerja, Anda mungkin juga ingin men-debo onresize agar tidak digambar ulang saat Anda menyeret. Ini adalah beberapa kode yang cukup sederhana, sehingga seseorang dapat mendasarkan solusi yang ditingkatkan di atasnya dengan sedikit usaha.
Mnebuerquo
19

Ada cara untuk melakukan ini tanpa JavaScript!

Anda dapat menggunakan gambar SVG sebaris. Anda dapat menggunakan CSS pada SVG jika inline. Anda harus ingat bahwa menggunakan metode ini berarti gambar SVG Anda akan merespons ukuran wadahnya.

Coba gunakan solusi berikut ...

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;
}

Contoh: https://jsfiddle.net/k8L4xLLa/32/

Ingin sesuatu yang lebih mencolok?

Gambar SVG juga memungkinkan Anda melakukan hal-hal keren dengan bentuk dan sampah. Lihat kasus penggunaan hebat ini untuk teks yang dapat diskalakan ...

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

Peter Mortensen
sumber
4
Solusi ini tidak berbeda dengan yang diterima dengan vwukuran. jika Anda mengubah teks, semuanya menjadi tidak masuk akal.
N69S
14

Ini mungkin bukan super praktis, tetapi jika Anda ingin font menjadi fungsi langsung dari orang tua, tanpa memiliki JavaScript yang mendengarkan / mengulang (interval) untuk membaca ukuran div / halaman, ada cara untuk melakukannya . Iframes.

Apa pun di dalam iframe akan mempertimbangkan ukuran iframe sebagai ukuran viewport. Jadi triknya adalah membuat iframe yang lebarnya adalah lebar maksimum yang Anda inginkan dari teks Anda, dan yang tingginya sama dengan tinggi maksimum * rasio aspek teks tertentu.

Mengesampingkan batasan bahwa unit viewport juga tidak bisa datang bersama dengan unit induk samping untuk teks (seperti dalam, memiliki% ukuran berperilaku seperti orang lain), unit viewport memang menyediakan alat yang sangat kuat: bisa mendapatkan dimensi minimum / maksimum . Anda tidak dapat melakukan itu di tempat lain - Anda tidak bisa mengatakan ... membuat ketinggian div ini menjadi lebar dari orangtua * sesuatu.

Yang sedang dikatakan, triknya adalah menggunakan vmin, dan untuk mengatur ukuran iframe sehingga [fraksi] * tinggi total adalah ukuran font yang baik ketika tinggi adalah dimensi pembatas, dan [fraksi] * total lebar ketika lebar adalah lebar dimensi pembatas. Inilah sebabnya mengapa tinggi harus merupakan produk dari lebar dan rasio aspek.

Sebagai contoh khusus saya, Anda punya

.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);
}

Gangguan kecil dengan metode ini adalah Anda harus secara manual mengatur CSS iframe. Jika Anda melampirkan seluruh file CSS, itu akan memakan banyak bandwidth untuk banyak area teks. Jadi, yang saya lakukan adalah melampirkan aturan yang saya inginkan langsung dari CSS saya.

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

Anda dapat menulis fungsi kecil yang mendapatkan aturan CSS / semua aturan CSS yang akan memengaruhi area teks.

Saya tidak bisa memikirkan cara lain untuk melakukannya tanpa memiliki bersepeda / mendengarkan JavaScript. Solusi sebenarnya adalah browser menyediakan cara untuk mengukur teks sebagai fungsi dari wadah induk dan juga menyediakan fungsionalitas vmin / vmax yang sama.

JSFiddle: https://jsfiddle.net/0jr7rrgm/3/ (klik sekali untuk mengunci kotak merah ke mouse, dan klik lagi untuk melepaskan)

Sebagian besar JavaScript di biola hanya fungsi klik-tarik kustom saya.

Roman Rekhler
sumber
@quemeful Tidak demikian ketika kita membawa atribut 'baru' dan 'mengkilap' (drumroll ...) srcdoc: jsfiddle.net/wauzgob6/3
Jack Giffin
9

Menggunakan vw, em& co. bekerja pasti, tetapi IMO selalu membutuhkan sentuhan manusia untuk fine-tuning.

Berikut ini skrip yang baru saja saya tulis berdasarkan jawaban @ tnt-rox ' yang mencoba mengotomatiskan sentuhan manusia itu:

$('#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>

Ini pada dasarnya mengurangi ukuran font menjadi 1emdan kemudian mulai bertambah sebesar 0,1 sampai mencapai lebar maksimum.

JSFiddle

WoodrowShigeru
sumber
1
Memberi +1 hanya untuk seseorang yang emsmembutuhkan sentuhan manusia dan ritme vertikal bukanlah semacam sihir.
serraosays
7

100% relatif terhadap ukuran font dasar, yang, jika Anda belum menyetelnya, akan menjadi agen pengguna default browser.

Untuk mendapatkan efek yang Anda inginkan, saya akan menggunakan sepotong kode JavaScript untuk menyesuaikan ukuran font dasar relatif terhadap dimensi jendela.

scoota269
sumber
7

Di dalam CSS Anda, coba tambahkan ini di bagian bawah mengubah lebar 320 piksel untuk di mana pun desain Anda mulai rusak:

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

        body { font-size: 1em; }

    }

Kemudian berikan ukuran font dalam "px" atau "em" seperti yang Anda inginkan.

Chunky
sumber
7

Solusi saya sendiri, berbasis jQuery, bekerja dengan secara bertahap meningkatkan ukuran font sampai wadah mendapatkan peningkatan tinggi yang besar (artinya mendapat jeda baris).

Ini cukup sederhana, tetapi bekerja dengan cukup baik, dan sangat mudah digunakan. Anda tidak perlu tahu apa - apa tentang font yang digunakan, semuanya diurus oleh browser.

Anda dapat bermain dengannya di http://jsfiddle.net/tubededentifrice/u5y15d0L/2/

Keajaiban terjadi di sini:

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
sumber
1
Karena skrip ini akan berjalan pada setiap acara pengubahan ukuran dan / atau perubahan orientasi, saya tidak merekomendasikan untuk menggunakan ini. Alih-alih menggunakan solusi berbasis javascript mencari solusi berbasis css seperti yang diberikan di atas.
Pilatus
1
Ubah ukuran dan perubahan orientasi adalah peristiwa "langka", tidak ada masalah kinerja di sini. Jika Anda mau, jangan ikat ke acara (jika mereka tidak mengubah ukuran wadah misalnya, untuk situs web yang tidak responsif). Solusi CSS tidak berfungsi dalam semua kasus tanpa harus memikirkan apa pun (seperti lebar font atau lebih) seperti solusi ini.
Vincent
Saya membungkus jawaban Anda sebagai fungsi jQuery. Ini menerima tinggi font yang diizinkan, min dan ukuran font maks. Lihat jsfiddle.net/oriadam/qzsy760k
oriadam
6

Komponen web ini mengubah ukuran font sehingga lebar teks bagian dalam cocok dengan lebar kontainer. Periksa demo .

Anda bisa menggunakannya seperti ini:

<full-width-text>Lorem Ipsum</full-width-text>
pomber
sumber
6

Saya telah menyiapkan fungsi skala sederhana menggunakan transformasi CSS alih-alih ukuran font. Anda dapat menggunakannya di dalam wadah apa pun, Anda tidak perlu mengatur pertanyaan media, dll. :)

Posting blog: Lebar header CSS & JS yang dapat diukur

Kode:

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';
  }
}

Demo yang berfungsi: https://codepen.io/maciejkorsan/pen/BWLryj

Maciej Korsan
sumber
Saya pikir OP sedang mencari solusi CSS.
m02ph3u5
5

Gunakan Variabel CSS

Belum ada yang menyebutkan variabel CSS, dan pendekatan ini bekerja paling baik untuk saya, jadi:

Katakanlah Anda memiliki kolom pada halaman Anda yang 100% dari lebar layar pengguna ponsel, tetapi memiliki max-width800px, jadi pada desktop ada beberapa ruang di kedua sisi kolom. Letakkan ini di bagian atas halaman Anda:

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

Dan sekarang Anda dapat menggunakan variabel itu (bukan vwunit bawaan) untuk mengatur ukuran font Anda. Misalnya

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

Ini bukan pendekatan CSS murni , tapi cukup dekat.


sumber
5

Coba http://simplefocus.com/flowtype/ . Ini yang saya gunakan untuk situs saya, dan sudah berfungsi dengan baik.

Pixel Reaper
sumber
Tautan mudah berubah. Tolong jelaskan solusinya dalam jawaban Anda. Juga, saya tidak ingin mengklik beberapa tautan acak dengan konten apa pun.
lilalinux
5

Masalah saya mirip, tetapi terkait dengan penskalaan teks dalam tajuk. Saya mencoba Fit Font, tapi saya perlu menghidupkan kompresor untuk mendapatkan hasil, karena itu memecahkan masalah yang sedikit berbeda, seperti halnya Text Flow.

Jadi saya menulis plugin kecil saya sendiri yang mengurangi ukuran font agar sesuai dengan wadah, dengan asumsi Anda memilikinya overflow: hiddendan white-space: nowrapbahkan jika mengurangi font ke minimum tidak memungkinkan menampilkan judul lengkap, itu hanya memotong apa yang dapat ditampilkan.

(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
sumber
5

Secara artistik, jika Anda perlu memasukkan dua atau lebih baris teks dalam lebar yang sama terlepas dari jumlah karakternya, maka Anda memiliki opsi yang bagus.

Yang terbaik adalah menemukan solusi dinamis sehingga teks apa pun yang dimasukkan kita berakhir dengan tampilan yang bagus.

Mari kita lihat bagaimana kita mendekati.

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>

Yang kami lakukan adalah mendapatkan lebar ( els[0].clientWidth) dan ukuran font ( parseFloat(window.getComputedStyle(els[0],null).getPropertyValue("font-size"))) dari baris pertama sebagai referensi dan kemudian hanya menghitung ukuran font baris berikutnya sesuai.

Redu
sumber
4

Coba gunakan fitText plugin , karena ukuran Viewport bukanlah solusi dari masalah ini.

Cukup tambahkan perpustakaan:

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

Dan ubah ukuran font untuk dikoreksi dengan menyetel koefisien teks:

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

Anda dapat mengatur nilai teks maksimum dan minimum:

$("#text_div").fitText(0.8, { minFontSize: '12px', maxFontSize: '36px' });
krolovolk
sumber
Ini hanya berguna untuk teks layar besar dan tidak direkomendasikan untuk paragraf.
Shiv
3

Lihatlah kode saya. Itu membuat font size smalleruntuk fitapa pun di sana.

Tapi saya pikir ini tidak mengarah pada pengalaman pengguna yang baik

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);
    }
});

Hasil

Basheer AL-MOMANI
sumber
2

Sebagai fallback JavaScript (atau solusi tunggal Anda), Anda dapat menggunakan plugin jQuery Scalem saya , yang memungkinkan Anda mengatur skala relatif terhadap elemen induk (wadah) dengan melewatkan referenceopsi.

Terima kasih
sumber
2

Jika bermanfaat bagi siapa pun, sebagian besar solusi di utas ini adalah membungkus teks menjadi beberapa baris, bentuk e.

Tetapi kemudian saya menemukan ini, dan ternyata berhasil:

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

Contoh penggunaan:

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

pk1557
sumber
2

Selalu miliki elemen Anda dengan atribut ini:

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

atau

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

Saat Anda menggunakan layar penuh, Anda seharusnya sudah memiliki variabel skala yang dihitung (skala> 1 atau skala = 1). Kemudian, pada layar penuh:

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

Ini bekerja dengan baik dengan kode kecil.

marirena
sumber
2

Untuk teks dinamis, plugin ini cukup berguna:

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

Cukup tambahkan 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;
}

Dan skripnya:

$('#mydiv').slabText();
pajouk
sumber
2

Ini bekerja untuk saya:

Saya mencoba memperkirakan ukuran font berdasarkan lebar / tinggi yang didapat dari pengaturan `font-size: 10px`. Pada dasarnya, idenya adalah "jika saya memiliki lebar 20 piksel dan tinggi 11 piksel dengan` ukuran font: 10px`, jadi apa ukuran font maksimum untuk menghitung wadah dengan lebar 50 piksel dan tinggi 30 piksel? "

Jawabannya adalah sistem proporsi ganda:

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

Sekarang X adalah ukuran font yang akan cocok dengan lebar, dan Y adalah ukuran font yang akan cocok dengan tinggi; ambil nilai terkecil

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;
}

NB: argumen fungsi harus elemen rentang atau elemen yang lebih kecil dari induknya, jika anak-anak dan orang tua keduanya memiliki fungsi lebar / tinggi yang sama akan gagal.

Maurizio Ricci
sumber
1

Saya tidak melihat jawaban apa pun dengan merujuk ke properti fleksibel CSS, tetapi ini bisa sangat berguna juga.

Smart Coder
sumber
2
Bisakah Anda menguraikan?
Peter Mortensen
1

Untuk membuat ukuran font sesuai dengan wadahnya, daripada jendela, lihat resizeFont()fungsi yang saya bagikan dalam pertanyaan ini (kombinasi jawaban lain, yang sebagian besar sudah ditautkan di sini). Dipicu menggunakan window.addEventListener('resize', resizeFont);.

Vanilla JavaScript: Ubah ukuran font-dahsyat agar pas dengan wadah

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 + '%';
    }
  }
}

Anda mungkin dapat menggunakan vw / vh sebagai fallback, jadi Anda secara dinamis menetapkan ematau remunit menggunakan JavaScript, memastikan bahwa font melakukan skala ke jendela jika JavaScript dinonaktifkan.

Terapkan .resizekelas ke semua elemen yang mengandung teks yang ingin Anda diskalakan.

Trigger fungsi sebelum menambahkan ukuran jendela pendengar acara. Kemudian, teks apa pun yang tidak sesuai dengan wadahnya akan diperkecil saat halaman dimuat, serta saat diubah ukurannya.

CATATAN: Default font-sizeharus diatur ke salah satu em, rematau %untuk mencapai hasil yang tepat.

Joshua Flood
sumber
1

HTML

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

Kode JavaScript untuk memaksimalkan ukuran font:

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
sumber