Що таке псевдоелемент :: content / :: і як він працює?


74

Це неможливо для Google, оскільки в кожній статті, де йдеться про :beforeі :afterпсевдоелементи, використовується слово "вміст".

Я чув про це в цій статті CSS-Tricks, пояснюючи, як реалізувати повзунок зображення як приклад використання для веб-компонентів. Приклад коду, який він відображається всередині, є таким:

CSS

#slides ::content img {
   width: 25%;
   float: left;
}

HTML

<template>
  ...
  <div class="inner">
    <content select="img"></content>
  </div>
</template>

Здається, йдеться про цей <content>тег, який використовується, щоб дозволити користувачеві включати веб-компоненти, але я хотів би зрозуміти це глибше.

РЕДАГУВАТИ:

Прочитавши далі, у вищезазначеній статті я виявив посилання на авторську таблицю "Shadow DOM CSS", що містить уривок, який пояснює, що таке ::contentпсевдоелемент:

Вибирає розподілені вузли всередині елемента. Потрібно поєднати з polyfill-next-selector для браузерів, які не підтримують власний селектор.

::content h1 {
    color: red;
}

Джерело: http://robdodson.me/blog/2014/04/10/shadow-dom-css-cheat-sheet/

Це корисно, але я все одно вважаю, що вся справа досить непрозора. Будь-яка додаткова інформація?


5
Spec може запропонувати додаткові відомості.
Paulie_D

1
@Paulie_D щойно побачив шпаргалку (додав посилання, про яке йдеться вище) - дякую! але все ще вважаючи всю концепцію незрозумілою. що таке розподілені вузли?
Джон

4
Більше читання - ТУТ
Paulie_D

2
::contentбуло перейменовано на::slotted
Oriol

Дякую Оріол. @jon Я оновив свою відповідь, щоб відобразити це. Після того, як браузери перекласти підтримку slotі slottedя заміню згадки contentі ::contentта , можливо , оновити питання, а так , що він залишається корисним для читачів майбутніх!
TylerH

Відповіді:


109

::contentПсевдо-елемент замінюється в майбутніх реалізаціях веб - компоненти / Shadow DOM з ::slottedпсевдо-елемента. Аналогічно, елемент, на який націлений цей псевдоелемент, змінився з > <contentна <slot> в останній версії специфікації Shadow DOM . Ви можете побачити відповідне обговорення цієї зміни тут .

В даний час браузери все ще підтримують <content>і ::content.


Оригінальна відповідь:


Короткий зміст:

::contentце, по суті, спосіб копати глибше і стилізувати нащадків ShadowHost, які зазвичай недоступні для стилізації, оскільки ваш CSS не знає, шукати фрагмент ShadowDOM без ::content.


Ця відповідь передбачає, що ви хоча б дещо знайомі з <template>елементом та веб-компонентами , зокрема з ShadowDOM , який має справу з ShadowTrees та їх двома основними елементами, ShadowHostта ShadowRoot.

Примітка. На момент написання статті веб-компоненти підтримують менше 50% підтримки (навіть із префіксом, підтримка за замовчуванням) у п’яти основних браузерах. Хоча всі сучасні браузери підтримують <template>, лише останні версії Chrome та Opera повністю підтримують ShadowDOM; з Firefox, що підтримує його частини, після того, як ви перемкнете необхідну функцію в about:config( dom.webcomponents.enabled) на true .

Мета використання ShadowDOMаналогічна поділу концерну MVC . Тобто ми хочемо відокремити наш вміст від нашої презентації та дозволити вкладені шаблони в наш код, щоб допомогти зробити його більш керованим. У нас це вже є на різних мовах програмування, але це деякий час залишається проблемою в HTML та CSS. Крім того, можуть виникати конфлікти з іменами класів при стилюванні елементів у веб-програмах.

Зазвичай ми взаємодіємо з LightDOM(своєрідною «Світлою Царством»), але іноді було б корисно скористатися перевагами інкапсуляції. Перехід до такого роду "Тіньової сфери" (частина веб-компонентів) - це новий метод запобігання згаданим вище проблемам, дозволяючи інкапсуляцію . Будь-які стилі, застосовані до розмітки у вас ShadowTree, не застосовуватимуться до розмітки за межами вашого ShadowTree, навіть якщо використовуються однакові класи та селектори.

