Шаблоны
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/template-element.
Элемент предназначен для хранения «образца» разметки, невидимого и предназначенного для вставки куда-либо.
Конечно, есть много способов записать произвольный невидимый текст в HTML. В чём же особенность ?
Его отличие от обычных тегов в том, что его содержимое обрабатывается особым образом. Оно не только скрыто, но и считается находящимся вообще «вне документа». А при вставке автоматически «оживает», выполняются из него скрипты, начинает проигрываться видео и т.п.
Содержимое тега , в отличие, к примеру, от шаблонов или , обрабатывается браузером. А значит, должно быть корректным HTML.
Оно доступно как DocumentFragment в свойстве тега content . Предполагается, что мы, при необходимости, возьмём content и вставим, куда надо.
- Вставка шаблона
- Итого
- Html шаблон для скрипта
- Стилизация кнопки загрузки
- Адаптивная галерея least.js
- Адаптивное многоуровневое меню
- Адаптивное Retina меню
- Размытое меню на CSS3
- Стильная форма регистрации на CSS3
- HTML5 Boilerplate
- Круглое социальное меню
- Turn.js — перелистывание страниц
- Кисть с эффектом кривой Безье
- Bubble кисть для Paint программы
- HTML templates with vanilla JavaScript
- The template element
- The template element is even worse with lots of items
- Creating HTML with JavaScript
- A hybrid approach
Вставка шаблона
Пример вставки шаблона tmpl в Shadow DOM элемента elem :
Привет из подполья!
- В элементе #elem содержатся данные в некоторой оговорённой разметке.
- Шаблон #tmpl указывает, как их отобразить, куда и в какие HTML-теги завернуть содержимое #elem .
- Здесь шаблон показывается в Shadow DOM тега. Технически, это не обязательно, шаблон можно использовать и без Shadow DOM, но тогда не сработает тег .
Можно также заметить, что скрипт из шаблона выполнился. Это важнейшее отличие вставки шаблона от вставки HTML через innerHTML и от обычного DocumentFragment .
Также мы вставили не сам tmpl.content , а его клон. Это обычная практика, чтобы можно было использовать один шаблон много раз.
Итого
Тег не призван заменить системы шаблонизации. В нём нет хитрых операторов итерации, привязок к данным.
Его основная особенность – это возможность вставки «живого» содержимого, вместе со скриптами.
И, конечно, мелочь, но удобно, что он не требует никаких библиотек.
Html шаблон для скрипта
Несколько интересных эффектов для текстовых полей включающих некоторые новые методы реализации и идеи. В основном используются CSS transitions и изредка CSS animations на label тегах или на псевдо-элементах.
Стилизация кнопки загрузки
Креативные кнопки выполняющие роль прогресс бара, отображающего ход выполнения, какого-либо действия требующего время.
Адаптивная галерея least.js
Пришло время адаптивных сайтов, продолжаем эту тематику в галерее, одинаково хорошо отображаемой как на десктопе, так и на мобильных устройствах. В галерее используется плагин lazyload — отложенная загрузка картинок, который позволяет экономить трафик. При наведении курсора на изображение отображается краткое описание, а по клику происходит показ полной версии изображения. По умолчанию изображения формируются случайным образом на странице.
Адаптивное многоуровневое меню
Экспериментальное меню позволяющее с экономить пространство на вашем сайте, где требуется использование много уровневого меню. «Детки» заменяют собой «родителей» не загромождая страницу. Меню можно устанавливать на страницы с адаптивным дизайном.
Адаптивное Retina меню
Красочное адаптивное меню с поддержкой Retina дисплеев. В зависимости от размера окна браузера меню принимает один из трех видов: для десктопов — обычное горизонтальное отображение, двухколоночное для планшетов и мобильная версия ввиде иконки-ссылки для отображения и скрытия пунктов меню на экранах небольших размеров. Для поддержки Retina используются иконки ввиде шрифта, а не ввиде картинок, таким образом мы избегаем пикселизации при изменении размера.
Размытое меню на CSS3
Простое горизонтальное меню с эффектом размытия и с элементом адаптивности. Используется CSS3 и HTML5.
Стильная форма регистрации на CSS3
Простая и стильная регистрационная форма для сайта. Для её работы требуется jQuery и плагин placeholder.
HTML5 Boilerplate
«Самый популярный фронтенд шаблон» — или как было написано раньше — это HTML/CSS/JS шаблон для всех маньяков, пишущих быстрые, неглючные и ориентированные на будущее сайты.
Круглое социальное меню
Сделаем круглое социальное меню в котором не используются изображения. Иконки социальных сервисов берутся из специального шрифта.
Turn.js — перелистывание страниц
Turn.js плагин добавляющий эффект похожий на перелистывание страниц в книгах для HTML5. Используется аппаратное ускорение. Работает на планшетах и смартфонах. Прост в управлении и весит всего 6Kb.
Кисть с эффектом кривой Безье
Создадим ещё одну кисть, теперь уже с эффектом кривой Безье, для созданной нами ранее paint программы.
Bubble кисть для Paint программы
Сейчас сделаем bubble кисть для созданной в прошлой статье paint программы на html5.
HTML templates with vanilla JavaScript
One of my new subscribers asked me how to use a chunk of HTML as a template that you can add data from another source (like an API) to. So today, we’re going to explore that.
The template element
A few years back, HTML added the template element. It’s purpose is to hold HTML that shouldn’t be rendered as-is, but is intended to be used as a template with JavaScript later.
Here, the #list-item element contains a list item that can be used to generate a list of wizards. It contains an li element with a .wizard class on it.
div id="app">div> template id="list-item"> li class="wizard">li> template>
In your JavaScript, you might use the document.querySelector() method to get the #app element (where you want to add your list) and the #list-item element (the template).
There’s also an array of wizards .
// My starting JS let app = document.querySelector('#app'); let listItem = document.querySelector('#list-item'); let wizards = ['Merlin', 'Gandalf', 'Neville'];
To do this, first, I would create a ul element with the document.createElement() method.
// Create a list element let list = document.createElement('ul');
Next, I would use a for. of loop to loop through my wizards .
Inside the loop, we want to use the listItem template for the HTML. The template element makes this absurdly difficult for something that’s supposed to make templating easier.
The content inside is a document fragment that you can access with the content property. Because we’re going to be using it more than once, we want to create a clone of it with the Element.cloneNode() method.
// Loop through each wizard and add it to the list for (let wizard of wizards) // Get and clone the inner content let li = listItem.content.cloneNode(true); >
At this point, li is a copy of document fragment in our template . We want the li element. For that, we need to use the document.querySelector() method to find it.
// Loop through each wizard and add it to the list for (let wizard of wizards) // Get and clone the inner content // Then, find the li element let li = listItem.content.cloneNode(true).querySelector('li'); >
Now, we can add the wizard to it with the Node.textContent property, and add it to the list element with the Element.append() method.
// Loop through each wizard and add it to the list for (let wizard of wizards) // Get and clone the inner content // Then, find the li element let li = listItem.content.cloneNode(true).querySelector('li'); // Add the wizard text, then add it to the list li.textContent = wizard; list.append(li); >
Then, finally, we can append the entire list to the DOM.
// Add the list to the UI app.append(list);
As you can see, this kind of sucks.
The template element is even worse with lots of items
Imagine if your template actually looked like this instead.
template id="list-item"> div class="wizard"> strong id="wizard-name">strong> div> template>
First, I would create an array to hold the elements I’m going to create from my template.
// Create an array of elements let elems = [];
Next, I’d loop through each wizard , get the template content, clone it, and look for the div inside.
// Loop through each wizard for (let wizard of wizards) // Get the content and clone it // Then, find the div element let div = listItem.content.cloneNode(true).querySelector('div'); >
I’d use the document.querySelector() to find the strong element inside the div , and set it’s textContent property to the value of the wizard .
Then, I’d use the Array.push() method to add the div to the elems array.
// Loop through each wizard for (let wizard of wizards) // Get the content and clone it // Then, find the div element let div = listItem.content.cloneNode(true).querySelector('div'); // Get the strong element inside the div let strong = div.querySelector('strong'); // Add the wizard name strong.textContent = wizard; // Add the div to the elems array elems.push(div); >
Finally, I would use the Element.append() method to add each element, using the spread syntax operator to pass the whole array in at once.
// Add the elements to the UI app.append(. elems);
As you can see, this is a huge pain in the ass, and that’s just with one element! Imagine doing this with multiple pieces of data across multiple elements.
This is, in my opinion, a big part of why the template element never really saw widespread use. It’s just not very functional.
Creating HTML with JavaScript
As a result of these challenges, it’s a lot more common for people to use template literals and generate their HTML entirely in JavaScript. With this approach, you skip the template element entirely.
There are a few ways to approach it, but the one beginners find the most readable is to first create an empty string to hold the html .
// Create an HTML string let html = '';
On each loop, you append (or concatenate) the html string with another HTML string. Template literals make it really easy to add variable content inside the string.
When you’re done, you can use the Element.innerHTML property to add your html string to the UI.
(If you’re using third-party data, don’t forget to sanitize your HTML string first to protect against XSS attacks.)
// Loop through each wizard for (let wizard of wizards) html += ` $wizard> `; > // Add the HTML to the UI app.innerHTML = html;
This approach is clean and simple, and as a result, far more common.
A hybrid approach
There is one technique you can use that combines both of these approaches.
The template element does not support string interpolation (replacing variables with data) like template literals do. But, you can use a little bit of JavaScript to use it that way.
A while back, I found a little helper function on StackOverflow that interpolates a plain old string like a template literal.
/** * Get a template from a string * https://stackoverflow.com/a/41015840 * @param str The string to interpolate * @param params The parameters * @return The interpolated string */ function interpolate (str, params) let names = Object.keys(params); let vals = Object.values(params); return new Function(. names, `return \`$str>\`;`)(. vals); >
Pass in the string as the first argument, and an object of parameters as the second.
To use it, we would setup our template element with variables in it just like we would a template literal.
template id="list-item"> div class="wizard"> strong>$strong> div> template>
Inside our JavaScript, we would pass the template elements Element.innerHTML property value into the interpolate() function as the string.
The params need to be an object, so we’ll wrap our wizard in an object and pass that in as the second argument. We’ll concatenate the string that’s returned back to the html string.
// Create an HTML string let html = ''; // Loop through each wizard for (let wizard of wizards) html += interpolate(listItem.innerHTML, wizard>); > // Add the HTML to the UI app.innerHTML = html;
The value of this is pretty minimal in our simple example, but can be pretty awesome with larger templates.
There are a few drawbacks to this approach, though. The biggest one is that it uses the Function() method, which can expose you to cross-site scripting attacks with third-party data.
Also, unlike a real template literal, it cannot support logic ( if. else , loops, and so on) inside the template.
This is a cool trick for special circumstances, but I would generally recommend against using it.
Hate the complexity of modern front‑end web development? I send out a short email each weekday on how to build a simpler, more resilient web. Join over 14k others.
Made with ❤️ in Massachusetts. Unless otherwise noted, all code is free to use under the MIT License. I also very irregularly share non-coding thoughts.