Создание эффективной семантической разметки

Мэни Шериар (Mani Sheriar) | 13 ноября 2009 г.

Когда я впервые собралась написать эту статью, я задумалась: «Разве не все знают, как создавать эффективную семантику разметки?» Я с головой ушла в веб-стандарты почти семь лет назад, и мне легко может показаться, что вокруг в этом должны разбираться все — особенно с учетом того, что в Интернете я чаще всего посещаю блоги других веб-дизайнеров, увлеченных веб-стандартами, или CSS Zen Garden, или многочисленные веб-сайты с демонстрациями CSS, или веб-сайты моих коллег (ну хорошо, и Flickr, и Facebook, но я не люблю разбираться во внутреннем устройстве этих веб-сайтов).

Но когда я глубже осмыслила свой опыт взаимодействия с другими разработчиками, как в интерфейсной, так и в серверной области, я поняла, что осталось еще немало неосвоенного и что есть еще, куда расти. Вспомнились некоторые конкретные группы людей, и мне начала нравиться идея пообщаться с ними о создании высококачественной разметки и о том, почему она так важна. В эти группы входят как новички в кодировании, которые могли бы с самого начала освоить лучшие методы, так и ветераны (что, возможно, означает людей от тридцати и старше), которые привыкли к определенным методам и не уверены в том, что их нужно менять. Но самое главное, меня взволновала возможность пообщаться с разработчиками серверных приложений, с которыми мне нужно работать над проектами большего размера — с теми, кто пишет на таких языках, как Ruby, ASP.NET, PHP, Python, кажущихся мне чем-то инопланетным.

Что такое веб-стандарты?

Одно из моих любимых описаний веб-стандартов — описание, автором которого является Расс Уикли (Russ Weakley) из MaxDesign:

«Термин “веб-стандарты“ для разных людей может означать разное. Для одних это “веб-сайты без таблиц”, для других это “использование правильного кода”. Но этим веб-стандарты не ограничиваются. Для веб-сайтов, созданных в соответствии с веб-стандартами, должны соблюдаться стандарты (HTML, XHTML, XML, CSS, XSLT, DOM, MathML, SVG и т. д.) и рекомендации (правильный код, доступный код, семантически корректный код, понятные пользователю URL-адреса и т. д.).

Другими словами, веб-сайт, созданный в соответствии с веб-стандартами, в идеале должен быть без излишеств, чистым, использующим CSS, доступным, удобным и подходящим для механизма поиска...»

По-моему, веб-стандарты по большей части означают следующее — полное разделение стилей и контента, контент, доступный для всех платформ, браузеров и устройств, а также самому широкому спектру пользователей и агентов пользователей.

Почему это важно?

У разработчика интерфейсного или серверного кода есть несколько причин заботиться о качестве создаваемой (X)HTML-разметки. Помимо всего прочего написание высококачественного кода может решить следующие задачи:

  • упростить (то есть сделать быстрее и дешевле) для разработчика или других лиц будущее изменение, модернизацию или переработку создаваемого веб-сайта или приложения;
  • реализовать широко разрекламированные преимущества ускоренной загрузки, повышения рейтинга оптимизации для механизмов поиска, улучшений доступности и готовность к будущим изменениям;
  • заслужить уважение коллег и клиентов (что, как известно, может помочь заработать на жизнь).

И, по-моему, самое главное, для разработчиков серверных приложений:

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

Что делать?

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

Представление документа без стилей

Когда я пишу код (X)HTML и оказываюсь перед выбором оптимального способа кодирования (использовать теги blockquote или div, список определений или таблицу, заголовок или полужирный текст), я задаю себе один удивительно простой вопрос, который почти всегда дает правильный ответ: «Как я писала бы код для браузера, способного отображать только текст?» Конечно, на определенном уровне понадобится учитывать и дизайн, но как дизайнер я скажу, что при создании разметки не стоит об этом думать. Рассматривайте дизайн как контейнеры и минимальные зацепки для CSS, которые могут понадобиться для создания макета, но во всех остальных отношениях, когда речь идет о понимании семантики самих тегов, вообще не думайте о дизайне.