Коли у ShadowTree(яке живе в ShadowDOM) є дерево з LightDOMрозподіленого всередині нього, та / або коли ShadowTreeвізуалізується, браузер перетворює результат у те, що називається складеним деревом .

Коли браузер надає ваш код, вміст розповсюджується та вставляється в інших місцях, крім тих, де він був фізично набраний. Цей розподілений результат - це те, що ви бачите (і те, що бачить браузер), і називається composed tree. Насправді вміст спочатку не вводиться в тому порядку, в якому він зараз з'являється, але ви цього не знаєте, як і браузер. Це поділ між "кінцевим результатом" та "оригінальним кодом", якщо хочете, є однією з головних переваг інкапсуляції.

Веб-компоненти та майбутнє CSS - це чудове 40-хвилинне відео про Веб-компоненти та, зокрема, про ShadowDOM, на яке мені вказав ZachSaucier .


Спеціально для вашого запитання ::contentпсевдоелемент застосовується до так званих розподілених вузлів . Розподілений вузол - це ще один термін для того, що ви поміщаєте в <content></content>теги. Вміст розподіляється з місця в оригінальній розмітці туди, де ви розмістили свої <content>теги в шаблоні.

Отже, коли вам потрібна конкретність у CSS, один із способів, як ви можете обробляти селектори, - це перейти до батьківського елемента та додати це як частину селектора. Приклад: якщо.container {} недостатньо конкретно, ви можете використовувати div .container {}або .main .container {}для того, щоб ваш селектор працював.

Думаючи про сенс ShadowDOM, який стосується масштабування та інкапсуляції, ви повинні усвідомити, що це нове ShadowTree, яке ви створили, є абсолютно новим (дискретним) фрагментом DOM. Він не в тому самому «Світлому царстві», як решта вашого вмісту; це в "Тіньовому царстві". Отже, як CSS знає, щоб націлити цю "Тіньову сферу"? Використовуючи ::contentпсевдоелемент!

::contentСелектор псевдо-елемент виступає в якості батьківського елемента розподілених вузлів.

HTML5Rocks має чудову послідовність підручників тут , тут і тут, які охоплюють більше інформації та дають кілька чудових прикладів (обов’язково відвідуйте Chrome або Opera, поки більше браузерів не підтримають ці функції).

Наприклад, див. Цю змінену та вдосконалену (за Лео ) версію коду з HTML5Rocks:

var div = document.querySelector('div');
var root = div.createShadowRoot();
var template = document.querySelector('template');

root.appendChild(template.content);
<template>
  <style>
    h3 { color: red; }
    content[select="h3"]::content > h3 { color: green; }
    ::content section p { text-decoration: underline; }
  </style>
  <h3>Shadow DOM</h3>
  <content select="h3"></content>
  <content select="section"></content>
</template>

<div>
  <h3>Light DOM</h3>
  <section>
    <div>I'm not underlined</div>
    <p>I'm underlined in Shadow DOM!</p>
  </section>
</div>

Також доступно на JSFiddle (не забудьте відвідати у браузері на базі WebKit, як-от Chrome або Opera)

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

Це може здатися непотрібним у порівнянні із звичайним використанням селектора CSS (наприклад, чому б просто не використовувати section p {}?), Поки ви не пам'ятаєте, що при обведенні a ShadowTreeви не можете нормально вибирати нащадків hostелементів (якими є розподілені вузли), оскільки вони знаходяться в "Тіньове царство", про яке я згадував раніше.


11
Це феноменальна відповідь. Щиро дякую, що знайшли час написати це!
Джон

1
@jon Ласкаво просимо! Я рада, що Ви знайшли це корисним. Також є третій підручник з HTML5Rocks, якщо ви все ще шукаєте інформацію.
TylerH

2
Новий рядок, уникнути зворотною косою рисою, не рекомендується, оскільки це не ECMAScript
Хуан Мендес,

4
@JuanMendes З того, що я щойно прочитав, "\ після нового рядка не є послідовністю екранування символів, а LineContinuation. Новий рядок не стає частиною рядка. Це просто спосіб рядок над кількома рядками (для полегшення редагування коду, наприклад) [..] " Джерело . Тож це, мабуть, зовсім не порятунок.
TylerH

1
Just FYI: для подальшого читання про веб-компоненти Ви можете відвідати слайд-шоу ("Майбутнє під назвою веб-компоненти"), яке презентував на Front Trends 2014 Зенон Роча (член Експертної програми Google Developers) - vimeo.com/97308701
Міхал Кутра

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.