21.08.2015

При верстке с использованием тега base возникает неприятное последствие – не возможность стандартно использовать механизм якорей (анкоров) на странице. В явном виде, например, это вылезает при верстке под MODx Revolution и Evolution.

Суть проблемы

Для начала немного справочных данных описывающих поведение браузера при использовании тега <base>:

Элемент определен внутри контейнера <head> и инструктирует браузер относительно полного базового адреса текущего документа. Тег предназначен для документов, в которых используется относительный адрес и эти документы могут переноситься в другую папку или даже на другой компьютер без потери связи. Браузер ищет тег , определяет полный адрес документа и корректно загружает его. Например, если адрес документа указан как <base href="http://www.megasite.ru/hzchd/">, то при добавлении рисунков достаточно использовать относительный адрес <img src="images/labuda.gif">. При этом полный путь к изображению будет http://www.megasite.ru/hzchd/images/labuda.gif, что позволяет браузеру всегда находить графический файл, независимо от того, где находится текущая веб-страница. Также можно применять и иерархическую систему пути с двумя точками. Так, если изображение добавляется как <img src="../images/labuda.gif">, то полный путь к файлу будет http://www.megasite.ru/images/labuda.gif.

Цитата из описания тега на сайте htmlbook.ru

Теперь опишем поведение браузера при использовании якорей (анкоров) на странице. Допустим у нас есть на странице тег <section id="target">…<section> и поставленная ссылка <a href="#target">Цель</a>. Ожидается, что браузер проскролит страницу непосредственно до этого тега, но при использовании тега <base> браузер не сделает этого, а следуя спецификации попытается открыть страницу с адресом http://www.megasite.ru/hzchd/#target, которой не обнаружит. Иллюстрацию описанного поведения можно посмотреть по ссылке.

Решение проблемы

Все быстро «нагугленные» решения не понравились своей не универсальностью. В основе их лежит попытка приплюсовывать к якорю полный пусть страницы. Решения грубо можно разделить на 2 категории:

  1. Прописать вручную полный пусть страницы перед якорем, как буд-то вы ссылаетесь с другой страницы;
  2. Влезть в «святая святых» CMS и сделайте так, что бы перед выводом страницы, в случае обнаружения ссылок в виде якорей, полный пусть на страницу добавлялся автоматически.

Оба подхода перезагружают страницу, хотя цель находится на ней же и не требует этого…

anchor.js

Мне показалось логичным решать эту проблему во frontend-е, с помощью JavaScript-а. Такой подход получается более универсальным. Js-библиотека должна натравливается на страницу или её часть, отслеживая клики на ссылки содержащие якоря (анкоры). При клике на такую ссылку скрипт блокирует стандартное поведение браузера и скролит сам до нужной области страницы (естественно не перезагружая её).

Приготовившись уже писать свою библиотеку и начав выбирать название для неё, «нагуглил» скрипт anchor.js. Плагин позиционируется себя как инструмент для плавных переходов по якорям, но он так же решает и проблему тега <base>.

Пример подключение плагина на странице:

<script src="http://yastatic.net/jquery/2.1.4/jquery.min.js"></script>
<script src="/examples/anchor-with-base/anchor-master/anchor.js"></script>
<script>
$( 'document' ).ready( function() {
	$( 'a[href*=#]' ).anchor( {
		transitionDuration : 500, // время анимации в миллисекундах
		transitionTimingFunction: 'linear' // тип анимации, по умолчанию 'swing'
	} );
} );
</script>

Пример работы плагина вместе с тегом <base> можно посмотреть по ссылке.

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