Разметка

Ниже приведена область основного контента главной страницы моего веб-сайта:

Кажется, что для создания такого количества видимых частей страницы потребуется немало разметки. Например, страница содержит значки слева, фоновые прямоугольники с пунктирной границей, заголовки и большие кнопки справа. Кроме того, требуется объединить содержание каждого раздела в одну ссылку, меняющую всю графику при наведении указателя.

Может показаться, что для этого потребуется большое количество тегов div или span либо другая дополнительная разметка, но если думать о документе как о документе без стилей, оказывается, что необходима лишь минимальная разметка, даже если оставлять зацепки для CSS, которые позднее добавят немного волшебства. Разметка содержит лишь неупорядоченный список, некоторые заголовки со ссылками, немного текста и выглядит примерно так:

<ul>
   <li class="portfolio">
     <h3><a href="portfolio/index.htm"><span>Portfolio</span></a></h3>
     <p>See how I put  both my artistic and  geeky sides to good use 
      creating websites that inspire.</p>
   </li>
   <li class="about">
     <h3><a href="about/index.htm"><span>About</span></a></h3>
     <p>Learn how to pronounce my name and other things you might 
      want to know about me.</p>
   </li>
   <li class="photography">
     <h3><a href="photography/index.htm"><span>Photography</span></a></h3>
     <p>Check out my passion for combining formal training in art with years of 
     digita design experience.</p>
   </li>
   <li class="contact">
     <h3><a href="contact/index.htm"><span>Contact</span></a></h3>
     <p>Get in touch to talk with me about potentially working together or anything 
           else.</p>
   </li>
</ul>

При этом я получаю документ без стилей, который выглядит в точности так, как я хочу:

Чтобы дать полное ощущение того, что я имею в виду, говоря о создании разметки для документа без стилей, я разработала версию своего веб-сайта совсем без стилей и без JavaScript. Я ничего не изменила в HTML-разметке, только убрала CSS и вызовы JavaScript. Надеюсь, что можно видеть, что она хорошо организована и легко читается. Обратите внимание, что убраны все символические изображения, и остались только изображения портфолио и фотографии (которые фактически являются частью контента).

Конечно, помимо этого хочется, чтобы код был структурированным и подробно прокомментированным. Если говорить о комментариях, по крайней мере мне нравится помещать что-то в конце каждого тега div, что-то похожее на строку <!-- конец боковой панели -->, чтобы было легко понять, что именно было закрыто. Кроме того, при использовании Dreamweaver я обнаружила, что выбор Commands > Apply Source Formatting (Команды > Применить форматирование источника) может делать чудеса, чтобы сохранить все правильное выделение и выравнивание, а также сделать код удобочитаемым.

Стиль

Теперь все готово к применению стилей, давайте скорее их добавим! CSS для этого раздела может выглядеть примерно так:

#bd-home #maincol ul {
  margin:0;
  list-style-type:none;
}
#bd-home #maincol ul li {
  margin:0 0 23px 0;
  width:648px;
  height:109px;
  position:relative;
}
#bd-home #maincol ul h3 span,
#bd-home #maincol ul p {
  display:none;
}
#bd-home #maincol ul h3 a {
  display:block;
  width:648px;
  height:109px;
  position:absolute;
  top:0;
  left:0;
}
#bd-home #maincol ul li.portfolio  a {
  background:url(../_images/home/portfolio.gif) no-repeat 0 0;
}
#bd-home #maincol ul li.portfolio a:hover {
  background:url(../_images/home/portfolio.gif) no-repeat -648px 0;
}
#bd-home #maincol ul li.about a {
  background:url(../_images/home/about.gif) no-repeat 0 0;
}
#bd-home #maincol ul li.about a:hover {
  background:url(../_images/home/about.gif) no-repeat -648px 0;
}
#bd-home #maincol ul li.photography a {
  background:url(../_images/home/photography.gif) no-repeat 0 0;
}
#bd-home #maincol ul li.photography a:hover {
  background:url(../_images/home/photography.gif) no-repeat -648px 0;
}
#bd-home #maincol ul li.contact a {
  background:url(../_images/home/contact.gif) no-repeat 0 0;
}
#bd-home #maincol ul li.contact a:hover {
  background:url(../_images/home/contact.gif) no-repeat -648px 0;
}

