Компонент · рівень 2

Блок опису

Чотири абзаци й чотири кадри на сторінці товару - там, де закінчуються таблиці й починається розповідь. Найменший файл із розібраних, і в ньому знайшлось те, чого в жодному не було: вигляд, який жив у скрипті.

рівень 2design/system/components/desc-block.css131 рядок8 селекторів21 оголошення2 екрани8 кадрів
Анатомія

Розмітка звідси - та сама, що на product.html. Фото підставляє design/_nav.js, як і в продукті.

Gold Standard 100% Whey - еталонний сироватковий протеїн від Optimum Nutrition. Основа формули - ізолят сироватки як перший інгредієнт, тому в кожній порції максимум чистого білка за мінімум зайвого.
зображення
Швидке засвоєння, 24 г білка та 5.5 г BCAA на порцію роблять його оптимальним вибором для відновлення після тренувань і щоденної норми білка. Підходить і початківцям, і досвідченим.
зображення
1Колонка .pdesc - 800 у ширину, по центру. Це єдина колонка тексту в продукті, яка себе обмежує: рядок довший за 800 читається гірше, а решта сторінки товару це таблиці й картки, які міряють себе інакше
2Абзац .pd-tx - 16 / --lh-airy. Основний кегль, а не зменшений: це не примітка під таблицею, це те, заради чого сюди дочитали
3Жирне - --text-primary, на пів тону темніше за абзац. Виділяється назва і число, а не речення
4Кадр .pd-img - aspect-ratio: 16/6. Ширину обирає колонка, тож коробка називає пропорцію, а не два числа. Те саме правило, що на квадратах картки товару (7.68), протилежний випадок
5Крок 32 між блоками - найбільший вертикальний ритм у продукті. Тут він доречний: кожен блок це окрема думка, а не пункт списку

Принцип 5 цілком: звичайні слова згори, глибина знизу. Склад, дозування і сертифікат вище на сторінці й у таблицях; тут - те саме людською мовою, для того, хто читає, а не звіряє.

Вигляд, який жив у скрипті
box.style.backgroundImage = 'url(' + src + ')'; box.style.backgroundSize = 'auto 84%'; box.style.backgroundPosition = 'center'; box.style.backgroundRepeat = 'no-repeat'; box.style.borderStyle = 'solid';

П'ять інлайн-властивостей на кожен із восьми кадрів. Дані з них - одна: яке фото. Решта чотири це вигляд коробки, і три з них повторювали те, що таблиця стилів уже казала за два рядки звідси.

Інлайн писавТаблиця стилів казалаЩо це було
borderStyle: solidborder: 1px solid var(--line-hair)повтор
backgroundPosition: centerbackground: ... center ...повтор
backgroundRepeat: no-repeatbackground: ... no-repeatповтор
backgroundSize: auto 84%background: ... center/contain ...розбіжність
backgroundImage: url(...)-дані

Четвертий рядок - той, заради якого це знахідка, а не прибирання. contain у файлі жодного разу не намалювався, і при цьому читався як правда: хто відкриє desc-block.css, побачить «вписати в коробку», а на екрані стоїть 84% висоти. Інлайн-стиль тим і поганий, що таблиця стилів його не бачить, а людина, яка читає таблицю стилів, не бачить інлайну.

Правило

Скрипт ставить дані, таблиця стилів ставить вигляд. «Яке фото» - дані. «Наскільки воно велике в коробці» - вигляд, і він мусить лежати там, де його шукатимуть.

84% - це власне поле рендера: продуктові знімки приходять зі студійним повітрям навколо, і заливка від краю до краю це повітря зрізала б. Підлога лишається --bg-page, білою, а не теплою поверхнею: у знімків свій м'який фон, і тепла заливка під ними читалась би як сіра коробка, домальована навколо товару.

заміряно на обох серверах, три екрани, три ширини: auto 84% · 50% 50% · no-repeat · solid - однаково до і після
Абзац, оголошений двічі
.pd-tx { line-height: var(--lh-airy) } /* структура */ .pdesc .pd-tx { font-size: 16; line-height: var(--lh-airy) } /* колір */ .pd-tx { font-size: 16; color: var(--text-body) } /* колір */

