Ваш логотип — всё еще изображение… и мой тоже!
Почти два года назад я написал статью о семантике изображений, в которой
описал какой должна быть правильная разметка для логотипа сайта. В двух словах,
в ней приведены доводы в пользу того, что логотипы — это контент, следовательно
они должны быть прописаны в разметке как элементы img
, а не h1
, как это
часто делают.
Две главные причины использования h1
:
- Он позволяет поместить логотип в спрайт.
- Заблуждение что логотип — это своего рода заголовок.
В своей статье (я все еще придерживаюсь мнения, которое в ней высказано), я опроверг второй пункт, однако первый не перестает меня волновать.
В репозитории CSS Wizardry меня попросили более детально рассказать как я применяю свои утверждения на практике:
Я недавно перечитывал Вашу статью о том, что логотип — это изображение и заметил, что на своем сайте Вы применяете другой подход. Расскажите нам о нем подробнее, пожалуйста.
Внимание, дальше много букв. Поищем баланс между правильной семантикой и лучшей производительностью.
Итак, ранее я писал что для логотипа не стоит использовать h1
, его лучше
поместить в img
. Вот разметка которую я сейчас (в феврале 2013 года) использую
на CSS Wizardry:
<a href="/" class="site-logo">
<img src="/img/dot.gif" alt="CSS Wizardry" class="s s--csswizardry-logo">
</a>
Заметьте что в src
указано не logo.png
или что-то в этом роде, а dot.gif
.
Это, как можно догадаться, прозрачное изображение в формате gif с размерами
1×1px.
Обновлено: сейчас я использую прозрачный gif размером 1×1px, закодированный в Base64
Эм … что?
Я поместил маленькое прозрачное изображение в формате gif в тэг img
и затем с
помощью CSS добавил в качестве фона SVG-спрайт. Таким образом, я использовал
подходящий с точки зрения семантики img
и, немного схитрив, добавил из CSS
изображение, которое увидят пользователи. Вот (S)CSS:
.s{
background-image:url(/img/css/sprites/main.svg);
}
.s--csswizardry-logo{
width:64px;
height:64px;
background-position:-5px -5px;
@include vendor(background-size, 250px 250px);
@include media-query(desk){
@include vendor(background-size, 500px 500px);
width:128px;
height:128px;
background-position:-10px -10px;
}
}
Я всего-навсего указываю класс, в котором будет применен спрайт (.s
) и затем
более детально описываю его свойства в .s--csswizardry-logo
(не забывая об
отзывчивом дизайне).
Стоит подчеркнуть, что хоть в разметке мой логотип и представлен всего лишь прозрачным gif-ом размером 1×1px, он является изображением.
Прежде, чем объяснить зачем я так делаю, нужно понять вот что:
Люди и машины
Когда дело касается HTML и CSS, следует провести разграничение (хоть оно и будет сильно упрощенным) между людьми (нашими пользователями) и машинами. Как правило (в большинстве случаев) на наши сайты имеют доступ два типа субъектов: машины, например скринридеры и боты, и люди, которые могут видеть сайт и взаимодействовать с ним.
Обычно мы строим сайты учитывая оба варианта. Именно поэтому мы печемся о доступности сайта и чистоте кода, и в то же время хотим чтобы сайт хорошо выглядел и уделяем много внимания дизайну. В этом состоит забота об интересах машин и пользователей.
N.B. Пользователя с нарушенным зрением, который заходит на сайт через скринридер, можно условно отнести к категории машин, так как он не напрямую работает с сайтом, а использует скринридер, который обрабатывает код и затем передает его пользователю. Я понимаю, что называть людей с дефектами зрения машинами оскорбительно, но только так я могу объяснить почему в этом случае мы говорим что на сайт заходит машина, а не человек, хоть эта машина и пребывает под управлением человека.
Семантика нужна машинам
Учитывая вышеизложенное, становится ясно, что только машинам есть дело до того
что мы используем img
. Для пользователя нет никакой разницы используем мы
img
, Flash-объект или div
с фоновой картинкой. img
ценны только для машин
(скринридеров, поисковиков, и т.п.). Именно им нужна семантика.
Машины также пользуются alt
-текстом. alt
-текст не нужен пользователям, он
нужен машинам, которые при необходимости передают его пользователям.
Таким образом, для добавления изображения семантически правильно будет
использовать элемент img
с alt
-текстом, так как именно в этом нуждаются
машины. Для машин (что мы, как фронтенд-разработчики должны понимать) не имеет
никакого значения реальное содержимое изображения. Если у вас элемент img
с
прозрачным gif-изображением и «CSS Wizardry» в качестве alt
-текста, машина
знает только то, что это изображение с альтернативным текстом, она понятия не
имеет что именно на изображении.
Изображения для людей
Для людей имеет значение что отображено на картинке и не имеет значения как
выглядит код. Следовательно, пользователям все равно каким образом мы
стилизируем элемент img
(мы, естественно, будем использовать для этого CSS).
Вот в чем вся соль; img
позволяет выполнить две задачи:
- Сообщить машине о наличии изображения и
alt
-текста. - Отобразить графические данные для пользователя.
Теперь вы понимаете, как можно представить прозрачный gif размерами 1×1px в
качестве семантически верного img
и при этом управлять представлением
логотипа через CSS используя спрайты.
Но зачем?!
Мы долго к этому шли, и вот наконец ответ на вопрос зачем так делать.
Вкратце: во имя производительности.
Все, кто последние несколько лет следит за публикациями на CSS Wizardry и моими постами в Twitter, знают, что проекты, над которыми я работаю, становятся все более сложными, архитектура и продуктивность все более важны и мне это нравится!
Что мне нравится больше всего в этой стороне веб-разработки — это сплав действительно впечатляющих и интересных хаков во имя производительности с «уродливой» разметкой. Года два назад я стремился к идеальной семантике и «полировал» свой код; теперь я рассматриваю код как потрясающий материал для создания больших, быстрых сайтов. Создание спрайтов для пустых элементов — это часть веселья.
Использование спрайтов — это азы продуктивности, мы все знаем зачем они нужны.
Однако важно сохранять правильную семантику всюду где это возможно, потому я и
использую спрайт для элемента img
.
Если с точки зрения семантики логотип должен быть изображением, а вы хотите
поместить его в спрайт, лучшим решением будет использовать просвечивающий img
.
Прозрачный gif размером 1×1px позволяет получить такое просвечивание для
маленького изображения.
Это изображение создает дополнительный HTTP-запрос, что противоречит принципам производительности, однако:
- Это лишь несколько дополнительных байтов, которые загрузятся практически незаметно.
- Использовать его можно бесконечное количество раз, так как браузер не будет его запрашивать повторно.
- Его можно кэшировать раз и навсегда так как вряд ли когда-нибудь потребуется обновление прозрачного gif размером 1×1px.
Можно было бы, конечно, указать в src
путь и к несуществующему изображению,
что вернуло бы ответ 404 и убрало бы необходимость доставлять в браузер
какое-либо изображение. Проблема здесь в том, что когда никакой объект не
загружается, браузеру нечего кэшировать. Это значит что имея пять элементов
img
, для которых используется спрайт, вы получите пять ответов 404 и никакого
кэширования. Изначальные расходы в виде одного HTTP-запроса на dot.gif
быстро
окупаются, так как маленькое изображение может быть кэшировано неограниченное
количество времени и использоваться снова и снова. Стоит ли напоминать что
изначальная причина всех этих действий — получение возможности использовать
спрайты, которые экономят вам массу HTTP-запросов!
Отмечу, что не всегда нужно или можно поместить изображения в спрайт. Я и не говорю что это нужно делать всегда, наоборот я бы сказал что довольно часто создать спрайт у вас возможности не будет (например для изображений с гибким размером). Я просто предлагаю вам дополнительный инструмент для работы.
Итак, что мы имеем? Использование спрайта для img
дает нам преимущества от
семантически верного когда и спрайтов. Машина видит img
с названием
«CSS Wizardry» (отлично) и пользователь видит мой логотип (чудесно)! Все
правильно, все счастливы.
Поправка: Как многие советуют, можно (если позволяет статистика) использовать data-URI в Base64 вместо gif и сэкономить HTTP-запрос. При таком подходе не будет происходить кэширование изображения, но мы можем использовать компрессию gzip.