Я использую CSS, чтобы определить фиксированную ширину и высоту, а также относительное положение для элементов списка (что важно, так как нужно разместить внутри них ссылки с абсолютным позиционированием), чтобы скрыть текст H3 и абзацы, а также чтобы превратить ссылки в элементы на уровне блоков с тем же размером, что и соответствующие контейнеры, и точно разместить эти элементы внутри контейнеров. Теперь я просто задаю фон для каждой ссылки. Эти четыре фона выглядят примерно так:

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

Использование каскада

Эти таблицы стилей не зря называются каскадными, и один из самых полезных способов сделать разметку экономной, скромной и гибкой — обеспечить достаточно зацепок для CSS, но избежать создания ненужных классов и идентификаторов благодаря улучшенному использованию каскада. Я вспоминаю, как впервые использовала CSS для веб-сайта. Я думаю, что назначила каждому тегу <p> класс «text» и каждому тегу <a> класс «link». Стыдно-то как!

Разметка

В каждом основном разделе моего веб-сайта есть другой заголовок на основе изображения для основного H2 страницы:

Можно подумать, что для H2 каждой из этих страниц нужно добавить уникальный класс или идентификатор, но в этом нет необходимости, если тегу <body> каждой страницы назначен уникальный идентификатор, так как можно просто использовать каскад.

<body id="bd-portfolio">
   <div id="container-wrapper">
     <div id="container">
       <div id="header">
         ...
         <h2><span>Selected Projects</span></h2>
       </div>
       <!-- end header -->

Стиль

Определив уникальный идентификатор, можно идти дальше и присвоить стили. Сначала я определяю базовые стили для основного H2:

/* --
***** Заголовок страницы
---------------------------------------------------------------------*/
#header h2 {
  position:absolute;
  top:109px;
  left:279px;
  margin:0;
  height:65px;
  width:653px;
}
#header h2 span {   display:none;
}

Затем я определяю изображения для каждой отдельной страницы

#bd-portfolio #header h2 {
  background:url(../_images/portfolio/title.gif) no-repeat 0 0;
}
#bd-about #header h2 {
  background:url(../_images/about/title.gif) no-repeat 0 0;
}
#bd-photography #header h2 {
  background:url(../_images/photography/title.gif) no-repeat 0 0;
}
#bd-contact #header h2 {
  background:url(../_images/contact/title.gif) no-repeat 0 0;
}

Конечно, этот пример достаточно прост, но если удастся перенести эту идею на более сложные сценарии, можно избежать массы ненужной работы. Прежде чем создавать новый идентификатор или класс, я задаю себе вопрос: «Действительно ли это необходимо или можно реализовать этот элемент с помощью уже используемых зацепок?» Если уникальный идентификатор назначен каждой странице или каждому типу страницы, и если уникальные идентификаторы назначены всем основным разделам страницы, удивительно, насколько мало классов потребуется.

Понятные идентификаторы и имена классов

Можно думать, что это элементарно. Я тоже так думаю! Но вы удивитесь, сколько времени мне пришлось потратить на назначение стиля элементам, называющимся подобно «block-block-block-47» (да, я говорю о тебе, Drupal!), или другим столь же бессмысленным именам. Подобные позорные виды классов и идентификаторов могу создать реальную головную боль для разработчика интерфейсных приложений, поэтому, уважаемые серверники, умоляю вас, подумайте секунду о нас, создавая код, который будет порождаться вашими языками программирования, и позаботьтесь сделать его осмысленным.