Середній рядок при (0,2,0) переважив обидва сусідні - і не сказав нічого нового. Його font-size дорівнює тому, що ставить рядок під ним; його line-height дорівнює тому, що ставить структура над ним. Два оголошення виграли, два оголошення померли, і жоден піксель від цього не залежав - але файл читався так, ніби текст опису стилюють у двох місцях.

Стилюють в одному. Знято; заміряно 16 елементів на двох екранах: 16px / 1.7 до і після.

Хто ще спирається на цю колонку
.sech:has(+ .pdesc) { max-width: 800px; margin-inline: auto }

Заголовок «Опис» бере мірку колонки, під якою стоїть. До 7.73 це правило звалось section[aria-label="Опис"] .sech - речення інтерфейсу в ролі селектора, - і його полагодили так: не питати, як секція називається, а спитати, що стоїть після заголовка. Тому .pdesc тут не просто клас: це якір для сусіда, і перейменувати його означає зрушити заголовок.

А .pd-block не оголошений ніде

Вісім екземплярів у розмітці, нуль правил у всій системі. Обгортка справді потрібна - саме вона є елементом флексу і саме між ними лягає крок 32, - але працює елемент, а не ім'я. Клас без жодного правила це або залишок, або гачок на майбутнє, і з коду не видно, що з двох. Записано в перейменування, крок 6, який за правилом іде після етапу 09.
Стани
СтанЩо робитьЧому так
спокійтекст, під ним кадр 16:6єдиний стан, який у блока є
до підстановки фотоу коробці слово «зображення», --text-mutedсірий прототип лишає рамку з підписом; у кольорі це видно частку секунди, поки не спрацював скрипт
вужче за 800колонка стискається до ширини сторінкиmax-width, а не width: обмеження зверху, а не розмір
опису ще немаєзамість абзаців - коробка .emptybox.mini усередині тієї самої колонкиу товару без опису нема чого читати, але є що сказати: перевірене вже стоїть нижче
наведеннянемаєтут нема на що натискати. Ані кадр, ані абзац нікуди не ведуть
фокуснемаєжодного контрола в блоці, і це правильно: опис читають, а не керують ним
Опис готуємо

Опис від виробника приходить із накладною, а не з товаром, і між «завели картку» та «отримали офіційний текст» проходить час. Досі в цей проміжок блок просто зникав - і зникав мовчки, разом із заголовком «Опис», тож сторінка виглядала так, ніби опису в цього товару не буває.

Опис

Опис готуємо
Склад, дозування і характеристики нижче - вони вже перевірені. Опис від виробника додамо, щойно отримаємо офіційний текст.
390 на product.html: 358 x 170.8, поле 24/16, рамка 1px #E9E7E2, тло #FAF9F7 · тут, у вужчій колонці стенда: 308 x 193.2. Нових оголошень у desc-block.css: 0
1Це атом, а не другий його примірник. .emptybox.mini з empty-state.css, без жодного модифікатора звідси. Коробка порожнього стану вже намальована один раз; компонент, який домалював би собі свою, розвів би два вигляди на одну ідею
2Чому .mini, а не .empty. .empty це пунктирна рамка з портретом ведмедя на цілий екран результатів. Тут сторінка не порожня: угорі галерея, ціна й кнопка, унизу склад і сертифікат. Ведмідь посеред сторінки товару перекричав би саме те, на що текст показує
3Чому .mini, а не .emptybox без нього. Коробка без .mini просить 46px поля, і це число не малюється в кольорі жодного разу: усі три кольорові коробки продукту - .mini. 40, 46 і 48 на одну ідею це відкрите рішення етапу 09 (empty-state.html), і не крок про опис товару має його закривати
4Коробка стоїть усередині .pdesc, а не замість неї. section-head.css:72 тримає заголовок «Опис» на мірці .sech:has(+ .pdesc) - прибрати колонку означає зрушити заголовок на всю ширину сторінки. Усередині колонки коробка отримує ті самі 800 і ту саму вісь безкоштовно
5Виходу немає, і це навмисно. Принцип 2 вимагає рівно одну головну дію на екран, а вона на сторінці товару вже є - «Додати в кошик». Кнопка в порожньому описі стала б другою головною дією за 200px від першої. Текст натомість показує вниз, де стоїть те, що справді перевірене
6Значка немає, і це замір, а не смак. .emptybox .ei має font-size: 0, а знак ставить uivIcons(), який читає одну мапу - UIV_EMOJI в design/_nav.js. doc і chat намальовані в icons.js і обидва пасували б, але рядка в тій мапі не має жоден: набраний тут емодзі або вийшов би сирим системним знаком серед знаків із набору, або, всередині .ei, не вийшов би взагалі

