Внедрение SVG с литералами шаблона не работает в браузере

Моя идея состоит в том, чтобы внедрить встроенный SVG в мой HTML, используя литералы шаблонов. Цель состоит в том, чтобы просто использовать преимущества стилизации встроенных SVG-иконок с помощью CSS, но избегать раздувания html-кода с помощью SVG. Также очень легко повторно использовать повторяющиеся значки, просто добавив соответствующий класс. Также все значки или векторные элементы, такие как логотип, могут храниться в одном файле JS. Я знаю, это странная идея, но я нашел ее полезной для моего проекта.

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

Также приветствуются любые идеи, как его оптимизировать и заставить работать лучше.

var iconLogo = document.querySelectorAll(".ric-logo");
var i; 
for (i = 0; i < iconLogo.length; i++) {
    iconLogo[i].innerHTML = `
<svg width="120px" height="18px" viewBox="0 0 120 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="ric-logo" stroke="none" stroke-width="1" fill="black" fill-rule="evenodd">
                <path d="M23.326087,0 C23.2252174,0 23.1275,0 23.0266304,0 L23.0266304,0 L2.52173913,0 C1.12902107,-8.82200545e-17 1.70558772e-16,1.16795283 0,2.60869565 L0,15 L5.04347826,15 L5.04347826,5.2173913 C5.04347826,4.8572056 5.32573353,4.56521739 5.67391304,4.56521739 L22.9730435,4.56521739 C23.631932,4.55997742 24.1901947,5.0660023 24.2717391,5.7423913 C24.306535,6.10977596 24.1892199,6.47520901 23.948885,6.74807191 C23.7085502,7.02093481 23.3677046,7.17567223 23.0108696,7.17391304 L7.56521739,7.17391304 L7.56521739,11.7391304 L23.0266304,11.7391304 L23.0266304,11.7391304 C23.1275,11.7391304 23.2252174,11.7391304 23.326087,11.7391304 C26.4597026,11.7391304 29,9.11123658 29,5.86956522 C29,2.62789386 26.4597026,1.98495123e-16 23.326087,0 Z" id="Path"></path>
                <path d="M64.9565217,1.21154527e-06 L61.173913,1.21154527e-06 C60.170401,-0.000815107822 59.2077021,0.410915432 58.4977174,1.14456624 L49.8796739,10.0532605 C49.6430123,10.2978107 49.3221127,10.4350542 48.9876087,10.4347821 L46.673913,10.4347821 C46.3257335,10.4347821 46.0434783,10.142794 46.0434783,9.78260833 L46.0434783,1.21154527e-06 L41,0 L41,12.3913036 C41,13.8320462 42.1290211,14.9999988 43.5217391,14.9999988 L49.826087,14.9999988 C50.829599,15.0008151 51.7922979,14.5890846 52.5022826,13.8554338 L61.1108696,4.95000041 C61.3493224,4.70184137 61.674158,4.56319679 62.0123913,4.56521787 L64.326087,4.56521787 C64.6742665,4.56521787 64.9565217,4.85720602 64.9565217,5.21739167 L64.9565217,14.9999988 L70,15 L70,2.60869644 C70,1.16795385 68.8709789,1.21154527e-06 67.4782609,1.21154527e-06 L64.9565217,1.21154527e-06 Z" id="Path"></path>
                <path d="M114,10 L120,10 L120,16 C120,17.1045695 118.992641,18 117.75,18 L114,18 L114,10 Z" id="Path"></path>
                <path d="M106,0 L106,9.7826087 C106,10.1427944 105.720178,10.4347826 105.375,10.4347826 L87.625,10.4347826 C87.279822,10.4347826 87,10.1427944 87,9.7826087 L87,0 L82,0 L82,12.3913043 C82,13.8320472 83.1192881,15 84.5,15 L108.5,15 C109.880712,15 111,13.8320472 111,12.3913043 L111,0 L106,0 Z" id="Path"></path>
    </g>
</svg>
`;
}
/* Styling all instances of SVG */

.ric-logo * {
  fill: blue;
	width: 120px;
	height: 15px;
};
<body>
<header class="header-menu">
	<div class="ric-logo">
	</div>
	<div class="menu-content">
		<ul>
			<li><a href="#"></a>Item-1</li>
			<li><a href="#"></a>Item-2</li>
			<li><a href="#"></a>Item-3</li>
			<li><a href="#"></a>Item-4</li>
		</ul>
	</div>
</header>
<main>
  <!-- Test repeating SVG class -->
  <div class="ric-logo">
	</div>
</main>
<footer></footer>
</body>


