Заметки с тегом «html» (страница 2)

Простые селекторы для разметки статьи в WordPress

Все браузеры начинают разбор CSS селекторов справа налево. Кстати, так же поступают и популярные библиотеки при поиске DOM элементов по заданному селектору.

Пусть в CSS файле, например, указан селектор section.main .article p { … } . Во время отрисовки проверяется, что текущий элемент p. Если это так, то браузер будет искать в дереве всех предков с классом article , а затем предков section с классом main . Только к элементам, для которых были найдены все требуемые предки, и будут применяться декоративные свойства.

Очевидно, что самые быстрые селекторы – это те, которые требуют меньше проверок: div, .main, #sidebar . Такие селекторы называются простыми. Каскадным селекторам (например, как в предыдущем случае) требуется гораздо больше времени для прохождения таких проверок. Так в БЭМ, по возможности, используются только простые селекторы или последовательности простых селекторов (например, a.menu__item-link:hover ), чтобы обеспечить максимальную скорость отображения страниц.

С обычной вёрсткой проблемы добавить нужные классы не возникает. А вот для контента, создаваемого пользователем, такие классы придётся назначать автоматически. Для своего блога на Вордпрессе я написал небольшой фильтр.


function my_content_filter_callback($parts)
{
    $tag = strtolower($parts[1]);
    $attrs = $parts[2];
    $cls_replacement = ' class="t-' . strtolower($tag);

    if (strpos($attrs, ' class=') === false) {
        $attrs = $cls_replacement . '"' . $attrs;
    } else {
        $attrs = str_replace(' class="', $cls_replacement . ' ', $attrs);
    }

    return '<' . $tag . $attrs . '>';
}

function my_content_filter($content)
{
    if (!is_feed()) {
        $out = preg_replace_callback('#<([a-zA-Z0-9]+)([^>]*)>#',
            'my_content_filter_callback', $content);
    } else {
        $out = $content;
    }
    return $out;
}

add_filter('the_content', 'my_content_filter', 20);

Фильтр вызывается при отображении статьи. Каждому тегу в статье добавляется класс с именем тега. Например, <p> становится <p class="t-p">, а <div class="video"> становится <div class="t-div video">.


<h3 class="t-h3">Элемент article</h3>
<p class="t-p">Новый элемент <em class="t-em">article</em> — это специальный вид
    <em class="t-em">section</em>, который обозначает независимую и самодостаточную
    часть страницы. На его месте можно использовать <em class="t-em">section</em>,
    но <em class="t-em">article</em> добавляет больше семантического значения.</p>

Теперь элементы статьи можно декорировать простыми селекторами не опасаясь, что они будут конфликтовать с оформлением других блоков.

.t-h3 { font-size: 1.5em; font-weight: bold; margin: 1em 0 0.5em; }
.t-p { margin: 1em 0; }
.t-em { font-style: italic; }

Подведу итоги:

  • небольшое увеличение объема HTML кода почти никак не сказывается на трафике для пользователя, так как по сети данные передаются в сжатом виде;
  • нет ручной работы по добавлению классов элементам;
  • при декорировании в CSS используются простые селекторы;
  • максимальная скорость при отрисовке страницы в браузере.
Оставте свой комментарий

Шаблонирование на JavaScript

Динамическое создание и обновление блоков страницы с давних пор принято делать через свойство DOM-элемента innerHTML . Если речь идет о куске HTML, пришедшего с сервера в асинхронном запросе, то другого адекватного варианта просто нет. С другой стороны, когда с сервера получаем только данные, а разметку создаем скриптом на JS, то тут уже появляются варианты.

Различные реализации JS-движка имеют свои сильные и слабые стороны. Долгое время создание DOM-элементов через document.createElement было очень дорогой по времени операцией. Не самый лучший дизайн API требовал многословности при создании увесистой структуры из элементов с атрибутами.


var container = document.createElement("div");
var link = document.createElement("a");
link.setAttribute("href", "http://yandex.ru/");
link.setAttribute("title","Яндекс");
link.appendChild(document.createTextNode("Поиск"));
container.appendChild(link);

Этот фрагмент фактически соответствует:

<div><a href="http://yandex.ru/" title="Яндекс">Поиск</a></div>

Поэтому широкое распространение получили различные шаблонизаторы на основе замены частей строки-шаблона данным или склеивания строки из нескольких частей.

Основной потенциальной проблемой таких шаблонизаторов является экранирование входящих данных. Значения атрибутов или текст внутри тегов должен быть очищен от спецсимволов, которые могут повлиять на результат при интерпретации HTML-кода при добавлении его в документ.

HTML – всегда был и остается результатом сериализации древовидной структуры документа в текстовый формат, который может легко восприниматься и редактироваться человеком. Браузер, получая его на вход из файла или через поле innerHTML, разбирает его, превращая в DOM-дерево, прежде чем примется его отображать.

Современные браузеры достаточно быстро выполняют JavaScript, чтобы дать сборке фрагментов DOM-дерева через соответствующие методы API, ещё один шанс.

Синтаксический сахар

Neil Jenkins сделал «сахарок» для создания отдельных элементов и целых иерархий – Sugared DOM. Однако его код не работает в IE из-за отличной от других движков реализации метода split() у строк. Я переделал работу в этой части кода и добавил unit-тесты.

