Свойства узлов: тип, тег и содержимое
Теперь давайте более внимательно взглянем на DOM-узлы.
В этой главе мы подробнее разберём, что они собой представляют и изучим их основные свойства.
Классы DOM-узлов
Каждый DOM-узел принадлежит соответствующему встроенному классу.
Корнем иерархии является EventTarget, от него наследует Node и остальные DOM-узлы.
На рисунке ниже изображены основные классы:
Существуют следующие классы:
- EventTarget – это корневой «абстрактный» класс для всего. Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события», о которых мы поговорим позже.
- Node – также является «абстрактным» классом, и служит основой для DOM-узлов. Он обеспечивает базовую функциональность: parentNode , nextSibling , childNodes и т.д. (это геттеры). Объекты класса Node никогда не создаются. Но есть определённые классы узлов, которые наследуются от него (и следовательно наследуют функционал Node ).
- Document, по историческим причинам часто наследуется HTMLDocument (хотя последняя спецификация этого не навязывает) – это документ в целом. Глобальный объект document принадлежит именно к этому классу. Он служит точкой входа в DOM.
- CharacterData – «абстрактный» класс. Вот, кем он наследуется:
- Text – класс, соответствующий тексту внутри элементов. Например, Hello в
Hello
.
- Comment – класс для комментариев. Они не отображаются, но каждый комментарий становится членом DOM.
- HTMLInputElement – класс для тега ,
- HTMLBodyElement – класс для тега ,
- HTMLAnchorElement – класс для тега ,
- …и т.д.
Также существует множество других тегов со своими собственными классами, которые могут иметь определенные свойства и методы, в то время как некоторые элементы, такие как , и , не имеют каких-либо определенных свойств, поэтому они являются экземплярами класса HTMLElement .
Таким образом, полный набор свойств и методов данного узла является результатом цепочки наследования.
Рассмотрим DOM-объект для тега . Он принадлежит классу HTMLInputElement.
Он получает свойства и методы из (в порядке наследования):
- HTMLInputElement – этот класс предоставляет специфичные для элементов формы свойства,
- HTMLElement – предоставляет общие для HTML-элементов методы (и геттеры/сеттеры),
- Element – предоставляет типовые методы элемента,
- Node – предоставляет общие свойства DOM-узлов,
- EventTarget – обеспечивает поддержку событий (поговорим о них дальше),
- …и, наконец, он наследует от Object , поэтому доступны также методы «обычного объекта», такие как hasOwnProperty .
Для того, чтобы узнать имя класса DOM-узла, вспомним, что обычно у объекта есть свойство constructor . Оно ссылается на конструктор класса, и в свойстве constructor.name содержится его имя:
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-pseudo-5] ::text / ::text-node pseudoelement #2208
[css-pseudo-5] ::text / ::text-node pseudoelement #2208
Comments
Please add ::text or ::text-node selector to select all text nodes inside any element
for example for#text1: Here is text #text2: Here also is text #text3: Here is second text in the paragraph
the p::text will select #text1 and #text3 and the pseudoelement can be styled like ::after and ::before (without need to set «content»).
The text was updated successfully, but these errors were encountered:
I’m definitely supportive of the idea in general.
A more detailed proposal with examples would probably be helpful in gaining more supporters, so if you’re already working on something @js-choi, please don’t stop just because this has now been formally raised as a working group issues.
- An anonymous block is different from a text node, since it can include inline elements. (In your code snippet, the text nodes that are direct children of the body would be «This is the» and «block in this example.») If there are use-cases for both, then maybe there needs to be more than one selector.
- Woule a pseudoelement selector only select direct-child text nodes for the element it is attached to, or any descendent text nodes?
- Whitespace-only text nodes are treated differently than content nodes in CSS layout, so would probably need to be distinguished.
Which are all probably good prompts for a WICG discussion if you want to start one.
- In my opinion ::text should select only direct childs. we can write in my example:
p::text, p ::text /* note a space before ::*/
to select all text nodes. - Yes, whitespace nodes should be treated in other manner.
It’s unclear about what most of the CSS properties would mean on a text-node, though, right? Specially non-inheriting ones.
In my opinion all styles including absolute positioning. But ::text::before forbidden.
What does an absolutely positioned text-node mean? Can you set display: block on a text-node? What about display: none ? What happens to text layout when you combine stuff using display: contents and such?
There’s two ways to go about this. One is to style the text node itself — only a subset of the CSS properties would apply, those that work on text. (More or less just the properties that are inherited, but there are some inherited properties that wouldn’t apply.) We’d have to define the precedence of this vs ::first-line and ::first-letter.
The second is to create an anonymous box around the text node and style that. In this case all of CSS applies. There is a minor problem here, tho — one of the use-cases for this is to solve issue 2 in the Scoping spec, and it’s not totally clear where in the flat tree the anonymous box would be.
@tabatkins What about selecting anonymous inline blocks? They’re not exactly the same as text nodes (especially regarding positioning), but they overlap quite a bit. My impression had been that those are already being generated by current agents and thus would not necessitate creating new boxes.
It’s unclear about what most of the CSS properties would mean on a text-node, though, right? Specially non-inheriting ones.
Works it like ::after and ::before.
will be shown identically like:
I think it is the easiest solution.
The text is removed and not shown.
Need clarification and any idea. It can be by exception treated as display:inline
The second is to create an anonymous box.
Yes, in my opinion the anonymous inline box will be the solution. Only exception to styles that cannot be applied like display:contents. Please note, if the element
in my example will be styled display:flex; the text nodes are switched to show like display:block .I have desired something like this several times when I have
Foo:and I want to vertically center the text with the textarea via vertical-align: middle , but there is no way to select the text.
Always wrapping text runs inside new boxes may be a breaking change, e.g. boxes inside a flex container become flex items, so this would prevent sequences of text runs to be wrapped inside a single anonymous flex item. CSS Flexbox could discriminate boxes generated by ::text from all the other ones, but this would be confusing and inconsistent.
It has also been suggested to inject the styles into anonymous boxes, but I think this is a bad idea because the cascade is supposed to happen in the element tree, and I prefer to avoid another fiasco like ::first-line .
I think what makes more sense would be:
- Text nodes (or sequences of text nodes?) in the DOM tree are wrapped inside a ::text pseudo-element in the CSS element tree.
- These ::text pseudo-elements must act as if they were assigned display: contents via a rule in the UA origin. Therefore, they do not generate any boxes and are treated as if they had been replaced with their children, which would be the current behavior. (There is precedence for this)
- This must be possible to override via display , so they do generate boxes if desired. But maybe mark this at-risk.
What is formal initial display value for ::after if the display, float and position are not defined?
BTW ::first-letter is greater fiasco than ::first-line
@Nadya678 ::before and ::after have the initial display: inline by default. But they also have content: none , which behaves like display: none .
OK. Thus here one exception: ::text — default display:contents .
I wasn’t aware of this ticket existing when I wrote this: #2406 (comment)
The basic take-away is that I don’t think a text node selector should be a pseudo element prefixed with colon(s) — that creates all kind of problems with specificity imho.
Instead it should be like an invisible p-tag with slightly less specificity than tags that auto opens on text and auto closes before any new block context / when the parent element closes.
I believe some of the above thinking too tightly tied to an artifact in the DOM (that never results from parsing) which is the possibility of having empty or adjacent text nodes. Let’s have CSS, if in a DOM-based implementation of the host language, pretend that document.normalize() was performed before styling. (And do something sensible for APIs using CSS selectors.)
@ByteEater-pl It could be tied to the concept of text run:
each contiguous sequence of sibling text nodes generates a text run [. ]. If the sequence contains no text, however, it does not generate a text run.
A pseudo element like ::text would have its benefits, but I’m still trying to figure out how to use it in the following use case:
p class pl-s">message"> Hi there span class pl-s">emoji-native" id pl-s">1">😋span> this is cool! span class pl-s">emoji-native" id pl-s">2">😍span> span class pl-s">emoji-native" id pl-s">3">😍span> p>
.emoji-native < margin: 0 3px; > .emoji-native + .emoji-native < margin-left: 0px; >
Basically in this example I want to consider ::text as a node between the two .emoji-native nodes when using the + operator, but it turns out it simply ignores it and adds that CSS on both ID 2 and 3 .
To be honest I don’t see a syntax that would make this work, this feels out of context. I would vouch though for a new kind of element that would represent displaced text written directly into the source code, or even a simple «invisible» HTML tag that represents all texts that are siblings to actual nodes.
@mauriciogior No, adding ::text shouldn’t break existing combinators or selectors, they would continue to skip text nodes
p class pl-s">message"> Hi there span class pl-s">emoji-native" id pl-s">1"> :nth-child(1) --> 😋 :nth-child(1)::text --> span> this is cool! span class pl-s">emoji-native" id pl-s">2"> :nth-child(2) --> 😍 :nth-child(2)::text --> span> span class pl-s">emoji-native" id pl-s">3"> :nth-child(3) --> 😍 :nth-child(3)::text --> span> p>
If what you want is selecting a .emoji-native whose previous sibling node (including text) is a .emoji-native element, then I don’t think that’s covered by this feature. You would need a new kind of combinator.
This selector would have been useful to me when targeting slotted text nodes, created either from implicit elements, or created from programatic, manual slot assignments. The CSS ::slotted(*) selector does not currently select text nodes.
I would also like to point out some prior art. At the time of this writing, other fully or partially shipping CSS text selectors or text-capable selectors include ::first-letter , ::first-line , ::selection , ::target-text , ::spelling-error , ::grammar-error , ::before , and ::after .
As a related aside, ::slotted(*)::before and ::slotted(*)::after can be used to target generated, slotted ‘before’ and ‘after’ text content. I am a little confused as to why the ::before or ::after selector comes after the ::slotted selector rather than inside of it. I could imagine that raises some parity issues for something like ::slotted(::text) or even ::slotted(::first-letter) , as either those selectors may include ::before content.
- Text – класс, соответствующий тексту внутри элементов. Например, Hello в