Принцип 1 у два речення. Перше знімає сумнів: склад і дозування на місці, перевірені, дивіться нижче. Друге називає причину й обіцянку без дати: «щойно отримаємо офіційний текст». Не вигадуємо опис самі і не вибачаємось - те саме антиправило, що в порожнього стану лістингу.

Правило і антиправило

Правило

Опис розповідає, а не перелічує. Склад і дозування вже стоять таблицею вище; тут те саме словами - для того, хто хоче зрозуміти, а не звірити. Один абзац - одна думка, і кадр поруч показує саме її.

Антиправило

Не роби з опису другий продажний блок. Ні знижки, ні кнопки, ні «залишилось мало» посеред тексту. Принцип 4: спокійно й упевнено. Купити пропонують угорі, тут - пояснюють.
Холостий контроль

Сторінка звіряє себе з файлом: 3 власні класи і 1 стан. Стан не додає класу - він названий у файлі й позичений з empty-state.css, тож у списку класів його немає і бути не мало б.

ПОВЕДІНКА НА ШИРИНІ - етап 10, крок 4

Від якого порогу: жодного. Блок опису плинний - це текст у колонці, яку задає його місце. Раунд молекул його не чіпав.
Токени

Прочитані з desc-block.css: 5 семантичних ролей і 6 примітивів.

Семантичні ролі (5)Примітиви (6)
--bg-page --line-hair --text-body --text-muted --text-primary--container-text --fs-16 --lh-airy --radius-12 --space-12 --space-32

Повз шкалу два числа: 1px рамки і 800px колонки. Друге - міра читабельного рядка, а не відступ, тож у шкалу відступів воно й не мало б лягти; але воно написане тут і ще раз у section-head.css, і два місця для одного числа - це той самий випадок, що вже закривали для інших значень. Кандидат на токен, рішення - етап 09.

A/B

Три проходи по 40 екранах на чотирьох ширинах: HEAD, HEAD ще раз і робоче дерево. Нульовий прохід 0, різниця 0, 215 452 елементи з кожного боку.

І тут нуль сам по собі нічого не доводить: перепис не заміряє background-size, background-position, background-repeat і border-style - тобто рівно ті чотири властивості, які цей крок переносив. Заміряно окремо, властивість за властивістю, на двох екранах і трьох ширинах, на обох серверах: однаково.

Немає в коді -> етап 09

Чого бракує

  • .pd-block без жодного правила - вісім екземплярів, нуль оголошень. Перейменування, крок 6
  • 800px у двох файлах - тут і в section-head.css. Кандидат на токен міри тексту
  • Кадр не має підпису - alt у фонового зображення не буває, і для читача з екрана чотири кадри опису мовчать
  • Довжина опису не обмежена - «читати більше» тут немає, на відміну від SEO-блока каталогу
  • Дві мертві мірки в атома, і файл не наш. Знайдено, поки будувався стан вище: без .ei згори й без .eact знизу .emptybox.mini .et тримає свої 8 згори, а .emptybox .es - свої 16 знизу, тож у коробки з полем 24 виходить 32 над заголовком і 40 під текстом. account-empty.html уже латає свою копію інлайном style="margin-top:0", і empty-state.html називає цей інлайн дефектом. Виправлення - :first-child / :last-child в empty-state.css, один раз на всі коробки без значка, а не окремо в кожному компоненті, який таку коробку вживає

Не домальовано наперед і не замовчано: етап 09 стартує з цього списку, зведеного в design/kit/docs/architecture.md.