Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 560
sbichenko Avatar asked Jun 21 '15 10:06

sbichenko


3 Answers

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.

like image 65
Rick Hitchcock Avatar answered Nov 10 '22 07:11

Rick Hitchcock


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>
like image 40
sbichenko Avatar answered Nov 10 '22 07:11

sbichenko


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.

like image 40
Rob Avatar answered Nov 10 '22 07:11

Rob