Головна / Статті

CSS attr() у вигляді тексту: безпосереднє введення значень атрибутів HTML у стилі

Дізнайтеся, як функція CSS attr() перетворює атрибути даних на значення довжини, кольорів та часу, чому її альтернативні рішення не працюють, чому функція url() заблокована, та як сьогодні безпечно її використовувати.

Видавець: REACTAPP.TOP18 хв читання4056 слів

Джерела: CSS attr() Reads Your HTML Now

Уявіть собі панель прогресу, значення якої — 87 — вже міститься у маркапі як data-fill="87". До недавнього часу для встановлення цього числа у поле width потрібен був невеликий скрипт: читати значення з dataset.fill, додавати знак відсотка та записувати його назад у сам елемент, з якого воно походило. Значення виходило з документа лише для того, щоб одразу ж повернутися назад, що призводило до використання скрипта та додаткової обробки зображення.

Функція attr() усуває цю необхідність. Тепер вона приймає тип даних, тож стилівий лист може читати атрибут як довжину, колір, число чи ідентифікатор та використовувати його у будь-якій властивості, яка підтримує цей тип. У цьому посібнику розглядається синтаксис, чотири способи виконання пошуку, шаблони, які замінюють поширені скрипти, обмеження щодо безпеки URL та способи впровадження цієї функції поки що при неповній підтримці з боку браузерів.

Від генератора рядків до введеного значення

Класична функція attr() працює у всіх основних браузерах з приблизно 2015 року, але вона виконувала лише одну функцію: створювати рядок для властивості content, зазвичай у псевдоелементі.

/* the version you already know */
blockquote::after {
  content: " — " attr(cite);
}

Це зручно для виведення посилання чи адреси, але нічого більше. Використання старої функції attr() усередині властивості width призводило до відхилення всього оголошення, оскільки ця функція повертала лише рядки, а властивість width не потребує рядків.

У версії 5 документа CSS Values and Units змінюється цей підхід: ви повідомляєте браузеру, який тип значення містить атрибут. Як тільки движок розуміє, що йдеться про довжину, колір чи число, результат може використовуватися у будь-якій властивості, де дозволений цей тип, що на практиці означає майже всі властивості.