Кроме того, если что-то всегда будет сбоку, назовите это «sidecol» (боковая колонка), или «sub-content» (дочерний контент), или как-то еще, но не «left-column» (левая колонка) или подобно. Что если при последующем изменении дизайна понадобится переместить столбец вправо? Представляете, насколько ненадежна функция поиска и замены? (Можно, конечно, оставить для левого столбца имя «rightcol» (правая колонка), и каждый раз любой, кому придется работать с этим веб-сайтом, будет вынужден выяснять это самостоятельно.) Просчитывайте свои действия, присваивая имена, и задавайте себе следующий вопрос: «Описывает ли имя функцию или стиль элемента?» Если это стиль, придумайте другое, более подходящее имя.

Никаких ускоренных методов

Некоторые из действительно умных программистов, с которыми я работала, не понимают, какую проблему создает использование пустых тегов параграфов для добавления в документ дополнительного пространства, или чем плох прием использовать <br / ><br /> для создания того же пространства. Ведь это же правильные теги, не так ли? И разметка пройдет проверку, так в чем же проблема? Возможно, они понимают, что это решение — не идеал, но когда нужно успеть к сроку, а такой подход является самым быстрым, они просто не задумываются о том, насколько это важно. Позвольте мне попытаться объяснить, почему это может привести к ряду вполне реальных проблем.

Пусть в разметке есть несколько пустых тегов <p>, чтобы добавить дополнительное пространство в нижней части страниц статей. Во-первых — и это главное — если вы не дизайнер (или если вы рядовой дизайнер), есть вероятность, что вы не сумеете заметить, что пространство слишком велико (или, возможно, недостаточно велико). Но я это замечу, и вполне вероятно, что это заметят наш клиент и некоторые из наших пользователей. Если теперь у меня возникнет задача «исправить это», я не смогу войти в CSS и настроить пространство, так как я не смогу работать со всеми абзацами, ведь так? Мне остается только найти элемент, всегда находящийся после этого пространства (если мне повезет и он вообще найдется), и назначить для него отрицательное значение верхнего поля, чтобы сжать это пространство (но при отсутствии пустого тега этот прием неизбежно приведет к визуальному перекрытию этого элемента с другими), или мне понадобится определенное волшебство JavaScript, чтобы найти все пустые теги <p> на страницах статей, назначить им класс «empty» (пустой), а затем можно будет определить стиль этого пространства. Я могу найти и другие сложные пути обнаружения пустых тегов <p>, если это возможно, в противном случае мне придется дозваниваться до автора этих тегов и пытаться объяснить, почему их нужно убрать (и разговор может оказаться удивительно нелицеприятным).

Либо ... вы не вставляете пустой тег <p>, и я смогу просто добавить отбивку в конец контейнеров статьи с помощью CSS. Вот так, пожалуйста!

Не забывайте о вопросе, задаваемом для документа без стилей, и вы вскоре увидите, что пустые теги <p> или несколько <br /> — неподходящий вариант. В документе без стилей они создали бы чрезвычайно неудобное пространство.

И снова, я знаю, что этот пример относительно прост, но именно он вспомнился мне, как, возможно, самый распространенный. Если читатель сможет извлечь для себя этот принцип — семантический код важен не только для проверки, его качество может решающим образом повлиять на время разработки — мы вместе сделаем большой скачок вперед. Разработчики интерфейсных и серверных приложений, соединяйтесь!

Хорошо структурированные таблицы стилей

Я работала над рядом достаточно больших веб-сайтов и знаю, что таблицы стилей могут стать действительно длинными! При работе с таблицей стилей, содержащей тысячи объявлений, даже понять, где искать нужный элемент, может оказаться непростой задачей. Лучший способ избежать подобной проблемы — организация. У меня есть протокол, который я всегда соблюдаю и который полезен для меня и, я надеюсь, будет полезен и другим. Мои таблицы стилей обычно начинаются с некоторой базовой структуры, подобной следующей:

/****************************************************************
 
---------------------- ОБЩИЕ ПОЛОЖЕНИЯ --------------------------
 
****************************************************************/ 
 
html {}
 
body {}
 
a {}
 
 
 
/****************************************************************
 
-------------------- ОСНОВНАЯ СТРУКТУРА -------------------------
 
****************************************************************/ 
 
