@font-face loader

Zilele trecute am avut nevoie să fac mici ajustări la o pagină în funcție de starea fonturilor custom. Pentru că uneori aceste fonturi sunt mult diferite de orice fallback, iar până în momentul încărcării există un flash enervant.

Cum Typekit nu a fost o opțiune în acest caz, a trebuit să caut alternative. Și am găsit WebFont Loader. Câteva linii de cod scrise în head și aveam totul la locul lui:

var fontsAreLoaded = false;
WebFont.load({
  custom: {
    families: ['UbuntuCondensedRegular'],
    urls: [ 'assets/fonts/custom-font.css' ]
  },
  active: function(){ fontsAreLoaded = true; }
});

Cum loaderul este încărcat primul, imediat după CSS (știu, sunt un nenorocit care încarcă 10kb de js în header) iar restul de scripturi sunt încărcate mult mai târziu (fiind situate în footer), am avut nevoie de un trick. Prin urmare, în footer, chiar înainte de body am așa ceva:

function checkIfFontsAreReady() {
  if( fontsAreLoaded ){
    $(window).trigger('custom-font-ready');
  }else {
    window.setTimeout( checkIfFontsAreReady, 20 );
  }
};
checkIfFontsAreReady();

13 Comentarii to “@font-face loader”

  1. OK si eu am dat de script-ul acela recent insa nu inteleg cum ai scapat de acel “flash enervant” fara fallback la alte font-uri.

  2. Staicu Ionuț-Bogdan

    Deși nu recomand, probabil ceva de genul ăsta:

    body { display:none }
    
    $(window).on('custom-font-ready', function(){
      $('body').show();
    });
    

    Dar o să ai site-ul inutilizabil până se încarcă fonturile (chiar nu mă interesează fonturi custom atunci când îți vizitez site-ul de pe o conexiune lentă).

    Cred că fallback & graceful degradataion sunt cuvintele cheie în toată povestea asta :)

  3. Da deci practic script-ul nu rezolva problema ci doar inlocuieste flash-ul cu font-uri normale dar care pentru 0,2-1 secunde strica tot aspectul site-ului. Plus ca necesita dependente si cod in plus.

    Eu unul prefer pagina alba (care se poate rezolva pana intr-o anumita limita) atunci cand font-urile fallback sunt prea diferite. Nu este “graceful degradataion” dar depinde si de target; eu de exemplu pt. orice mai jos de IE9 redirectionez spre Chrome download.

    Fix : S3 combinat cu CloudFlare, macar static1 si static2 cookieless sau daca vrei performanta pura Akamai i.e. Rackspace CloudFiles.

  4. Staicu Ionuț-Bogdan

    Te invit să faci asta când ți se cere în mod express compatibilitate IE7+ cu niște politici de securitate draconice (de exemplu nu poate executa nici o aplicație „aprobată” de sysadmin, cookies sunt acceptate doar de pe câteva domenii etc) iar totul trebuie să meargă într-un intranet, cu o conexiune extrem de instabilă în exterior.

    Mici curiozități:

    – Ce faci dacă CDN-ul este picat (s-a întâmplat de cel puțin două ori în ultimul an să pice S3-ul, de exemplu)? Utilizatorul nu vede pagina?
    – Ce se întâmplă dacă utilizatorul dezactivează JS? (fie cu bună știință, fie pur și simplu nu se încarcă JS-ul)
    – De ce obligi utilizatorul să descarce minim 30kb extra doar pentru a putea vedea site-ul? (și soluția propusă de mine descarcă ceva kb extra, dar nu limitează cu nimic utilizatorul)

    Mici note de luat în seamă pe viitor:
    – nu toți au conexiuni de 100Mb/s (din contră aș putea spune; România este doar o excepție fericită, dar restul Europei se zbate cu o conexiune mizeră la un preț ridicol de mare – cel puțin 40-50€ pentru o conexiune incredibil de lentă; idem pentru US)
    – nu toți știu să instaleze Chrome/Chrome frame
    – nu toți au trafic nelimitat (iar aceștia încearcă să dezactiveze tot ce papă resurse aiurea: js, imagini)

    Da, într-o lume perfectă renunți la suport pentru browsere vechi. Dar în momentul în care pierzi clienți, nu poți renunța la browsere vechi, fiind necesar ca site-ul să se degradeze frumos.

    Nu uita că XP (implicit IE8) are încă o piață uriașă.

  5. – Ce faci dacă CDN-ul este picat (s-a întâmplat de cel puțin două ori în ultimul an să pice S3-ul, de exemplu)? Utilizatorul nu vede pagina?
    – S3 + CloudFlare = 2 CDN-uri iar daca combini cu Akamai deja esti paranoic :-)

    – Ce se întâmplă dacă utilizatorul dezactivează JS? (fie cu bună știință, fie pur și simplu nu se încarcă JS-ul)
    – pai ce lagatura are JS-ul aici ? am zis doar ca font-urile sa fie mutate pe CDN reducand spre minim acel flash pana ele devin disponibile i.e. no-JS-needed

    – De ce obligi utilizatorul să descarce minim 30kb extra doar pentru a putea vedea site-ul? (și soluția propusă de mine descarcă ceva kb extra, dar nu limitează cu nimic utilizatorul)
    – De ce oamenii obliga utilizatorii sa descarce jQuery ? eu unul am renuntat la jQuery si mai nou chiar la Zepto asa ca pot reinvesti acei ~27K in font-uri

    – nu toți au conexiuni de 100Mb/s (din contră aș putea spune; România este doar o excepție fericită, dar restul Europei se zbate cu o conexiune mizeră la un preț ridicol de mare – cel puțin 40-50€ pentru o conexiune incredibil de lentă; idem pentru US)
    – iarasi revin la parabola cu jQuery/Zepto

    – nu toți știu să instaleze Chrome/Chrome frame
    – complet de acord, daca din target-ul respectiv fac parte si ei, nu ai ce face

    – nu toți au trafic nelimitat (iar aceștia încearcă să dezactiveze tot ce papă
    resurse aiurea: js, imagini)
    – again : tai intr-o parte adaugi in alta :-) prefer sa scriu VanillaJS si site-ul sa foloseasca font-urile custom decat invers.

  6. Staicu Ionuț-Bogdan

    pai ce lagatura are JS-ul aici ? am zis doar ca font-urile sa fie mutate pe CDN reducand spre minim acel flash pana ele devin disponibile i.e. no-JS-needed

    Eu unul prefer pagina alba (care se poate rezolva pana intr-o anumita limita) atunci cand font-urile fallback sunt prea diferite.

    Cum faci pagina albă până se încarcă fonturile?

    O bibliotecă (jQuery, underscore etc) este mult mai utilă decât un font. Poate tu ai timp să te lupți cu diferențele dintre browsere. Sau poate ai timp să-ți faci propriile plugins (sortable, draggable, autocomplete, calendar; chestii utile mai peste tot). Poate tu ai nevoie doar de compatibilitate cu webkit. Eu nu am timp și nici nu-mi permit luxul de a nu oferi suport pentru toate browserele (poate doar în anumite situații, dar mult mai rar decât mi-ar face plăcere)

    Am vaga bănuială că ești în situația să crezi că un CDN este răspunsul la toate problemele avute.

    Mai știu eu pe cineva care credea că „Answer to the Ultimate Question of Life, the Universe, and Everything” este Singelton :D

  7. Dap, clar solutia cu VanillaJS nu este aplicabila oriunde insa un CDN ar ajuta mai ales ca poti incerca unul free (e.g. CloudFlare in care daca setezi cum trebuie cateva reguli poti filtra sa fie “on” doar pe anumite resurse)

    Cum faci pagina albă până se încarcă fonturile?

    Legat de pagina alba, depinde de context :

    – pentru un blog efectul de pagina alba il poti obtine fara JS si este chiar mai ok sa arate background-ul pentru ca functioneaza ca un “hei uite ceva s-a incarcat” :-)

    – pentru orice altceva, da, este problema spinoasa:

    -> Pentru o aplicatie, serviciu sau ceva asemanator si nu poti incarca font-uri din locurile clasice fie as merge pe CDN fie fallback dar in niciun caz pe o varianta cu pagina alba cred ca stim amandoi de ce :-)

    PS : de ce nu folosesti _markdown_ ?

  8. intreaba si eu ca nestiutorul… da cu ce-i gresit daca folosesti @font-face in css si mod_expires in htaccess?

  9. Staicu Ionuț-Bogdan

    @semeketh: nu-i nimic greșit. Soluția prezentată de mine tratează altă problemă. În proiectul pentru care am avut nevoie de această treabă, fontul custom diferă foarte mult de fontul default – 12px custom ar echivala cu ~18px de arial, stricând unele chestii.

  10. si js-ul ala-ti rezolva problema cu marimea fontului? sau baga o bucata de css in head cu niste definitii ale fontului respectiv si calea spre el. ceva de genu

    @font-face{
    	font-family: 'Clearendon';
    	font-style: light;
    	src: url('/fonts/ClarendonLTStd-Light.otf');
    }
    
    @font-face{
    	font-family: 'Clearendon';
    	font-style: bold;
    	src: url('/fonts/ClarendonLTStd-Bold.otf');
    }
    

    si pentru a scapa de flash-ul ala ii pui in htaccess

    ExpiresActive on
    ExpiresDefault "access plus 1 year"


    o sa-a ai parte de flash-ul ala doar la prima incarcare a paginii.
    + ce spui tu o sa arate cu un hack urat. o sa-ti sara toate elementele in toate directiile cat se incarca fontul custom.
    cat despre cdn-uri, mi se pare stupid sa te bazezi pe un serviciu extern pentru cativa kb (pe serverul tau, utilizatorii oricum descarca fisierele) care oricum intra in cache-ul browser-ului. si cu putina munca poti combina toate scripturile in unul singur (valabil si pentru css si pentru js). si scapi si de problema in care modifici scriptul dar in cache ai scriptul vechi. si-i rogi pe utilizatori sa dea un ctr f5. ca sa nu mai zic ce mumos e sa te uiti la un cdn picat sau care se misca f greu. partile astea intra in categoria “eu mi-s coder si fac codare cool. ma folosesc de tehnologii cool. folosesc tehnologii pe care nu le inteleg doar pentru ca am citit pe un blog scris de unu care nu intelegea”
    aaa… si:
    – Ce se întâmplă dacă utilizatorul dezactivează JS? (fie cu bună știință, fie pur și simplu nu se încarcă JS-ul)
    *pai scriptul tau e degeaba. desteptii care dezactiveaza js-ul sa-si tina gura.
    – nu toți au conexiuni de 100Mb/s (din contră aș putea spune; România este doar o excepție fericită, dar restul Europei se zbate cu o conexiune mizeră la un preț ridicol de mare – cel puțin 40-50€ pentru o conexiune incredibil de lentă; idem pentru US)
    probabil uiti ca 40-50$ la ei echivaleaza cu 2-3 lei la noi. nu raporta la cat inseamna in lei, raporteaza la puterea de cumparare.
    – nu toți știu să instaleze Chrome/Chrome frame
    who the fuck cares? nu faci site-uri pentru power useri deci n-ar trebui sa te bazezi pe faptul ca are instalat nush ce rahat. de fapt pornesti de la ideea ca el scrie http://www.gigi@yahoo.com cand vrea sa-si verifice mailul.
    – nu toți au trafic nelimitat (iar aceștia încearcă să dezactiveze tot ce papă resurse aiurea: js, imagini)
    fuck’em all. sa dezactiveze si optiunea de date. bonus lol, imaginile si scripturile sun degeaba?
    – Ce se întâmplă dacă utilizatorul dezactivează JS? (fie cu bună știință, fie pur și simplu nu se încarcă JS-ul)
    asta dupa ce dai exemplul ala de font-loader. te cam contrazici.

  11. Staicu Ionuț-Bogdan

    @semeketh: mi se pare că ești împotriva mea cam la tot ce zic (nu e vorba de acest articol ci în general). Să-ți răspund:

    – te invit să convingi un client încăpățânat că flash-ul ăla e vizibil doar la prima încărcare și ca e ok așa. Încăpățânat la modul „i won’t pay you if you don’t remove that jumping page” (fiind și ultimul proiect cu acest client, nu-mi permit să rămân cu ~40h neplătite în ideea că le recuperez „mai încolo”);

    – fiind un fel de graceful degradation, atunci când nu se încarcă JS-ul vor fi afișate fonturi default (arial) cu un font-size ceva mai mic. Imediat ce fontul este încărcat, adaug o clasă la body (cu ajutorul căreia ajustez dimensiunea fontului) și execut restul de JS ce depinde de dimensiuni ceva mai exacte (de ex. jScrollPane). Da, va exista un jump, dar mult mai puțin deranjant.

    – de notat că nu eu am adus vorba de CDN-uri și că am încercat să sugerez că e ușor inutil;

  12. te inseli. chiar nu-s impotriva ta la toate posturile. daca aveam ceva nu mai intram pe blog. din contra, verific destul de des daca ai mai scris ceva (nu folosesc readere). iar la partea cu cdn-uri nu m-am referit la tine. citesc si eu comentariile. sunt posturi care tin de programare cu care nu-s de acord. si la restul ma feresc sa comentez cu “bravo, ai dreptate!!”. deocamdata nu esti programator. cel putin nu inca. peste cativa ani, daca continui sa inveti, probabil o sa intelegi de ce acum nu esti programator.
    ps:

    font-family : "custom font", arial, etc etc

    face cam acelasi lucru cu loaderul. corect, o sa arate cam aiurea pana se icarca fontul custom dar sunt sigur ca exista fonturi de sistem care sa se pupe cat de cat cu fontul custom. si din experienta iti spun ca nu exista nici un flash. initial o sa afiseze primul font disponibil pe sistem dupa care va afisa fontul custom.

  13. Staicu Ionuț-Bogdan

    Știu că nu sunt programator; mă recomand așa doar pentru că e mai ușor de explicat decât „butonator șef de PC-uri” :w00t:

    De obicei merge cum spui tu, cu fonturi fallback. Ăsta a fost un caz mai special ce a avut nevoie și de ceva JS în momentul în care fonturile erau încărcate. De aici și articolul :)

Show trackbacks

Ți-a plăcut articolul? Lasă un comentariu!

You can insert code snippets using BBcode:
[js].[/js] [html].[/html] [php].[/php] [css].[/css]
You can also use some HTML tags:
<blockquote>.</blockquote> <code>.</code> <a href="">.</a> <strong>.</strong> <em>.</em>

windows apple dropbox facebook twitter