person Yury S    schedule 08.03.2019    source источник
comment
Рассматривали ли вы просто использование фонового изображения css вроде этого: .ric-logo { background-image: url(/images/ric-logo.svg); } ?   -  person Ted    schedule 08.03.2019
comment
Привет, Тед, моя идея состоит в том, чтобы SVG работал так же, как Inline SVG. Если я использую его как внешний файл (изображение), у меня нет доступа к его внутренним частям. Вы можете видеть в моем фрагменте, что я могу применить стиль CSS к этому SVG — изменить заливку цветом, изменить что-то при наведении, например, или даже анимировать некоторые части. На самом деле это может быть очень полезно — довольно простое, легкое решение без каких-либо внешних библиотек. Но я не могу понять, почему это не работает.   -  person Yury S    schedule 08.03.2019
comment
Ах, попался. Это имеет смысл.   -  person Ted    schedule 08.03.2019
comment
В качестве альтернативного решения, чтобы избежать раздувания, вы можете создать корень svg в нижней части вашей страницы, непосредственно перед тегом </body>. Таким образом, вас не будет беспокоить код. В своем HTML вы можете создать элемент svg и использовать значок с <use xlink:href = "#ric-logo" . Если вы посмотрите на css-tricks.com, вот как они решают эту проблему.   -  person enxaneta    schedule 09.03.2019
comment
Благодарю вас! Я уже понял (вы можете увидеть пример и фрагмент ниже), но решение, которое вы предлагаете, весьма полезно, особенно если SVG не слишком много. Первоначальная идея с js-инъекцией уже работает, и я нашел ее очень полезной (я могу загрузить все иконки и иллюстрации для всего сайта только один раз из одного js-файла).   -  person Yury S    schedule 30.05.2019


Ответы (2)


Я не уверен, как вы структурировали свои файлы, поэтому, возможно, я неправильно воспроизводю ваши проблемы. Дайте мне знать, если я сделал какие-либо ложные предположения.

Во-первых, codepen и фрагменты на Stack Overflow автоматически включают CSS и JS, а локальные файлы — нет. Если вы еще этого не сделали, вам нужно включить соответствующие теги <script> и <style>, содержащие ваши css и js.

Если вы уже делаете это и только что отредактировали их для целей этого вопроса, то другая возможная проблема заключается в том, что предоставленный вами javascript вы включили в верхнюю часть своей страницы. document.querySelectorAll(".ric-logo") не будет работать до тех пор, пока страница не будет загружена, и если вы поместите предоставленный вами javascript вверху страницы, он запустится до завершения загрузки страницы. Самый простой способ исправить это — поместить javascript внизу страницы.

Если по какой-то причине вы не хотите, чтобы ваш javascript был внизу вашей страницы, вам нужно что-то вроде jQuery $(document).ready или одна из ванильных альтернатив из этот вопрос.

person Nicholas    schedule 08.03.2019
comment
Привет Николай, Спасибо! Похоже, это работает. Я просто поместил свой ‹сценарий› внизу страницы. - person Yury S; 08.03.2019
comment
Я не думал о том, что document.querySelectorAll(".ric-logo") будет работать только тогда, когда весь контент загружен. Очевидно, это правильно, потому что этот скрипт должен найти все селекторы. Я проверил ваши предложения о ванильном решении, чтобы все зависимости оставались наверху, поэтому оно также работает хорошо. Я прикреплю фрагмент, может быть, это будет полезно для других - person Yury S; 09.03.2019

@Nicholas был прав, и проблема заключалась в том, что document.querySelectorAll не работал, пока не загрузился весь материал DOM. Таким образом, одно из решений — разместить document.querySelectorAll внизу страницы. Другой способ — использовать функцию, которая запускает ваши скрипты при загрузке страниц. Это объясняется здесь.

Я применил его к своему сценарию, и он работает хорошо. Так что, если вам интересно, я публикую вырезки здесь. Это может быть полезно для создания шаблонов с использованием строковых литералов или, как в моем случае, для динамического внедрения встроенного SVG.

// Icons SVG injection 
// Function that run code when DOM is loaded
function ready(callback){
	// in case the document is already rendered
	if (document.readyState!='loading') callback();
	// modern browsers
	else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
	// IE <= 8
	else document.attachEvent('onreadystatechange', function(){
    if (document.readyState=='complete') callback();
    });
}

ready(function(){
// All inside tht function executes when DOM is loaded

// Logo SVG 
	var mySvg = document.querySelectorAll(".my-svg");
	var i; 
	for (i = 0; i < mySvg.length; i++) {
	    mySvg[i].innerHTML = `
      <svg width="188px" height="188px" viewBox="0 0 188 188" version="1.1">
        <circle id="Oval" fill="#FC4903" cx="94" cy="94" r="94"></circle>
</svg>
  `
	};

});
/* styling svg */


.my-svg * {
  fill: red;
	width: 200px;
	height: 200px;
};
<!-- creating container where you like to insert SVG -->
<div class="my-svg">
  <div></div>
</div>

person Yury S    schedule 08.03.2019