CSS attr() у формате тексту: прымэнне значэнняя атрыбута HTML безпосередна ў стылі
Дазвольце даклэ научыцца, як функцыя CSS attr() ператварае атрыбуты дадзеных у дужынкі, кольоры і часы, чаму не функцыонуюць ўсі альтэрнатыўныя варыянты, чаму функцыя url() заблокавана, і як можна сьогодні безпечна ўжываць яе.
Крыніцы: 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 або спадчынную расу, і консоль застаецца мовчазной.
Чаму funкцыя 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 en аднам месцы, усі розташаваны ў ряд лісты на сайце будуць следаваць новам рытму.
Унікальны 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() выканаў сваю роботу.
Псевдо-элементы: случай без альтернатывы
Кожна з іншых пераваг, практыкуемых у гідзе, мае альтэрнатыўу: вы завжды можете задаць спецыяльную власнасць у формате inline. Псевдо-элементы ж адрозніяюць. element.style нарабатывае на самым элементе, а ::before чыста ::after не ўтвараюць вузлаў DOM, таму няма чаго прыкрепіць у формате inline-стайла. Ранейшыя варыянты былі спецыяльнаяю власнасцю, якая успадковвалася ад хоста (што все рава вымагае стайлізавання хоста яким-небудзь спосабам), чыста створанай шаблонай стаяла. Атрыбут на хосте, напроты, можа быць прачытаны безпосередна з псевдо-элементаў.
Ёсць метрык, якой єдынай інформацыяй являецца адзін атрыбут.
<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ția 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, декларацыя становіцца нэвалідной у момент вычыслення значэння.
Модель абяранняяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяяя
Пам’ятайце працэўныя межы такой захоўнай меры. Усё, што знаходзіцца ў атрыбуте, можа быть прачытана кожным скраптом на сторонце, будзе видна ў режыме view-source і будзе передана ў 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 для разработчыкаў).
- 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 на аснове безпечных стандартаў, перайдзіце на shipping modern CSS safely.
Выбір между attr() і JavaScript
Ні адна з эйхых тэчак не ўсюды є кращай. Наведзены нижэй падзел являецца практычным кераваннем.
Выбірайце attr(), калі:
- Маркап вже мае неабяжлівую значэнне. Яго перадача ў скрыпт толькі для прабыць зноў яго задаць на там самым вузле нічога не дае.
- Яго трэба разместіць пры самай першай рамцы. Атрыбут існуе ў той момент, калі парсер стварае элемент, тады як скрыпт запускаецца пазней і можа спаказваць візуальныя змены.
- Псевдо-элемент патрэбуе значэнне. Інлайн-стылі, заданыя через
element.style, не магуць прабіць змяніць::beforeабо::after. - У вас дыяўча Палітыка безпекі кантэнту. Інлайн-стылі выклекуе
unsafe-inlineабо nonce; атрыбуты data не выклекуюць нічога з гэтага.
MutationObserver, які бы стежыў за дрэвам.Застаўцеся з 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, якщо вам патрэбны точныя правіла парсінгу.