Скелетон
Сірі фігури на місці контенту, поки він вантажиться. Функційна підказка, а не декорація: форма скелетона це обіцянка того, що приїде.
Розмітка та сама, що в продукті. До кроку 7.28 тут стояло <div class="skcardbox"><div class="skcard">… - коробка всередині коробки, чого в продукті немає жодного разу, тому демо малювало подвійну рамку. Сітка була придушена інлайновим style="display:grid;grid-template-columns:repeat(3,1fr);gap:14px", тобто показувала не .skgrid, а інлайн поверх нього. І пульсації в демо не було зовсім, хоча анатомія її називала.
.skcard - повторює форму майбутньої картки: той самий квадратний знімок, той самий падінг, ті самі три рядки. Якщо форма не збігається, завантаження виглядає як перебудова. І саме це тут і було до 7.68: цей рядок обіцяв 10/11 - і картка малювала 10/11 від 620 угору, а під 620 вона квадратна. На 390 скелет виходив 171 × 188.09 над карткою 171 × 171: стрибок на 17px саме на телефоні. Обіцянка, написана на цьому стенді, не виконувалась там, де її найбільше видно.skline - 10px, радіус 4, ґрунт --bg-sunken. Три ширини l m s, щоб стос смуг не читався таблицею.skpulse - на контейнері, не на смузі. Каже «триває», а не «зламалось»Браузер обійшов 40 кольорових екранів на 1280 і 390: 140 елементів скелетона, 22 підписи класів, 5 екранів завантаження. Найчастіша частина - смуга - була написана шість разів.
| Ім'я | Файл до 7.28 | Шт | Висота | s | m | l |
|---|---|---|---|---|---|---|
.skline | skeleton.css | 78 | 10px | 50% | 72% | 90% |
.co-skel .sl | checkout-form.css | 3 | 11px | 46% | 72% | - |
.auth-skel .sl | auth-dialog.css | 2 | 11px | - | 70% | - |
.acc-subsk | account-shell.css | 1 | 12px | - | - | - |
.acc-h1sk | account-shell.css | 1 | 24px | - | - | - |
.skcardbox .skline | skeleton.css | - | 10px | власний ґрунт, який перекривався | ||
Висоти ні за чим не йдуть. Це перевірено, а не припущено: кожен екран завантажено двічі - як скелетон і як контент.
| Смуга | Стоїть на місці | Текст | Відношення |
|---|---|---|---|
.skline 10px | .pcard .nm | 16 / 20.8 | 0.63 |
.acc-h1sk 24px | .acc-h1 | 30 / 48 | 0.80 |
.acc-subsk 12px | .acc-sub | 14 / 22.4 | 0.86 |
Ні драбини, ні коефіцієнта - просто чотири числа. Скелетонна смуга це не висота тексту, це знак, який каже «тут буде рядок»; знак, що каже те саме, має казати це одним розміром. Тому рядок скрізь 10 - як уже було в 78 смугах з 84 - і власне число лишає тільки та смуга, що стоїть на місці заголовка: інше речення, а не промах.
| Що | Було | Стало | Скільки |
|---|---|---|---|
висота смуги .sl і .acc-subsk | 11px · 12px | 10px | 6 смуг |
.co-skel .sl.s | 46% | 50% | 1 |
.auth-skel .sl.m | 70% | 72% | 1 |
Два файли, що розійшлись на два відсотки щодо одного сірого прямокутника, - це не рішення, яке хтось ухвалював. Ширші за них два вузькі стовпчики (чекаут і діалог входу) стали на 2px нижчі, бо в кожному по дві смуги, - це наслідок, а не окрема зміна.
Найважливіше, чого не було на попередній редакції сторінки: .skpulse вішають на контейнер, і контейнер здебільшого це справжній компонент. Вісім з 22 підписів перепису - це живий компонент, вбраний в один клас.
| Носій | Що це |
|---|---|
.bb.skpulse | блок покупки на PDP |
.gmain.skpulse .gthumb.skpulse | галерея товару, велике фото і 4 мініатюри |
.acc-nav.skpulse .acc-cardgrid.skpulse | навігація і сітка кабінету |
.skgrid.skpulse | сітка карток каталогу |
Прозорість на батькові, тому нічому всередині не треба знати, що воно вантажиться. Саме тому це голий клас, а не щось, прив'язане до фігур цього файлу.
І тепер вона зупиняється. На кроці 7.28 додано @media (prefers-reduced-motion: reduce): підказка про завантаження не має права бути тим, від чого людині зле. Форма лишається, дихання зупиняється, прозорість фіксується на 0.78 - посередині циклу, щоб стан читався так само.
Перепис угорі цього файлу рахував смугу «шість разів у чотирьох файлах». Його знімали по 40 кольорових екранах на 7.28, а тренерський потік увійшов у колір на 7.95. Перерахунок по п'ятьох тренерських екранах завантаження дав дев'ять редакцій, і три нові не згодні ні з шістьма, ні між собою.
| Смуга | Висота | Радіус | Ґрунт | Де |
|---|---|---|---|---|
.sk-line | 13px | 6px | --bg-sunken | coach-client-loading |
.skln | 12px | 6px | --bg-rule | coach-order-loading, coach-orders-loading |
.qa-skel .sk | 12px | 6px | --bg-rule | coach-session-loading |
.skline | 10px | 4px | --bg-sunken | цей файл, і 78 смуг із 84 |
--bg-rule - це --warm-200, тобто --line-hair. Три тренерські екрани фарбували скелетонну смугу кольором волосини, поки решта продукту фарбувала --warm-100. Зміряно: rgb(233,231,226) проти rgb(242,240,237).
А рядки навколо смуг були тим самим компонентом, передрукованим руками. Не схожість - ті самі оголошення поруч: .sk-row = .oc-item (40 / 1fr, gap 11, волосина), .sk-ph = .oc-ph (40 квадрат, радіус 7), .qa-skel = .qa-row (44 / 1fr, gap 11, padding 9/0), .skhd = .ccard-hd, .skav = .ccard-av, .skclist = .clist, .skgrp = .od-grp.
Тому правило не «перенести їх у компонент», а правило 7.68, дочитане до кінця: скелетон - це обіцянка про коробку, яка його замінить, і єдина обіцянка, що не може розійтися, - сама коробка. Розмітка тих п'ятьох екранів тепер носить .ocard, .oc-item, .oc-ph, .ccard, .clist, .od-grp, .qa-row - справжнє, порожнє, зі .skline всередині. 20 приватних правил пішли в нуль, і жодне оголошення їх не замінило.
Додалось рівно двоє: заглушка кнопки, яку писали двічі (.sk-btn 38 × 120 і .skacts i 38 із flex: 1) - обидві на 2px нижчі за btn--s, чий min-height = --size-40; і речення під скелетоном.
Завантажуємо список клієнтів…
Це доводить 8.24 до кінця, а не скасовує його. Той крок зняв coach-clients-loading з третього імені скелетонної картки і поставив на .skcard; те саме читання на крок далі каже, що це взагалі не скелетонна картка, а картка клієнта, що стоїть порожня. .skcard лишається каталогу й кабінету, де коробка-замінник це .pcard; назвати їх - питання етапу 09, а не рух, який цей крок зміряв.
Був --bg-skeleton = #E9E7E2. Його називали три оголошення - .acc-h1sk, .acc-subsk, .skcardbox .skline - і всі три перекривались одним пізнішим рядком у account-shell.css, який повертав їх на --bg-sunken. Тому всі 140 виміряних елементів дали #F2F0ED, і жоден - #E9E7E2.
Те, що він справді фарбував: дві штрихові підкладки (.auth-visual, .wfh-mega .ms-ph) і одна волосина (.fgroup). Жодне з трьох не скелетон.
Перейменовано на слово власника, крок 7.28. Штриховка лишила значення й отримала ім'я того, що малює - --bg-hatch, 4 вживання (два елементи по дві зупинки градієнта). Волосина пішла на --line-hair, і це той самий --warm-200: примітив у себе в нотатці так і зветься - «plate pixel - the hairline». Нуль пікселів змінилось, одне ім'я перестало брехати. Ґрунт скелетонної смуги - --bg-sunken, і тепер він сказаний один раз у skeleton.css.
І остання умова пішла разом із сіткою, яку скелет обіцяє - раунд 3
Раунд 1 звів тут три числа до двох підлог із перемиканням на 620. Раунд 3 показав розгорткою, що саме це перемикання робить уproduct-grid.css: ряд карток губив колонку на 620, бо підлога стрибала зі 150 на 200. Сітка перейшла на пандус, а скелет, що лишився б із перемикачем, почав би брехати рівно на тій ширині - тобто повернув би дефект, який раунд 1 тут і полагодив. Тепер обидва читають --grid-col-fluid і --grid-gap-fluid, одним оголошенням без жодної умови. І 959 пішло: воно стояло в парі з 960 у account-shell.css, тому раунд 1 і лишив його винним - обидва склались на --bp-shell-wide разом.ПОВЕДІНКА НА ШИРИНІ - етап 10, крок 4
Від якого порогу:--bp-grid-2col (620), і більше жодного. Було три фіксовані кількості колонок на двох умовах - 1fr 1fr, потім три на 620, потім чотири на 1040, - і 1040 немає в реєстрі. Що саме міняється: сітка тепер auto-fill з тими самими двома підлогами, що й product-grid.css (--grid-col-min-narrow 150px і --grid-col-min 200px), і з тим самим проміжком. І це виправило дефект, якого ніхто не бачив: на 1280 справжня сітка товарів дає три колонки по 248px, а скелет малював чотири по 185 - обіцяв розкладку, якої сторінка не приносила. Тепер обидві дають 248 x 3, піксель у піксель.На кожному екрані, де дані приходять мережею: каталог, PDP, кабінет, чекаут, діалог входу. Принцип 2 - «ніколи порожній погляд». У продукті таких екранів 11 - зміряно tools/inventory.mjs по 88 кольорових екранах, за якорями цього файлу, - і на кожному скелетон повторює форму саме того, що там буде. На 7.28 їх було 5: тренерський потік увійшов у колір на 7.95, а на 8.38 його п'ять екранів завантаження перестали малювати власні скелетони.
Правило
Форма скелетона = форма контенту. Тоді завантаження виглядає як проявлення, а не як перебудова. Тому.skcard має те саме співвідношення знімка, що й картка товару.Антиправило
Не став спінер замість нього на списках. Спінер каже «чекай», скелетон каже «ось що буде». Для однієї дії (надсилання форми) спінер доречний - див. Форма чекауту. І не малюй смугу власної висоти «бо тут заголовок» - для заголовка є.acc-h1sk.Шістнадцять марок на трьох екранах завантаження стояли інлайновими висотами: смуга, чий РОЗМІР казав, за що вона стоїть, а ім'я не казало нічого. Тепер у кожної своя робота, і два екрани, що малювали ту саму марку двома числами, зійшлись в одну: рядок наявності в блоці покупки (30 x 40%) і провідна цифра картки акаунта (28 x 40%) - це одне, і зветься воно .skline--fig.
Цифри поза сходинками притягуються до найближчої, а нічия йде вгору - це власне правило файла про відступи, прочитане на розмір. Там, де сходинки поруч немає, літерал лишається і несе [?]: .skline--trust це 120, і воно стоїть за цілий блок довіри.
.skimg це aspect-ratio: 1, бо кожна фотографія цього продукту квадратна. Коробка логотипа не квадратна і не фотографія - вона широка й низька, тож brands-loading обіцяв не ту коробку правильним компонентом. Марка бере ту висоту, яку коробка справді має.
Сторінка звіряє себе з файлом: 18 власних класів і 1 стан оголошено в skeleton.css. Нижче - ті, яких на цій сторінці немає ні в демо, ні в розмітці.
Робота: СТАТУС. Рухається: opacity, рівний цикл. Тривалість цикл 1.1s, поза реєстром, крива ease-in-out. Значення читаються через var() з tokens.css: підміна токена в браузері веде за собою кожне з них, тобто числа у файлі немає. При prefers-reduced-motion рух зникає, а стан лишається.
Цикл, а не перехід: skpulse 1.1s ease-in-out infinite. Токена в нього поки немає - жоден із трьох щаблів циклу не виражає, і четвертий заводиться лише окремим рішенням власника. При prefers-reduced-motion цикл ЗАМІНЮЄТЬСЯ статикою (animation: none, рівний тон), а не прискорюється: пульс на 1ms це миготіння, тобто гірше.
Крок 4: цикл став токеном. 1.1s ease-in-out був одним із трьох останніх літералів продукту. Тривалість пішла в --dur-cycle і зберегла число цього файлу: за КІЛЬКІСТЮ ЕКЗЕМПЛЯРІВ пульс - це той цикл, який продукт реально показує (22 сірих і 39 кольорових проти трьох обертунів), тож токен узяв 1100, а обертуни віддали 200мс. Крива - linear, і платить за це саме цей файл: обертання іншої не терпить, а тристопкова рампа під linear має ріг на повороті. М'якість переїхала в кейфрейми, де формі циклу й місце - сім стопок, що наближають косинус. Кінцеві значення ті самі, 1 і .55.
Прочитані з skeleton.css, не переписані руками. Колір іде лише через роль, геометрія - напряму з примітива. Два числа без токена: 10px смуги і 240/320px двох іменованих смуг кабінету - вони названі рішеннями в самому файлі.
| Семантичні ролі (4) | Примітиви (19) |
|---|---|
--bg-sunken --elevation-1 --line-hair --text-muted | --dur-cycle --ease-cycle --fs-12 --grid-col-fluid --grid-gap-fluid --radius-12 --radius-4 --radius-8 --size-24 --size-30 --size-40 --size-46 --size-52 --size-64 --space-12 --space-16 --space-2 --space-24 --space-8 |
Окрема коробка без знімка - .skcardbox, і вона ніколи не стоїть усередині .skcard: це два різні візерунки, сітка кабінету і сітка каталогу. .skcardbox.span2 розтягує її на всю ширину сітки.
Якорі: .skline .skgrid .skcard .skcardbox .skpulse .sl
5 екранів у design/: account-loading.html, auth-loading.html, checkout-loading.html, listing-loading.html, product-loading.html. Плюс .skpulse на живих компонентах тих самих екранів.