el("div");

Элементы можно создавать с установленными атрибутами id и class , используя знакомый CSS синтаксис

el("div#id.class1.class2");

Элементу можно установить другие атрибуты. Например,

el("div#id", { tabindex: -1, title: "Контейнер" });

Дочерние элементы передаются в массиве последним аргументом

var container = el("div", [
    el("a", {"href": "http://yandex.ru/", "title": "Яндекс"}, [
        "Поиск"
    ])
]);

Производительность

Тесты показывают превосходство DOM версии во всех браузерах кроме Оперы, где разница в скорости почти не заметна и Интернет Эксплорера, который всё же быстрее работает с полем innerHTML.

Ноутбуки и настольные компьютеры в настоящее время настолько мощные, что разница в скорости создания фрагментов не так уж и важна. С другой стороны, на мобильниках и планшетах – это может быть критичным. Тесты показали, что DOM версия быстрее от 45 до 100% в WebKit браузерах (браузеры в iOS устройствах и браузер по-умолчанию в Android устройствах), и примерно одинакова с innerHTML версией в Opera Mobile.

Заключение

Sugared DOM метод имеет ряд преимуществ перед шаблонизаторами:

  • Прост в отладке (описание шаблона – это и есть исполняемый код).
  • Не нужно дополнительно искать элементы после создания фрагмента – все ссылки на готовые элементы можно получить в процессе построения дерева.
  • Не нужно беспокоиться об экранировании данных. Нулевая вероятность XSS. Текстовая стока явно преобразуется в текстовый узел DOM-дерева.
  • Нет пустых текстовых узлов из-за пробелов между тегами.
  • Среда разработки помогает отслеживать ошибки в таком шаблоне, так как он является обычным JS-скриптом.
  • Гибкость шаблонирования обеспечивается полным доступом к объектам и функциям JS.

PS. Заметка вдохновлена статьёй Building the new AJAX mail UI part 2: Better than templates, building highly dynamic web pages

Комментарии к заметке: 3

Навигация по ссылкам в списках

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

Список авторов статей в блоге

Каждый элемент в списке содержит имя, фотографию и краткую биографию автора. Имя и фотография обрамлены ссылками на архив статей этого автора.


<ul class="authors">
  <li class="author">
    <div class="author-userpic">
      <a class="author-archive-link" title="Vicki Moyes" href="/author/vicki/">
        <img class="author-pic photo" alt="Vicki Moyes" src="/img/users/vicki-moyes.jpg">
      </a>
    </div>
    <p class="author-title">
      <a href="/author/vicki/" class="author-title-archive-link">Vicki Moyes</a>
    </p>
    <p class="author-bio">Director of Moyes Gliders.
      Organizer of annual Forbes competition.</p>
  </li>
</ul>

Используем tabindex=-1

Элементы, обрамленные ссылками

При переключении фокуса с помощью клавиши «Tab» пользователь каждый раз сначала попадает на ссылку с фотографии, затем на ссылку с имени.

Проектируя интерфейс, первостепенно внимание уделяется пользователям, работающим с мышью или touch-интерфейсом. Кому-то из них привычнее и удобнее кликать по картинкам, а кто-то кликает только по явно обозначенным ссылкам. Поэтому удалить ссылку, обрамляющую фотографию, нельзя. Но зато можно сделать так, чтобы она не участвовала в последовательности переключения фокуса с клавиатуры. Для этого добавим ей атрибут tabindex="-1".

Переходы только по именам авторов

Такой нехитрый прием позволяет значительно улучшить впечатления пользователя от интерфейса и сделать его поведение более предсказуемым.

Одна ссылка

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


<a href="page.html">
    <div><img src="img1.jpg" alt="Page image"></div>
    <p>Page title</p>
</a>

Фрагмент кода валиден на 100%, только если используется в HTML5 документе.

Комментарии к заметке: 4

Таблица без таблицы или display: table-cell для всех браузеров

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

Все современные браузеры могут отрисовывать блок как таблицу, строку таблицы или ячейку таблицы являясь на самом деле обычными блочными или даже строчными элементами.

.table {
    display: table;
}
.table-row {
    display: table-row;
}
.table-cell {
    display: table-cell;
}

Разметка, например, может быть такой:


<div class="table">
    <ul class="table-row">
        <li class="table-cell">Ячейка 1</li>
        <li class="table-cell">Ячейка 2</li>
        <li class="table-cell">Ячейка 3</li>
    </ul>
</div>

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


.table, .table-row, .table-cell {
    display: block;
    float: left;
}
.table-cell {
    clear: right;
    zoom: 1;
}
.table {
    overflow: hidden;
    position: relative;
}

Комбинация float: left; и clear: right; заставляет следующий блок намертво прилипнуть к предыдущему, образовывая ячейки нашей таблицы. Можно использовать прибивку в другую сторону, если нужен обратный порядок элементов.

Комментарии к заметке: 9

Закомментировать HTML

Чтобы закомментировать кусок HTML нужно обрамить его последовательностью <!-- с одной стороны и --> с другой.

<!-- <p>Эта строка не разбирается и не отображается</p> -->

В HTML нет разделения на строчный и блочный комментарий как, например, во многих языках программирования. Все комментарии являются блочными.

Оставте свой комментарий