Миниблог

CLS и смещение макета, решение в массиве. Скелетоны. Пример в Fenom.

И вначале реклама, небольшой блок. Прошу не сердиться и не вносить ее в фильтры блокировщиков.

подробнее о рекламодателе можно узнать внутри блока
Спасибо. А теперь сам материал.

Разрабатывая (ну, то есть программируя) динамическую подгрузку данных через fetch на сайте, я столкнулся с предупреждением от PageSpeed Insights, которое люто понизило мне балл и звучало примерно так

" Устраните большие смещения макета 2 смещения макета " или же другим языком это называется CLS.

Смещение макета (CLS, Cumulative Layout Shift) — это метрика, которая измеряет, насколько непредсказуемо изменяется расположение элементов на странице во время её загрузки. В идеале, контент на странице должен оставаться стабильным, чтобы пользователь мог взаимодействовать с ним без проблем. Высокое значение CLS указывает на плохой пользовательский опыт, так как элементы могут сдвигаться, вызывая случайные клики или другие неудобства. Оптимизация CLS включает в себя фиксацию размеров изображений, отложенную загрузку скриптов и предотвращение внезапных изменений макета. 

Простым языком, открыв сайт с мобильного телефона, и, несмотря на анимашку "загрузка данных", при их получении этих данных, слой-контейнер div может увеличиться и остальной контент, соответственно "прыгнет". 

Чтобы этого не происходило, то создается заранее макет-скелет, куда будут загружаться данные с небольшой анимацией. Очень часто это называется "скелетон", а в bootstrap - это placeholder. 

Например, у меня в цикле выводятся карточки с фио и ссылками. Данные в них, например фотография, периодически меняются и поэтому приходится их подгружать. Вот решение с fenom + bootstrap верстка (да, это для чанка в modx)

<div id="person-container placeholder-glow">
{foreach:escape $array as $item index=$index}
{if $index == 0}<div class="row">{/if}
{if $index < 12}
<div class="col-6 col-md-3" data-id="{$item['id']}">
<h4 class="text-center" id="placeholder-name-{$item['id']}">{$item['name'] | urldecode}</h4>
{if $item['var'] is not empty}<p class="text-center" style="margin-top:-2px;"><i class="fa-regular fa-id-badge"></i> {$item['var'] | urldecode }</p>{/if}
<div class="placeholder-glow"> <div class="detail placeholder col-12" id="detail-{$item['id']}" style="min-height: 299px;"></div></div>
</div>
{if $index == 11}</div><p>А также:</p>{/if}
{elseif $index >= 12 && $index < 21}
<strong>{$item['name'] | urldecode}</strong>
{if $item['var'] is not empty} ({$item['var']}) {/if}
{if $item@last} и другие{else}, {/if}
{/if}
{foreachelse}
<div>Нет данных</div>
{/foreach}
</div>

Давайте заодно и с Fenom познакомимся. Fenom - это один из шаблонизаторов (который, обычно, позволяет обрабатывать получаемые данные на странице или шаблоне, без сложного и тяжелого кода, но при этом работать с динамикой, обрабатывать получаемые данные и т.д., по сути помогая с разделяемой логикой приложения и представления), который используется в MODX, как альтернатива встроенному. Его преимущества огромны, что видно из справки операторов https://github.com/fenom-template/fenom/blob/master/docs/ru/readme.md  . Чанк ожидает данные, которые передает сниппет и fenom разбирает массив по следующему принципу 

1. если элемент первый (индекс =0) до создаем строку в bootstrap {if $index == 0}<div class="row">{/if}

2. первые 12 элементов (от 0 до 11) мы создаем столбик в половину или 1\4 от строки {if $index < 12} с data-id для последующей обработки fetch 

3. заполняем полями, где указываем в классах свойство placeholder при этом получаемые поля декодируем,, чтобы не было html сущностей {$item['name'] | urldecode}

4. если поле с var не пусто, то выводит с иконкой из font-awesome и тоже с классом placeholder {if $item['var'] is not empty}<p class="text-center" style="margin-top:-2px;"><i class="fa-regular fa-id-badge"></i> {$item['var'] | urldecode }</p>{/if}

5. заполняем основной слой, который получит данные из fetch запроса 

6. если записей больше 12, но меньше 20 то выводим их списком {if $index == 11}</div><p>А также:</p>{/if}
{elseif $index >= 12 && $index < 21}
<strong>{$item['name'] | urldecode}</strong>

7. при этом, если запись будет последняя, то закончим фразой "и другие", если нет, то ставим запятую. {if $item@last} и другие{else}, {/if}

8. если массив в целом пустой, то выведем, что нет данных (правда макет сместится, только сейчас это понял :-) 

{foreachelse}
<div>Нет данных</div>
{/foreach}

9. Ну и все это оборачиваем в общий div. 

Таким образом мы на странице получим красивый внешний вид подгрузки данных, а заодно быстро вас познакомил с кусом обработки массивов на fenom. На самом деле он может гораздо больше.

Документация на placeholders в bootstrap - https://getbootstrap.com/docs/5.1/components/placeholders/

Лично я стараюсь его (bootstrap) уже не использовать, а работать с bulma css или tailwind, поэтому вот есть очень хорошая библиотека с готовыми макетами https://dgknca.github.io/css-skeletons/  - можно даже найти хороший. И очень легко интегрируется и есть поддержка cdn. 

Bulma тоже поддерживает из коробки https://bulma.io/documentation/features/skeletons/ причем даже кнопки, изображения и все, что только можно .

 

 Ну а если вы в целом не знаете про fetch (например, я сам только недавно стал внедрять вместо классического ajax), то вот неплохая книга из Читай-Города про асинхронную загрузку данных

bookjs 5aa79 

Купить можно здесь -  https://shp.pub/70slgr?erid=2SDnjcxBP5c  (Реклама: ООО "Новый книжный центр" ИНН 7710422909)

Похожее

draw I
draw I
draw I
draw I

 quote a81ca

Если вдруг вам было здесь полезно, уютно и приятно, что захотелось меня отблагодарить - вы можете пожертвовать мне на кофе.

 

i

Будет осуществлен переход на сайт Yoomoney

А это что? а это мой канал https://t.me/spoOky_blog

draw I

 


Внимание: На сайте могут присутствовать ссылки ePN

Мини-портфолио

очередной бесполезный блог