#container {}
 
#header {}
 
#content {}
 
#maincol {}
 
#sidecol {}
 
#footer {}
 
#copyright {}
 
 
 
/****************************************************************
 
------------------------ ВЕРХНИЙ КОЛОНТИТУЛ ---------------------
 
***************************************************************/  
 
/* -- ***** Основная навигация 
 
---------------------------------------------------------------*/ 
 
#mainnav {}
 
 
 
/* --***** Вспомогательная навигация 
 
---------------------------------------------------------------*/ 
 
#subnav {}      
 
/****************************************************************
 
-------------------- ОСНОВНАЯ КОЛОНКА -------------------------
 
****************************************************************/ 
 
#maincol {}
 
 
 
/* -- ***** Домашняя страница
 
---------------------------------------------------------------*/ 
 
#bd-home {}
 
 
 
/* -- ***** Страница сведений
 
---------------------------------------------------------------*/ 
 
#bd-about {}
 
/* -- ***** Страница фотографий
 
---------------------------------------------------------------*/ 
 
#bd-photography {}
 
/* --***** Страница контактов
 
---------------------------------------------------------------*/ 
 
#bd-contact {}
 
 
 
/****************************************************************
 
-------------------- БОКОВАЯ КОЛОНКА -------------------------
 
****************************************************************/ 
 
#sidecol {}
 
 
 
/****************************************************************
 
-------------------- НИЖНИЙ КОЛОНТИТУЛ  И АВТОРСКИЕ ПРАВА--------
 
****************************************************************/
 
 
 
/* --***** Нижний колонтитул
 
---------------------------------------------------------------*/ 
 
#footer {}
 
/* --***** Авторские права
 
---------------------------------------------------------------*/ 
 
#copyright {}
 
/** -------------Третий уровень  ------- **
 
 
 
/* -- четвертый уровень-- */

Я создаю большие, даже огромные, очевидные разделители разделов, которые легко можно заметить и найти. Я помещаю все стили, относящиеся к отдельной странице, в отдельные разделы и я всегда называю их «Страница такая-то», чтобы, если при работе над действительно длинной таблицей стилей понадобится найти стили, например, для страницы оплаты, я могла выполнить поиск по названию «страница оплаты» и перейти прямо к нужным стилям. Порядок создаваемых мной стилей соответствует порядку разметки. Например, если боковая колонка идет перед основной, я помещаю ее первой и в таблице стилей. Нижний колонтитул и сведения об авторских правах всегда идут последними — в соответствии с разметкой. Я даже разделы страниц размещаю в порядке, соответствующем навигации. Это также упрощает поиск нужных элементов.

Создание прочного фундамента

Помните рассказы д-ра Суса, как там всегда качались на качелях, которые были поставлены слишком высоко на ужасных сваях так, что, казалось, они просто не могут устоять? Если фундаменты здания установлены не под правильными углами, здания кажутся достаточно устойчивыми вначале, но добавление каждого структурного элемента делает их все более и более зыбкими. В точности то же самое происходит с нашим кодом, если специально не следить за его аккуратностью и правильностью. Небольшая неряшливость, допущенная в начале, создает эффект бабочки для всей команды и на все время жизни проекта. Со временем небольшие изменения занимают больше времени, чем предполагалось, так как много сил требуется только для расшифровки неорганизованных таблиц стилей, для решения проблем с кодом, неподходящим для использования стилей, и для обнаружения кода, создающего проблемы.

Все начинается с пустого тега <p>, непонятного имени класса, отсутствия зацепок для CSS. Впоследствии для решения этих проблем понадобятся ухищрения кодирования, создающие новые проблемы — и так снова, и снова. Исправление проблем, подобных описанным, становится все более сложным и даже невозможным, но этих подводных камней относительно легко избежать в самом начале. Все, что потребуется — понимание роли разметки. Это основа любого веб-сайта и любого веб-приложения. Создавайте их четкими и организованными, избегайте излишеств — и вы, ваша команда и, в итоге, ваш проект будут обречены на успех!