В процессе разработки JS модулей, претендующих на переиспользуемость, часто возникает необходимость кроме js-кода и разметки подгрузить еще и файл со стилями. Как известно, сами по себе стили могут быть добавлены к документу тремя способами: через тэг link, через тэг style, и через атрибут style. В зависимости от выбранного способа можно получить различные плюсы и минусы. Я предлагаю посмотреть на способ, состоящий из использования тэга link, но избавленный от проблемы отсутствия события окончания загрузки таблицы стилей со стороны браузера.
Начнем с ответа на вопрос «Зачем именно через тэг link?»
Дело в том, что от модуля обычно хочется получить возможность удобно кастомизировать его визуальное представление.
Если мы захотим использовать атрибут style прямо в нашей разметке, то в дальнейшем при переиспользовании нам придется как-то эти атрибуты менять — супер неудобно и не гибко.
Если мы захотим использовать тэг style, то возникает проблема с тем, что для кастомизации таких стилей придется также вставлять в документ тэг style с нужным содержимым, что также не очень удобно.
Если мы захотим использовать тэг link, то мы сможем просто подключить нашу собственную таблицу стилей после загруженной и подправить представление по-умолчанию под сиюминутные нужды.
Из вышеперечисленного выходит, что вариант с тэгом link наиболее гибкий, т.к. позволяет переопределить стили при использовании компонента наибольшим числом способов.
Как написано в документации RequireJS, для подгрузки css можно использовать такой код:
Он всем неплох, кроме того что вы не узнаете, когда именно будет подгружен ваш css (и будет ли вообще, могли же, например, в путях опечататься). Эта проблема чревата еще и тем, что может вызвать некрасивое поведение картинки, в случае если рендер страницы будет проводится до окончания загрузки файла.
А хочется написать компонент примерно так:
Но как же потом запихнуть полученный текст css в нашу страницу? Тэг style мог бы нам помочь, но ранее было решено, что наш вариант — это именно link.
Предлагаемое решение — это Data URL (если кто не знает, что это такое, здесь можно посмотреть).
Добавлять будем примерно так:
Метод несомненно имеет некоторые минусы, из очевидных — base64 кодирование увеличивает объем данных, теоретически можно столкнуться с ограничениями на длину URL для некоторых браузеров. Но если объем стилей небольшой, то метод выглядит вполне рабочим.
UPD:
Cпасибо oledje за подсказку, base64 кодирование для текста не нужно, лучше подойдет URL encoding, подправил код.
для тех кому только код
define(["text!myCSS.css"], function(cssText) {
'use strict';
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css"
link.href = "data:text/css,"+encodeURI(cssText);
var cssLinks = document.querySelectorAll("link[rel=stylesheet]");
if (cssLinks.length > 0) {
cssLinks[0].parentElement.insertBefore(link, cssLinks[0]);
} else {
document.querySelector("head").appendChild(link);
}
});
Начнем с ответа на вопрос «Зачем именно через тэг link?»
Дело в том, что от модуля обычно хочется получить возможность удобно кастомизировать его визуальное представление.
Если мы захотим использовать атрибут style прямо в нашей разметке, то в дальнейшем при переиспользовании нам придется как-то эти атрибуты менять — супер неудобно и не гибко.
Если мы захотим использовать тэг style, то возникает проблема с тем, что для кастомизации таких стилей придется также вставлять в документ тэг style с нужным содержимым, что также не очень удобно.
Если мы захотим использовать тэг link, то мы сможем просто подключить нашу собственную таблицу стилей после загруженной и подправить представление по-умолчанию под сиюминутные нужды.
Из вышеперечисленного выходит, что вариант с тэгом link наиболее гибкий, т.к. позволяет переопределить стили при использовании компонента наибольшим числом способов.
Как написано в документации RequireJS, для подгрузки css можно использовать такой код:
function loadCss(url) {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
document.getElementsByTagName("head")[0].appendChild(link);
}
Он всем неплох, кроме того что вы не узнаете, когда именно будет подгружен ваш css (и будет ли вообще, могли же, например, в путях опечататься). Эта проблема чревата еще и тем, что может вызвать некрасивое поведение картинки, в случае если рендер страницы будет проводится до окончания загрузки файла.
А хочется написать компонент примерно так:
define(["text!myCSS.css", "text!myHTML.html"], function(cssText, htmlText) {
'use strict';
...
});
Но как же потом запихнуть полученный текст css в нашу страницу? Тэг style мог бы нам помочь, но ранее было решено, что наш вариант — это именно link.
Предлагаемое решение — это Data URL (если кто не знает, что это такое, здесь можно посмотреть).
Добавлять будем примерно так:
var link = document.createElement("link");
link.rel = "stylesheet";
link.type = "text/css"
link.href = "data:text/css,"+encodeURI(cssText);
var cssLinks = document.querySelectorAll("link[rel=stylesheet]");
if (cssLinks.length > 0) {
cssLinks[0].parentElement.insertBefore(link, cssLinks[0]);
} else {
document.querySelector("head").appendChild(link);
}
Метод несомненно имеет некоторые минусы, из очевидных — base64 кодирование увеличивает объем данных, теоретически можно столкнуться с ограничениями на длину URL для некоторых браузеров. Но если объем стилей небольшой, то метод выглядит вполне рабочим.
UPD:
Cпасибо oledje за подсказку, base64 кодирование для текста не нужно, лучше подойдет URL encoding, подправил код.