Скелетон загрузки
Скелетон загрузки — это визуальная заглушка для области интерфейса, в которой данные еще не готовы к показу. Компонент выводит анимированную линию или круг и помогает сохранить структуру страницы во время загрузки списка, карточки или аватара.
В Bitrix Framework за скелетон отвечает расширение ui.system.skeleton. В нем доступны функции Line, Circle и renderSkeleton. Для Vue-компонентов используется отдельное расширение ui.system.skeleton.vue.

Подключить расширение
Если вы подключаете компонент из PHP, загрузите расширение ui.system.skeleton.
\Bitrix\Main\UI\Extension::load('ui.system.skeleton');
Если вы работаете в модульном JavaScript, импортируйте функции из ui.system.skeleton.
import { Line, Circle, renderSkeleton } from 'ui.system.skeleton';
Создать скелетон
Функция Line(width, height, radius) создает линию скелетона. Функция Circle(size) создает круглый скелетон.

import { Line, Circle } from 'ui.system.skeleton';
const container = document.getElementById('profile-placeholder');
container.append(
Circle(40),
Line(180, 14, 8),
Line(120, 12, 8),
);
Элементы, созданные через Line() и Circle(), можно сразу добавить в контейнер или заменить ими загружаемый блок.
Настроить линию
Передайте в Line() размеры скелетона:
-
width— ширина скелетона в пикселях. Если параметр не передан или равенnull, линия занимает100%ширины контейнера. -
height— высота скелетона в пикселях. По умолчанию используется12px. -
radius— радиус скругления в пикселях. По умолчанию используется8px.
import { Line } from 'ui.system.skeleton';
const titleSkeleton = Line(240, 18, 6);
Чтобы оставить значение по умолчанию для одного из параметров, передайте null. Например, Line(null, 16, 8) создаст линию со стандартной шириной.
Настроить круг
Передайте в Circle(size) размер круга в пикселях.
import { Circle } from 'ui.system.skeleton';
const avatarSkeleton = Circle(48);
По умолчанию используется размер 18px.
Убрать скелетон после загрузки
Скелетон не хранит состояние загрузки и не заменяет данные автоматически. После получения данных удалите созданные узлы или замените контейнер содержимым.
import { Line } from 'ui.system.skeleton';
const container = document.getElementById('task-title');
const skeleton = Line(200, 16, 8);
container.append(skeleton);
fetch('/local/ajax/task-title.php')
.then((response) => response.text())
.then((title) => {
skeleton.remove();
container.textContent = title;
});
Отрисовать скелетон из шаблона
Функция renderSkeleton(path, root) асинхронно загружает HTML-шаблон по адресу path и вставляет его в контейнер root. В path передайте путь к HTML-шаблону, доступный браузеру. Promise можно не обрабатывать, если дальнейший код не зависит от завершения отрисовки.
import { renderSkeleton } from 'ui.system.skeleton';
const root = document.getElementById('deal-card-skeleton');
renderSkeleton('/local/js/deal-card-skeleton.html?v=1', root);
В шаблоне можно использовать записи Line() и Circle(). При загрузке шаблона компонент заменит их на HTML соответствующих скелетонов.
<div class="row">
Circle(40)
<div>
Line(180, 14, 8)
Line(120, 12, 8)
</div>
</div>
<style>
.row {
display: flex;
align-items: center;
gap: 12px;
padding: 16px;
}
</style>
Для каждого шаблона используйте отдельный контейнер. Не вызывайте renderSkeleton() повторно для элемента, в который скелетон уже отрисован.
HTML-шаблон кешируется браузером и в памяти приложения до перезагрузки страницы. После правок шаблона добавляйте к пути версию, чтобы сбросить кеш: renderSkeleton('/local/js/deal-card-skeleton.html?v=2', root);.
Стили скелетона прописывайте в <style> внутри HTML-шаблона. Компонент отрисовывает содержимое в изолированной области, поэтому CSS основной страницы туда не доходит.
Подставить сохраненные данные
В HTML-шаблоне можно указать ключ в фигурных скобках, например {dealTitle}. При отрисовке renderSkeleton() заменит такую запись значением из localStorage модуля main.core. Сохраните значение через localStorage.set() до вызова renderSkeleton():
import { localStorage } from 'main.core';
localStorage.set('dealTitle', 'Сделка №42');
<div class="deal-card-skeleton">
<div class="deal-card-skeleton__title">{dealTitle}</div>
Line(180, 12, 8)
</div>
Такой способ подходит для короткого текста, который нужно показать рядом со скелетоном до загрузки актуальных данных.
Использовать во Vue
В расширении ui.system.skeleton.vue доступны компоненты BLine и BCircle. Компонент BCircle также доступен под именем Circle.
import { BLine, BCircle } from 'ui.system.skeleton.vue';
export const UserCardPlaceholder = {
components: {
BLine,
BCircle,
},
template: `
<div class="user-card-placeholder">
<BCircle :size="40"/>
<div class="user-card-placeholder__content">
<BLine :width="180" :height="14" :radius="8"/>
<BLine :width="120" :height="12" :radius="8"/>
</div>
</div>
`,
};
BLine принимает свойства width, height и radius. Переданные значения применяются в пикселях. Если width не передан, линия занимает 100% ширины контейнера.
BCircle принимает свойство size в пикселях. По умолчанию используется 18px.
Подробнее о работе с Vue в Bitrix Framework читайте в статье Vue.js.