/* the version this article is about */
.bar   { width: attr(data-fill %, 0%); }
.chip  { background-color: attr(data-brand type(<color>), #888); }
.dial  { rotate: attr(data-deg deg, 0deg); }
.card  { view-transition-name: attr(id type(<custom-ident>), none); }

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

  • Це не спосіб видалити JavaScript з процесу стилізації. Використання style="--fill: 87%" безпосередньо в HTML ніколи не вимагало скрипту. Новизна полягає у тому, що тепер значення атрибута використовується у стилі, який раніше вимагав скрипту, а тепер — ні.
  • Це не переміщує логіку додатку до CSS. Ваш додаток все одно вирішує, що завдання виконано на 87 відсотків. Єдине зміна — хто читає це число з елемента: ваш код або таблиця стилів, яка все одно мала бути застосована.

Структура функції

Граматика цього коду поміщається в один рядок.

attr( <attr-name> <attr-type>? , <fallback-value>? )

Використовуйте attr(data-fill %, 0%). Він складається з трьох частин: назви атрибута, який потрібно прочитати, типу, за допомогою якого його інтерпретують, та значення за замовчуванням у разі, якщо пошук не дає корисних даних.

Тип можна вказати у трьох різних формах. Перша — це type(), який обгортає будь-який CSS-тип у дужки.

/* 1. type() — any CSS data type */
color:  attr(data-brand type(<color>), crimson);
width:  attr(data-w type(<length>), 0px);
scale:  attr(data-s type(<number>), 1);

Друга форма — це проста одиниця вимірювання, яка означає „атрибут містить звичайне число; до нього слід додати цю одиницю“. Третя форма — raw-string, яка також є значенням за замовчуванням, якщо тип не вказаний, та відтворює історичну поведінку.

/* 2. unit shorthand — the attribute holds a bare number */
width:           attr(data-w px);      /* data-w="10"    → 10px  */
rotate:          attr(data-deg deg);   /* data-deg="45"  → 45deg */
animation-delay: attr(data-i s);       /* data-i="2"     → 2s    */
width:           attr(data-fill %);    /* data-fill="87" → 87%   *//* 3. raw-string — the default, and the old behaviour */
content: attr(data-name raw-string, "stranger");
content: attr(data-name);   /* identical */

Скорочення для одиниці вимірювання очікує число без одиниць

attr(data-w px) означає «прочитати число у data-w та розглядати його як пікселі». Тому атрибут має бути у форматі data-w="10". Запис data-w="10px" не обробляється, оскільки одиниця вимірювання вказується у стилевому файлі, а не у маркапі. Якщо ви хочете, щоб HTML містив власну одиницю вимірювання (наприклад, тому що редактор може ввести 2rem або 10px), скористайтеся type(<length>) та збережіть повне значення.

Недійсний запасний варіант призводить до помилки раніше та по-іншому

Значення за замовчуванням обробляється разом із рештою оголошення ще до того, як браузер перевірить елемент. Якщо ви напишете attr(data-w px, banana), оголошення є недійсним під час обробки та повністю ігнорується: атрибут ніколи не читається, і замість нього застосовується будь-яке попереднє оголошення тієї самої властивості у правилі. Це зовсім інша проблема, ніж відсутність атрибута, яка виявляється лише значно пізніше під час обчислення значення. Якщо у вашій голові розділяти ці два випадки, налагодження стає набагато простішим.

Типи, які можна оголосити

У функції type() допускаються наступні типи, а також інформація про те, що має містити атрибут, та типові місця його використання.

  • <length>: значення на кшталт "12px" або "2rem" для властивостей width, padding чи inset.
  • <percentage>: "87%" — для параметрів width або translate.
  • <length-percentage>: один із попередніх варіантів — для будь-яких елементів, які потребують вказання розміру.
  • <number>: "4.5" — для параметрів opacity, scale або як вхідні дані для функції calc().
  • <integer>: "3" — для параметрів grid-column, z-index або order.
  • <color>: "#4fc3f7" або "tomato" — для параметрів color та background-color.
  • <angle>: "45deg" або "0.25turn" — для параметра rotate або кутів градієнта.
  • <time>: "300ms" — для параметрів animation-delay та transition-duration.
  • <resolution>: щільність у форматі "2dppx", яка використовується параметром image-resolution.
  • <custom-ident>: ідентифікатор у форматі "card-3", зручний для найменування елементів, таких як view-transition-name чи anchor-name.
  • <string>: CSS-рядок у лапках, який зазвичай використовується параметром content.
  • <transform-function>: значення у форматі "rotate(20deg)", яке застосовується до властивості transform.
  • <image> та <url>: присутні в граматиці, але фактично недоступні через причини, описані у розділі про безпеку нижче.
  • *: приймає все, і здебільшого корисний для виявлення функцій.
  • Числа потребують функції calc(), щоб стати розмірами

    <number> не має розміру. 4.5 сам по собі не може встановити ширину, тому майже завжди потрапляє всередину calc(). Найзручніший підхід — спочатку зберегти його у власності та виконати обчислення саме там.

    .stars {
      --r: attr(data-rate type(<number>), 0);
      width: calc(var(--r) * 20%);   /* 4.5 → 90% */
    }
    

    Проміжний параметр --r — це не просто формальність. Він дозволяє використовувати це значення у кількох оголошеннях, а оскільки користувацькі властивості успадковуються, саме таким чином значення потрапляє до нащадків елементів, що, як ви побачите, є єдиним способом поділитися атрибутом з дочірніми елементами. Якщо ви вже використовуєте користувацькі властивості для передачі даних між скриптами та стилями, стаття про користувацькі властивості у часі виконання розглядає інший аспект цього механізму.

    Як відбувається пошук: чотири результати, а не два

    Є спокуса припустити, що ця функція або працює, або правило ігнорується. Насправді існує чотири різних результати, і їх плутанина є найпоширенішою причиною несподіванок.

    • Атрибут відсутній. Якщо вказано альтернативний варіант, він використовується. Якщо ні, результатом є значення „guaranteed-invalid“, і декларація стає недійсною у момент обчислення значення (IACVT).
    • Атрибут існує, але є порожнім (data-x=""). При використанні типової функції attr() порожня стрічка не розпізнається як відповідний тип, тому застосовується альтернативний варіант. Однак при безтиповому пошуку це вважається успіхом, що призводить до отримання порожньої стрічки, і альтернативний варіант проігнорується.
    • Значення не піддається обробці як оголошений тип. Якщо є альтернативний варіант, він використовується; інакше — IACVT.
    • Значення піддається обробці. Воно отримується, і стиль оновлюється відразу після зміни атрибута.

    Що насправді означає „недійсно у момент обчислення значення“

    Під час парсингу виявляється звичайна синтаксична помилка. Браузер ігнорує це оголошення, і набуває чинності попереднє оголошення тієї самої властивості в тому ж правилі. Проблема IACVT виникає значно пізніше, коли каскад вже обрав переможне оголошення, тому немає чого можна було б використати як альтернативу. Властивість поводиться так, ніби її значення встановлено як unset: успадковані властивості беруть значення від батьківського елемента, а невспадковані — повертаються до свого початкового значення.

    .bar {
      width: 50%;                  /* cascade drops this: the next one parsed fine */
      width: attr(data-fill %);    /* attribute missing → IACVT → width: auto */
    }
    /* result: auto. NOT 50%. */
    

    Ось чому завжди надавати альтернативу — це не справа смаку. Без неї неправильно написана назва атрибута тихо призводить до використання значень auto, 0 або успадкованого кольору, і консоль залишається мовчазною.

    Чому функція attr() без вказання типу не може створити колір

    Значення за замовчуванням raw-string заслуговує особливої уваги. Припустимо, правило встановлює значення background-color з атрибута без вказання типу, і ви тестуєте його на елементах, які відрізняються лише цим атрибутом. Елемент без атрибута отримує значення за заміну, як і очікувалося. Кожен елемент, у якого є цей атрибут, відображається прозорим, включаючи той, що містить абсолютно коректну назву кольору.

    Пояснення полягає у тому, що функція attr(), яка використовується без вказання типу, підставляє буквальний текст атрибута як рядок CSS, а не оброблене значення CSS. Атрибут background-color не приймає рядки, тому підстановка провалюється на етапі обчислення значення. Альтернативний варіант не допомагає: він застосовується лише у разі відсутності атрибута чи помилки під час обробки за оголошеним типом, а в цьому правилі нічого не було оголошено. Пошук успішно повернув рядок; проте на наступному кроці виникла помилка через те, що потрібен був колір, а нічого не було для його обробки.

    /* data-c="red" — and the element still renders transparent */
    .swatch { background-color: attr(data-c, gold); }
    

    Висновок простий: щоразу, коли метою є властивість, яка не є content, необхідно оголосити її тип.

    Шаблони, які замінюють скрипт

    Багато завдань, які команди зазвичай виконують за допомогою кількох рядків JavaScript, тепер можна повністю реалізувати у таблиці стилів.

    Ширина з атрибута data

    У маркапі вказується звичайне число.

    <div class="bar" data-fill="87"></div>
    

    Шаблон стилів читає це значення за допомогою скорочення у відсотках, а якщо це не спрацює — використовує порожню смугу.

    .bar {
      height: 8px;
      border-radius: 99px;
      background: linear-gradient(90deg, #4fc3f7, #2dd4bf);
      width: attr(data-fill %, 0%);
    }
    

    Колір, обраний у CMS

    .chip { background-color: attr(data-brand type(<color>), #888); }
    

    Колір бренду, обраний редактором контенту, є даними, а не елементом дизайну. За допомогою функції attr() його можна безпосередньо використовувати у шаблоні стилів, не додаючи вбудовані стилі. Оскільки перевірка формату <color> відбувається у браузері, помилка редактора призводить лише до використання сірої замінної кольорової смуги, а не до пошкодженого CSS.

    Анімації списку з відстрочкою

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

    <li data-i="0">Inbox</li>
    <li data-i="1">Drafts</li>
    <li data-i="2">Sent</li>
    

    Кожен елемент отримує свій індекс у вигляді числа, а функція calc() перетворює його на значення затримки.

    li {
      --i: attr(data-i type(<number>), 0);
      animation: fade-in .45s both;
      animation-delay: calc(var(--i) * .09s);
    }
    

    Якщо атрибут вже містить повний проміжок часу, скорочення у форматі s дозволяє читати його безпосередньо.

    /* or, if the attribute already holds a duration */
    li { animation-delay: attr(data-delay s, 0s); }
    

    Використання параметра --i для вказівки індексу має додаткову перевагу: крок таймінгу стає єдиною CSS-константою. Змінивши .09s в одному місці, усі розташовані послідовно списки на сайті автоматично будуть дотримуватися нового ритму.

    Унікальне значення view-transition-name для кожної картки

    Ця схема дозволяє реалізувати те, що раніше було неможливим. Кожен елемент, який бере участь у переході між відображеннями, повинен мати своє унікальне значення view-transition-name; раніше це означало необхідність створення окремого правила для кожної картки або присвоєння імен зі скрипту. Тепер одне правило керує всіма картками.

    .card {
      view-transition-name: attr(id type(<custom-ident>), none);
      view-transition-class: card;
    }
    

    Зауважте, що тут використовується атрибут id, а не атрибут data-*. Функція attr() може читати будь-який атрибут елемента, включаючи id, href, title, colspan чи lang. Простір імен data-* — це місце, де HTML очікує розміщення користувацьких даних сторінки. Поєднання цього імені з view-transition-class дозволяє стилізувати переходи всіх карток за допомогою одного селектора, незважаючи на те, що кожна з них має унікальне ім’я.

    Корисним способом перевірки будь-якого з цих варіантів є тимчасове видалення вашого скриптового базового рішення та перевірка того, чи все ще залишається стилізація; якщо так, то роботу виконує attr().

    Псевдоелементи: випадок без альтернативного рішення

    Кожна з інших переваг, описаних у цьому посібнику, має альтернативу: ви завжди можете встановити власність безпосередньо у елементі. Псевдоелементи є іншими. element.style впливає на сам елемент, тоді як ::before чи ::after не є вузлами DOM, тож немає чого прикріплювати до них стилі безпосередньо. Попередні варіанти — це власність, успадкована від господаря елемента (що все одно вимагає стилізації господаря), або генерований файл стилів. На відміну від цього, атрибут господаря елемента може бути прочитаний безпосередньо з обох псевдоелементів.

    Ось метрика, яка має лише один атрибут як дані.

    <div class="meter" data-pct="72"></div>
    

    Етикетка використовує класичну функцію attr() у полі content, яка працює в усіх браузерах.

    .meter::before {
      content: attr(data-pct) "% complete";
    }
    

    Смуга використовує спеціальну форму для встановлення своєї ширини на основі того самого атрибута.

    .meter::after {
      content: "";
      display: block;
      height: 10px;
      width: attr(data-pct %, 0%);
      background: linear-gradient(90deg, #fbbf24, #f472b6);
    }
    

    Одне атрибут живить два псевдоелементи, і жоден з них не потребує додаткового дочірнього елемента. Позначки, кільця прогресу, текст підказок, порядкові префікси, суфікси одиниць вимірювання та етикетки даних графіка — усе це має таку структуру: псевдоелемент, який потребує числа, вже міститься у хост-елементі. Раніше, перед використанням функції attr(), це число доводилося вводити двічі — один раз як атрибут для тексту та ще раз як власність для геометрії, і ці два варіанти могли відрізнятися. Тепер його достатньо ввести лише один раз.

    funcія attr() читає лише елемент, який стилізується

    Ця функція читає атрибути елемента, до якого застосовується правило. Вона не перевіряє предків чи братські елементи, і не існує еквівалента функції closest(). Через наявність резервного варіанту ця помилка проявляється без звукових сигналів, тому майже кожен робить її принаймні один раз.

    Розгляньмо розділ, який визначає кольор акценту для свого вмісту.

    <section class="theme" data-accent="#4fc3f7">
      <h2>Title</h2>
    </section>
    

    Читання атрибута з заголовка не приносить жодної користі, оскільки у заголовка його немає.

    /* WRONG — this reads the h2, which has no data-accent */
    .theme h2 { color: attr(data-accent type(<color>), #888); }
    /* every heading is #888, forever, with no error */
    

    Рішення полягає у тому, щоб прочитати атрибут один раз на елементі, який його має, та передати значення через власність.

    /* RIGHT — read it once on the element that has it, then inherit */
    .theme    { --accent: attr(data-accent type(<color>), #888); }
    .theme h2 { color: var(--accent); }
    .theme a  { border-bottom: 2px solid var(--accent); }
    

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

    Чому URL заборонені

    Кожне значення, створене за допомогою attr(), позначається як attr()-tainted, і таке значення ніколи не може використовуватися для створення URL, незалежно від шляху. Обидві ці декларації не мають жодного ефекту:

    span[data-icon] { background-image: url(attr(data-icon)); }
    span[data-icon] { background: image-set(attr(data-icon)); }
    

    Забруднення передається разом із значенням. Його направлення через власність, обгортання його у функції src() або image(), чи розміщення всередині інших функцій на будь-якій глибині залишає слід на місці. Де б воно не опинилося у контексті URL, його оголошення стає недійсним під час обчислення значення.

    Модель загроз пояснює це правило. Значення атрибутів часто залежать від користувачів: імена для відображення, ідентифікатори CMS, назви коментарів. Якщо стилевий файл може перетворити таке значення на мережевий запит, будь-хто, хто може записувати дані у це поле, зможе змусити браузер кожного відвідувача завантажити адресу на свій вибір разом із тим, що браузер зазвичай додає до таких запитів. Саме вирішення цієї проблеми у специфікації дозволило виробникам браузерів домовитися про впровадження цієї функції. Оголошення WebKit на Interop 2026 чітко це підкреслює: оскільки питання безпеки вже регулюються специфікацією, усі движки заявили про готовність до впровадження цієї можливості та її взаємодії між собою.

    Пам’ятайте про обмеження цього захисту. Будь-який вміст атрибута є доступним для читання кожним скриптом на сторінці, видимим у режимі перегляду коду та передається в HTML-пакеті. Заборона URL закриває один шлях витоку даних; це не робить атрибути приватними. Ніколи не зберігайте там секретну інформацію.

    Виявлення підтримки та поступове впровадження

    Безпечний підхід — це простий базовий варіант, який розуміє кожен браузер, а версія з введеними даними додається як додатковий рівень для движків, що її підтримують. Почніть з базового варіанту, який тут реалізується за допомогою вбудованої користувацької властивості.

    .bar {
      width: var(--fill, 0%);          /* baseline, everyone */
    }
    

    Потім нехай браузери, які підтримують це, перейдуть на використання атрибута.

    @supports (width: attr(x %)) {
      .bar {
        width: attr(data-fill %, 0%);  /* modern browsers take over */
      }
    }
    

    Той самий тест доступний під час виконання, якщо ваш код потребує розгалуження.

    // the same answer at runtime, if you need to branch in code
    if (CSS.supports("width", "attr(x %)")) {
      // typed attr() is available
    }
    

    Тестування з використанням реальної властивості

    Будьте обережні з фрагментами для виявлення, які використовують ім’я властивості-замінника, наприклад @supports (x: attr(x type(*))), що зустрічається у документації для посилань. Жодної CSS-властивості під назвою x не існує, і кожен браузер повертає значення false, коли запит на підтримку стосується властивості, якої він не знає, тому тест провалюється навіть у браузерах, де ця функція працює. Використовуйте існуючу властивість. Запит @supports (width: attr(x %)) є надійним: width — це справжня властивість, а attr(x %) може бути оброблений лише движками, які реалізують скорочення для одиниць вимірювання. Варто перевірити поточну документацію MDN щодо функції attr(), адже приклади в документації іноді коригуються.

    Використання каскаду замість @supports

    Коротша версія омине блок @supports та дозволить каскаду прийняти рішення.

    .bar {
      width: var(--fill, 0%);        /* everyone */
      width: attr(data-fill %, 0%);  /* supporting browsers override */
    }
    

    Браузер, який не може розпарсити attr() всередині width, видаляє це оголошення під час парсингу, тож застосовується попередній рядок. Така поведінка випливає з того, як каскадування обробляє недійсні оголошення. Проте формат @supports чітко визначає намір та потребує лише кількох додаткових рядків, тому варто його використовувати, якщо ви хочете, щоб поведінка була зрозумілою майбутнім читачам, а також перевіряти коротший формат у браузері, який його не підтримує, перш ніж покладатися на нього.

    У обох варіантах необхідно зберегти альтернативний варіант всередині самого attr(). У підтримуючому браузері відсутній атрибут не переходить на оголошення var(), розташоване вище; оголошення attr() вже перемогло у каскадуванні, тож стає IACVT, і значення ширини визначається як auto.

    Підтримка браузерами на момент написання

    Підтримка швидко змінюється, тому сприймайте ці дані як моментальний знімок та підтверджуйте їх на сайті Can I use перед тим, як покладатися на них. Станом на серпень 2026 року приблизно 70 відсотків користувачів у всьому світі використовували браузери з підтримкою функції attr():

    • Chrome 133 та новіші версії: підтримується; це перші версії, які її додали (див. оголошення Chrome for Developers).
    • Edge 133 та новіші версії: підтримується, оскільки вони базуються на Chromium.
    • Firefox 155 та новіші версії: підтримується; присутня, але за замовчуванням вимкнена у версіях 152–154.
    • Samsung Internet 29 та новіші версії: підтримується.
    • Safari на десктопі: ще не випущена; доступна лише у режимі Technology Preview.
    • Safari на iOS: ще не випущена, і оскільки кожен браузер iOS використовує WebKit, це стосується всіх браузерів iOS.

    Старий метод attr(), який приймає лише рядок, усередині content — це окрема справа. Він був широко доступний у версії Baseline протягом десяти років, ще з найранніших версій усіх основних двигунів. Якщо вам потрібно лише content: attr(data-label), ви можете використовувати його без жодних з вищезазначених заходів обережності.

    Interop 2026 включає функцію attr() до своїх пріоритетних напрямків. Interop — це щорічна співпраця, під час якої Apple, Google, Microsoft та Mozilla разом із Igalia та Bocoup вибирають функції, яких бракує або які не працюють у принаймні одному движку, та беруть на себе зобов’язання покращити їх протягом року. Прогрес відстежується на публічному панелі керування на основі спільних тестів Web Platform Tests. Це найсильніший публічний сигнал того, що розробляється підтримка Safari, але це лише зобов’язання, а не дата випуску. Очікуйте альтернативний рішення до кінця 2026 року. Щоб дізнатися більше про безпечний підхід до випуску нового CSS, дивіться безпечний випуск сучасного CSS.

    Вибір між attr() та JavaScript

    Жоден із інструментів не є кращим у всіх випадках. Наведений нижче розбір є практичним посібником.

    Використовуйте attr(), коли:

    • Маркап вже містить значення. Його перенесення до скрипту лише для того, щоб знову встановити його на тому самому елементі, нічого не дає.
    • Воно має бути безпосередньо у першому фреймі. Атрибут існує відразу після створення елемента парсером, тоді як скрипт виконується пізніше та може спричинити видиму корекцію.
    • Псевдоелемент потребує значення. Вбудовані стилі, встановлені через element.style, не мають можливості впливати на ::before чи ::after.
    • У вас діє сувора політика безпеки контенту. Вбудовані стилі вимагають параметра unsafe-inline або значення nonce; атрибути типу data не вимагають нічого з цього.
  • Елементи додаються динамічно. Новостворені вузли отримують свої стилі з уже існуючих правил; немає потреби щось запускати знову, і не потрібен MutationObserver для стеження за деревом.
  • Ви хочете мати єдине джерело істини. Підхід з використанням скриптів часто зберігає значення як у атрибуті, так і в вбудованому стилі, і ці два варіанти можуть відрізнятися.
  • Ви хочете, щоб презентація залишалась у CSS, була видимою для каскадних правил, запитів до медіа та контейнерів, а також у інспекторі стилів браузера.
  • Використовуйте JavaScript у таких випадках:

    • Значення не має підстав існувати в DOM. Значення, отримане від ResizeObserver або обробника прокрутки, не слід спочатку перетворювати на атрибут.
    • Він оновлює кожен кадр анімації. Виклик el.style.setProperty('--x', v) є більш прямим та уникає необхідності вказування атрибута.
    • Дані є об’ємними, вкладеними чи конфіденційними. Будь-який вміст атрибута є публічно видимою рядком.
    • Вам потрібен Safari сьогодні, і значення має важливість. Полоска прогресу, яка застрягла на нулі в одному браузері, є дефектом, а не гарним запасним варіантом.

    У першому списку помітно відсутня тема продуктивності. Встановлення одного вбудованого стилю ніколи не було проблемою. Ви отримуєте краще розміщення значення та кращу видимість його змісту, а не швидкість.

    Чек-лист небезпек

    • Завжди передбачайте запасний варіант. Відсутнє або неперетворюване значення без запасного варіанту призводить до IACVT та властивості unset, а не до попередньої декларації.
    • Порожній атрибут — це не відсутній атрибут. Якщо атрибут не заданий типу, data-x="" повертає порожній рядок, і механізм запасного варіанту ніколи не активується.
    • Відсутній тип означає буквальний текст. background-color: attr(data-c, gold) з параметром data-c="red" нічого не відображає; потрібно вказати тип.
    • Немає ні url(), ні image-set(). Це навмисне обмеження, яке зберігається навіть після використання користувацьких властивостей.
    • Читається лише елемент, який відповідає умовам. Для предків значення потрібно зберігати у користувацькій властивості, щоб воно успадковувалося.
    • Для скорочень одиниць вимірювання потрібні просто числа. Використовуйте data-w="10", а не data-w="10px".
    • Недійсний запасний варіант призводить до скасування оголошення під час обробки, що є ранньою та іншою проблемою, ніж відсутній атрибут.
    • <number> сам по собі не може визначати розмір чого-небудь. Збережіть його та помножте у функції calc().
    • Атрибути є публічними. Не зберігайте в них конфіденційну інформацію.
    • Перевіряйте функціонал на реальному елементі, наприклад, за допомогою @supports (width: attr(x %)).
    • На момент написання Safari ще не випустив цю функцію, тому тримайте базовий варіант для всього необхідного.

    Підсумок

    Функція attr() передбачає невелику зміну синтаксису, яка має чіткий вплив на архітектуру: значення, які вже існують у HTML, більше не потребують скриптів для того, щоб стати стилями. Ця функція сприяє точності. Вказуйте тип, завжди задавайте запасний варіант, зчитуйте атрибут з елемента, який його містить, та передавайте його через власні властивості, приймаючи те, що URL-адреси залишаються недоступними. Поєднуйте кожне суттєве використання з базовим варіантом до моменту випуску Safari, і така схема може бути впроваджена в експлуатацію вже сьогодні, причому стилевий лист автоматично буде виконувати свою роль у міру поширення підтримки. Формальне визначення міститься у проєкті CSS Values and Units Level 5, якщо вам потрібні точні правила парсингу.