Stas Bichenko
Stas Bichenko

Reputation: 13273

How do I get the perceived styling of a text node?

window.getComputedStyle() method accepts only element nodes. Is there any way to reliably get the style that determines the visual representation of a text node?

I realize that nodes can't have style attributes, but they certainly are styled, since they inherit the parent element's styles. Is there, perhaps, a way to get all computed styles from the parent element that are relevant to the text node's visual representation?


Note that wrapping the node in a span is out of the question: this would affect CSS rules such as span:nth-child or span + span, etc.

Upvotes: 28

Views: 2981

Answers (3)

Stas Bichenko
Stas Bichenko

Reputation: 13273

I'll give it a try myself.

  1. Use window.getComputedStyle() on the parent element and store the tag name and the style information.
  2. Create a new element with the stored tag name and assign the styles to it via style attribute.
  3. Add a child <foo> element (strictly speaking, it should be of a tag name that is not mentioned in the current CSS rules, so that they don't affect it).
  4. Attach the parent element to the <head> of the document (Webkit-specific).
  5. Use window.getComputedStyle() on the child element.
  6. Set inline as the value of display property (as text nodes are always inline).

Note the results of the code snippet. color is red, margin-left is zero, despite the parent having a left margin, and width (and height, too) is auto.

var source = document.querySelector('.bar');
var sourceStyle = window.getComputedStyle(source);
var sourceTag = source.tagName;
var clone = document.createElement(sourceTag);
var child = document.createElement('foo');
var head = document.querySelector('head');

child.innerHTML = 1;
child.setAttribute('style', 'display: inline;');
clone.appendChild(child);
clone.setAttribute('style', sourceStyle.cssText);
head.appendChild(clone);
alert(window.getComputedStyle(source).marginLeft); // 100px
alert(window.getComputedStyle(child).color); // rgb(255, 0, 0);
alert(window.getComputedStyle(child).marginLeft); // 0px
alert(window.getComputedStyle(child).width); // auto
.bar {
  color: red;
  margin-left: 100px
  }
<html>
  <head>
    <title>An example</title>
  </head>
  <body>
    <div class="bar">
      foo
    </div>
  </body>
</html>

Upvotes: 8

Rob
Rob

Reputation: 15168

The answer to your question is, you can't. Styles are applied to the elements and are shaped by their content. The text content of an element is not styled directly because it is just data. The other answers and comments are only suggestions to obtain the styling of the element which isn't what you asked for. So what you are asking for can't be done because there is no styling applied to the data, the text node, of an element.

Upvotes: 2

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

If the text node is the only node in an element, you could simply use getComputedStyle() on its parentNode.

However, consider the following:

div {border: 1px solid black;}
<div>This <em>is</em> a <strong>test</strong></div>

You cannot say that "This" and "a" each have a border. Would it be accurate to say "This" has top-bottom-left borders, and "a" has top-bottom borders only? That's questionable.

If you limit yourself to styles that specifically apply to text (color, background, textDecoration, font, etc.), applying getComputedStyle() on parentNode should always work.

Upvotes: 10

Related Questions