Ваш логотип — всё еще изображение… и мой тоже!

Почти два года назад я написал статью о семантике изображений, в которой описал какой должна быть правильная разметка для логотипа сайта. В двух словах, в ней приведены доводы в пользу того, что логотипы — это контент, следовательно они должны быть прописаны в разметке как элементы img, а не h1, как это часто делают.

Две главные причины использования h1:

  1. Он позволяет поместить логотип в спрайт.
  2. Заблуждение что логотип — это своего рода заголовок.

В своей статье (я все еще придерживаюсь мнения, которое в ней высказано), я опроверг второй пункт, однако первый не перестает меня волновать.

В репозитории 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 позволяет выполнить две задачи:

  1. Сообщить машине о наличии изображения и alt-текста.
  2. Отобразить графические данные для пользователя.

Теперь вы понимаете, как можно представить прозрачный gif размерами 1×1px в качестве семантически верного img и при этом управлять представлением логотипа через CSS используя спрайты.

Но зачем?!

Мы долго к этому шли, и вот наконец ответ на вопрос зачем так делать.

Вкратце: во имя производительности.

Все, кто последние несколько лет следит за публикациями на CSS Wizardry и моими постами в Twitter, знают, что проекты, над которыми я работаю, становятся все более сложными, архитектура и продуктивность все более важны и мне это нравится!

Что мне нравится больше всего в этой стороне веб-разработки — это сплав действительно впечатляющих и интересных хаков во имя производительности с «уродливой» разметкой. Года два назад я стремился к идеальной семантике и «полировал» свой код; теперь я рассматриваю код как потрясающий материал для создания больших, быстрых сайтов. Создание спрайтов для пустых элементов — это часть веселья.

Использование спрайтов — это азы продуктивности, мы все знаем зачем они нужны. Однако важно сохранять правильную семантику всюду где это возможно, потому я и использую спрайт для элемента img.

Если с точки зрения семантики логотип должен быть изображением, а вы хотите поместить его в спрайт, лучшим решением будет использовать просвечивающий img. Прозрачный gif размером 1×1px позволяет получить такое просвечивание для маленького изображения.

Это изображение создает дополнительный HTTP-запрос, что противоречит принципам производительности, однако:

Можно было бы, конечно, указать в src путь и к несуществующему изображению, что вернуло бы ответ 404 и убрало бы необходимость доставлять в браузер какое-либо изображение. Проблема здесь в том, что когда никакой объект не загружается, браузеру нечего кэшировать. Это значит что имея пять элементов img, для которых используется спрайт, вы получите пять ответов 404 и никакого кэширования. Изначальные расходы в виде одного HTTP-запроса на dot.gif быстро окупаются, так как маленькое изображение может быть кэшировано неограниченное количество времени и использоваться снова и снова. Стоит ли напоминать что изначальная причина всех этих действий — получение возможности использовать спрайты, которые экономят вам массу HTTP-запросов!

Отмечу, что не всегда нужно или можно поместить изображения в спрайт. Я и не говорю что это нужно делать всегда, наоборот я бы сказал что довольно часто создать спрайт у вас возможности не будет (например для изображений с гибким размером). Я просто предлагаю вам дополнительный инструмент для работы.

Итак, что мы имеем? Использование спрайта для img дает нам преимущества от семантически верного когда и спрайтов. Машина видит img с названием «CSS Wizardry» (отлично) и пользователь видит мой логотип (чудесно)! Все правильно, все счастливы.

Поправка: Как многие советуют, можно (если позволяет статистика) использовать data-URI в Base64 вместо gif и сэкономить HTTP-запрос. При таком подходе не будет происходить кэширование изображения, но мы можем использовать компрессию gzip.