Куленепробивні і доступні шрифти-іконки

19

Від автора: При реалізації шрифтів-іконок потрібно бути особливо акуратним, щоб гарантувати відмінну враження для всіх користувачів. Що відбувається, коли ваш шрифт не завантажується? Що трапляється, коли в браузері не підтримується @font-face? Ми покажемо вам, як виконати «куленепробивні» шрифти-іконки.

У нескінченному квесті на побудову раціональних і ефективних сайтів для клієнтів, скромняга-шрифт багато разів пропонували в якості альтернативної легкої реалізації векторних іконок. Хоча зазвичай ми воліємо (і рекомендуємо застосовувати для векторних іконок SVG з тих міркувань, які задокументував в пості свого блогу Айєн Февер (Ian Feather ) Lonelyplanet.com інколи ми співпрацюємо з іншими командами, які вже займалися впровадженням шрифтів-іконок. На такі випадки ми вирішили вивчити, яким найкращим і загальнодоступним способом застосовуються шрифти, іконки.

А ви знали про те, що більшість методів застосування шрифтів-іконок погано узгоджуються з скринридер-ами, а для нормальної роботи і загальнодоступності їм потрібні шаблони спеціальної розмітки? А ще ми виявили, що багато старі (і нові!) мобільні браузери—особливо Opera Mini, браузер Nokia XPress, Blackberry 4-5, Android 2.1 і Windows Phone 7-7.8— взагалі не підтримують @font-face. Повивчавши питання ще трохи, ми здивувалися, дізнавшись, що (на момент написання тексту) ці браузери служать принаймні 370 мільйонів користувачів у всьому світі.

У цій статті ми обговоримо, де шрифти-іконки працюють добре, а де погано, що відбувається з ними, коли не підтримується @font-face (або коли шрифт не вантажиться), і як вирішувати такі проблеми під час виконання квесту з пошуку стійкого методу доставки шрифтів-іконок.

Проблеми шрифтів-іконок

ДОСТУПНІСТЬ

Розглянемо наступну розмітку:

<span class=»icon-star»>Favorite</span>

Безліч популярних бібліотек користуються вищенаведеної розміткою і вводять шрифти-іконки з допомогою властивостей CSS :before або :after. Однак це не приховано від скринридер-ів і може прочитуватися вголос. «Але це ж Unicode!», скажете ви, «Невже скринридеры взагалі чіпають символи Unicode?». Так, чіпають (навіть деякі знаки у «користувача» областях Private Use, але про це пізніше).

Наприклад, якщо застосувати наступний CSS до нашого прикладу інтервалу:

.icon-star:before { content: «★ «; }

отримана в результаті сторінка з’явиться в більшості браузерів ось такий, і буде виглядати просто відмінно:

Але VoiceOver (Mac OS X) висловить її словами «Black Star Favorite». Далеченько від ідеалу, так?

На жаль, не існує надійного підходу із застосуванням одного лише CSS, здатного сховати від скринридеров зайвий вербальний контент (підтримка speak: none обмежена). Самий вірний спосіб приховати непотрібне словесне вміст від скринридера (але не від зрячого користувача) – це скористатися aria-hidden=»true». Такий підхід вимагає від нас використання для іконок окремого елемента HTML, що виключає застосування до батьківського елементу :before або :after.

На нашу частку залишається лише наступний шаблон HTML і CSS:

<style>
.icon-star:before { content: «★ «; }
</style>
<span><span class=»icon-star» aria-hidden=»true»></span>Favorite</span>

VoiceOver читає це як «Favorite», а потрібні нам візуальні стилі зберігаються. Нотатки на полях: Відомі відкриті питання Chrome і Firefox, що стосуються прихованого в областях контенту всередині елемента button, але навіть в таких випадках aria-hidden залишається найбільш вдалим способом приховати вміст від скринридеров.

НАДІЙНІ АЛЬТЕРНАТИВИ

Далі давайте розглянемо, що відбувається, коли браузер не підтримує @font-face і/або файл шрифту не завантажується. Два звичних способу реалізації користувальницьких іконок в якості шрифтів включають перетворення вищезазначених іконок в символи Unicode та їх відображення спеціальними лігатурами з символьних рядків. Тестування показало, що в обох методів є свої труднощі.

Реалізуйте Unicode; запасний варіант для смайлика або пробіл

В Unicode є три не визначених специфікацією загальнодоступних розділу. Звані «користувацькими» областями (Private Use Areas) (або «PUA»), вони дозволяють користувальницьких шрифтів вставляти символи, що не мають офіційного значення в Unicode. Застосування перших PUA (іноді званих «BMP PUA») допустимо з кодуванням UTF-8.

Багато популярні рішення проблеми шрифтів-іконок включають відображення своїх символів сукупністю PUA щоб уникнути конфлікту з існуючими визначеннями Unicode. Наприклад, вам не захотілося б замінити визначення Unicode для Black Star Rainbow. (Ну, може і захотілося б, але не слід цього робити).

Застосування PUA дозволяє уникати семантичних колізій, але візуальні проблеми залишаються все одно. Наприклад, шрифти за замовчуванням однієї операційної системи визначають свої символи в PUA. Якщо які-небудь з ваших іконок відображаються символом з символом за замовчуванням і запит шрифту виконується невдало, то буде показаний символ за замовчуванням. Ось невеликий приклад PUA в iOS7:

Розглянемо попередній приклад. Припустимо, що ми перетворимо нову власну іконку чорної зірочки в символ Unicode PUA. Розмітка буде приблизно такий:

<style>
.icon-star:before { content: «\e001″; }
</style>
<span><span class=»icon-star» aria-hidden=»true»></span>Favorite</span>

Коли не вдається зробити запит шрифту-іконки, замість неї з’являється знак Unicode за замовчуванням, в iOS це буде показано так:

Коли конфліктуючими символ PUA визначено не докладно, це не означає, що очікується порожній знак—замість відсутнього символу може бути показаний символ за замовчуванням. Найчастіше це простий прямокутник (той самий жахливий гліф за замовчуванням):

Іноді все складніше:

Шрифти-іконки часто покладаються на появу невидимого тексту (Flash of Invisible Text, або FOIT – почитайте про альтернативу WebKit’а для появи тексту без стилів (Flash of Unstyled Text, або FOUT) для приховування таких альтернативних варіантів, поки проводиться запит @font-face. FOIT – предмет розбіжностей в середовищі веб-розробників. При малоймовірному розвитку подій в майбутньому, коли браузер переключиться на використання FOUT замість FOIT, шрифтів-іконкам знадобиться додатковий захист для приховування альтернативних символів на час виконання запитів @font-face.

Реалізуйте лігатури; альтернативний варіант для Real Text

Замість того, щоб в запасному варіанті покладатися на спеціальні символи, у когось виникла грандіозна ідея застосовувати для альтернативного тексту лігатури. Лігатура виходить, коли дві або більш букви з’єднуються в один гліф. Це дає вам можливість підставляти гліфи, коли у вихідному тексті зустрічаються зумовлені поєднання символів.

Наприклад, легування може підставити ♥, коли ви друкуєте «love»:

Коли лігатури не підтримуються (або не вантажиться шрифт), то показується альтернативний текст. Теоретично це чудово, але є деякі обмеження.

Якийсь час на багатьох ресурсах для підключення до лігатурам рекомендувалося використовувати text-rendering: optimizeLegibility;, що дійсно є частиною специфікації SVG (стандартом не CSS). Це рішення реально кишить багами.

Деякі пропонували альтернативний спосіб включення лігатур: font-feature-settings. Підтримка цього більш надійного підходу, на жаль, невелика навіть у браузерах десктопів: настроювані шрифти, іконки помітно губилися в IE9 і нижче, Android 4.3 і нижче, у всіх браузерах до BlackBerry 10 і в поточних версіях IE Mobile. На час написання цього тексту це означає, що альтернативи доставляються до 30% від загальної кількості користувачів. (Тьху.)

Ще одна проблема лігатур в тому, що ви прив’язуєте контент до візуальному представленню. Це може викликати проблеми інтернаціоналізації; наприклад, будь-якого тексту знадобиться окрема лігатура для кожної мови, що викликає цікаві проблеми підтримки сайтів і робочого процесу. Також цікаво виміряти різницю розмірів шрифту з однією мовою і десятьма різними мовами. Досить гарантувати створення окремих шрифтів для кожної мови? Напевно, немає—хоча б тому, що викачуються і не використовуються додаткові байти.

Нарешті, варто відзначити, що лігатури не здатні містити пробіли, що виключає множинні слова для однієї ікони. (Ларрі Фокс (Larry Fox) люб’язно вказав, що лігатури не можуть підтримувати прогалини, хоча Киамун (Keyamoon) звертає нашу увагу на те, що в Chrome є відкритий баг лігатур пробілу.)

Отже, що тепер? Шрифти-іконки – це невдале підприємство?

Насправді немає. Незважаючи на вищезазначені небезпеки, шрифти, іконки можна застосовувати! Просто доведеться приділити їм трохи більше уваги, ніж просто вставити блок @font-face в CSS і вважати справу закінченою. Перед тим, як заглибитися в подробиці, ми розробили два різних рішення на основі двох сценаріїв застосування шрифтів-іконок:

Декоративні іконки: це ті випадки, коли іконка служить чисто декоративною деталлю і не несе особливого значення або функціональності. Якщо не показується гліф іконки, це нормально, але для нормального центрування/вирівнювання сусіднього вмісту альтернатива не повинна займати «нерухомість» екрану.

Необхідні іконки: в таких випадках іконка необхідна для сприйняття, або для призначення сайту, і повинен показуватися або гліф іконки, або альтернативний вміст на його місці. Існує два варіанти нагальних іконок: альтернатива тексту (змінює довжини, без обмежень «нерухомості») і альтернатива іншого гліфа, надійного еквівалента Unicode (ЗВЕРНІТЬ УВАГУ: існує дуже мало надійних кросплатформених/кроссбраузерных гліфів, на щастя, Джон Холт Ріплі (John Holt Ripley) зібрав матрицю підтримки символів Unicode) або зображення (ймовірно, бітового PNG для сумісності).

Щоб зменшити складність цієї реалізації, ми сконцентрували суть використаних у цих прикладах CSS і JS в бібліотеку багаторазового користування під назвою Font Garde. Ми виклали її на GitHub для того, щоб ви змогли застосовувати ці шаблони стійких шрифтів-іконок у своїй роботі. Увімкніть два індивідуальних властивостей тіста Modernizr, afontgarde.css і afontgrade.js і ви готові до гонок.

ДЕКОРАТИВНІ ІКОНКИ

Реалізувати декоративні іконки простіше всього. Іконка просто відображається в тих випадках, коли підтримується @font-face, і ховається, коли немає. «На відмінно» все виглядатиме так:

А браузери-«трієчники» відобразять ось таке:

Потрібно виконати зовсім невеликі вимоги шаблон розмітки:

<span class=»icon icon-twitter» aria-hidden=»true»></span>
Share on Twitter (Sibling Text)

По-перше, застосовується окремий елемент span для вирішення проблеми доступності скринридерам. Після стандартного блоку @font-face додамо свій CSS для шрифтів-іконок:

.supports-fontface.icomoon .icon:before {
font-family: icomoon;
}
.supports-fontface.icomoon .icon-twitter:before {
content: «\e604»;
}

Зверніть увагу, що для подачі класу supports-fontface ми користуємося тестом властивостей Modernizr. Клас icomoon поставляється afontgarde.js (що робить тестування шляхом вимірювання і порівняння розмірів гліфа з шрифтом за замовчуванням для того, щоб гарантувати успішну завантаження шрифту).

JS

AFontGarde( ‘icomoon’, ‘\uE600\uE601\uE602\uE605’ );

Тут для вимірювання ми передаємо в утиліту сімейство шрифтів і деякі гліфи іконки. Вам знадобиться всього лише викликати цю утиліту по разу до кожного шрифту, а в подальшому ми будемо покладатися на клас icomoon. Так як CSS потрібно додавати ці два класу для відображення шрифту-іконки, то вирішуються вищезазначені проблеми. Чудово! Цей випадок вживання нам підходить.

НЕОБХІДНІ ІКОНКИ

Для них потрібно забезпечити появу хоч чого-небудь, якщо раптом не вдасться відобразити шрифт-іконку. Такі випадки зазвичай діляться на два табори: ті, де потрібно замінити зображення-гліф текстом, і ті, де ми застосовуємо альтернативний гліф.

Нагальні іконки з текстовою альтернативою

Вищий бал

«Трійка»

HTML

<span class=»icon-fallback-text»>
<span class=»icon icon-twitter» aria-hidden=»true»></span>
<span class=»text»>Twitter</span>
</span>

CSS

.icon-fallback-text .icon {
display: none;
}
.supports-fontface.supports-generatedcontent.icomoon .icon-fallback-text .icon {
display: inline-block;
}
.supports-fontface.supports-generatedcontent.icomoon .icon-fallback-text .text {
/* загальний спосіб візуально приховати контент, який при цьому залишається доступним для скринридеров (h5bp.com) */
clip: rect(0 0 0 0);
overflow: hidden;
position: absolute;
height: 1px;
width: 1px;
}

Вище наведено бібліотечний код, включений за допомогою afontgarde.css

Тут використовується той же принцип тестування властивостей, за винятком того, що ми додаємо додатковий клас supports-generatedcontent, щоб переконатися підтримки :before :after. Якщо це не так, то показується альтернативний текст.

Необхідні іконки з альтернативним глифом або зображенням

Вищий клас

Альтернативний гліф-середнячок

Альтернативне зображення на «трієчку»

HTML

<span class=»icon-fallback-glyph»><!— or «icon-fallback-img» —>
<span class=»icon icon-hamburger» aria-hidden=»true»></span>
<span class=»text»>Menu</span>
</span>

CSS

Бібліотечний код з afontgarde.css для стислості був пропущений.

/***************************
* альтернативний гліф
***************************/
.icon-fallback-glyph .icon-hamburger:before {
content: «\2261»; /* Hamburger */
font-size: 2em;
line-height: .5;
}
/* вищий клас */
.supports-fontface.icomoon .icon-fallback-glyph .icon-hamburger:before {
content: «\e601»;
}

Переконайтеся, що ретельно відібрали альтернативний символ-гліф. Кросбраузерна/платформна сумісність може відрізнятися. Звіртеся з таблицею сумісності Джона Холта Ріплі (John Holt Ripley).

Також зауважте, що ми підганяємо font-size і line-height альтернативного гліфа так, щоб він якомога точніше відповідав шрифту-іконці. Коли (і тільки коли) завантажився шрифт, ми встановлюємо CSS-вміст нового гліфа шрифту-іконки.

/***************************
* альтернативне бітове зображення
***************************/
.icon-fallback-img .icon-hamburger {
width: 1em;
height: 1em;
background: url(«fonts/png/hamburger.png») no-repeat;
}
/* вищий клас */
.supports-fontface .icon-fallback-img .icon-hamburger:before {
font-family: icomoon;
content: «\e601»;
}

За умов змагання між тестуванням властивостей і фоновими зображеннями CSS випадок застосування альтернативного зображення менш надійний, ніж інші підходи. Якщо для виконання скрипту потрібно чекати перевірки завантаження шрифту (і додайте клас icomoon), запит фонового зображення запуститься передчасно, незважаючи на успішну завантаження шрифту. Друга половина цього компромісу означає, що якщо запит HTTP шрифту буде неуспішний, то ми покажемо символ Unicode за замовчуванням.

Зауважте, ми регулюємо ширину і висоту елемента альтернативного зображення так, щоб він якомога точніше відповідав шрифту-іконці. Якщо хочете підігнати розмір фонового зображення, прийміть до уваги обмеження браузерної підтримки властивості CSS background-size.

Уффф!

Напевно, це здається занадто складним завданням. Але саме тому ми спакували все легко розміщується бібліотеку, яка дозволяє неодноразово використовувати ці шаблони з невеликими витратами. Тести властивостей – ключовий момент застосування шрифтів-іконок, переконайтеся, що користуєтеся ними розсудливо метою захисту свого контенту від ненавмисних альтернативних практик.