Targeting text nodes with CSS

后端 未结 2 500
有刺的猬
有刺的猬 2020-12-02 02:03

I\'m working on the CSS for a container object. I have it mostly working. Specifically, I\'m looking at test case 1, 2 and 3. They all have text nodes. Is there a way to tre

相关标签:
2条回答
  • 2020-12-02 02:41

    In this case, I'd be tempted to place each text node inside a <span> which is the classic, non-semantic phrasing element.

    (See: http://www.w3.org/TR/html-markup/span.html)

    You can then style the span in a similar manner to the way you have styled the p and the code.

    If you choose this approach, you have two choices. You can either:

    1) Write the spans directly into the markup:

    code, p, quote, span {
      display: block;
      position: relative;
      margin: 0;
      padding: 1em;
      border: 1px solid black;
      box-sizing: border-box;
    }
    
    p {background-color: #0df;}
    code {background-color: #ccc;}
    span {background-color: #fff;}
    
    
    .container {
      display: block;
      position: relative;
      margin-right: 0;
      margin-left: 0;
      margin-top: 1.5em;
      margin-bottom: 1.5em;
      padding: 0.5rem;
      border: 1px solid black;
      box-sizing: border-box;
      border-radius: 10px;
      box-shadow: none;
    }
    
    .container :first-child {
      border-top-left-radius: 10px;
      border-top-right-radius: 10px;
      border-bottom-left-radius: 0;
      border-bottom-right-radius: 0;
      border-width: 0;
      margin-top: -0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    .container >:last-child {
      border-top-left-radius: 0;
      border-top-right-radius: 0;
      border-bottom-left-radius: 10px;
      border-bottom-right-radius: 10px;
      border-bottom-width: 0;
      border-left-width: 0;
      border-right-width: 0;
      margin-top: 0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    .container >:not(:first-child):not(:last-child) {
      margin-left: -0.5rem;
      margin-right: -0.5rem;
      margin-bottom: -0.5rem;
      border-right-width: 0;
      border-left-width: 0;
      border-bottom-width: 0;
    }
    .container >:only-child {
      border-radius: 10px;
      border-width: 0;
      margin-top: -0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    <div id="container-1" class="container">
    <p>first child</p>
    <span>text</span>
    <code>last child</code>
    </div>
    
    <div id="container-2" class="container">
      <p>first child</p>
      <span>text</span>
    </div>
    
    <div id="container-3" class="container">
      <span>text</span>
      <p>last child</p>
    </div>

    Or, if you prefer not to have spans included in your markup, you can

    2) Add the span elements dynamically, after the page loads:

    var containers = document.getElementsByClassName('container');
    
    for (var i = 0; i < containers.length; i++) {
        for (var j = 0; j < containers[i].childNodes.length; j++) {
            if (containers[i].childNodes[j].nodeName !== '#text') {continue;} /* skips all nodes which aren't text nodes */
            if (/^[\s\n]*$/.test(containers[i].childNodes[j].textContent)) {continue;} /* skips all text nodes containing only whitespace and newlines */
    
            var text = containers[i].childNodes[j];
            var span = document.createElement('span');
            span.appendChild(text);
            span.textContent = span.textContent.trim();
            containers[i].insertBefore(span,containers[i].childNodes[j]);
        }
    }
    code, p, quote, span {
      display: block;
      position: relative;
      margin: 0;
      padding: 1em;
      border: 1px solid black;
      box-sizing: border-box;
    }
    
    p {background-color: #0df;}
    code {background-color: #ccc;}
    span {background-color: #fff;}
    
    
    .container {
      display: block;
      position: relative;
      margin-right: 0;
      margin-left: 0;
      margin-top: 1.5em;
      margin-bottom: 1.5em;
      padding: 0.5rem;
      border: 1px solid black;
      box-sizing: border-box;
      border-radius: 10px;
      box-shadow: none;
    }
    
    .container :first-child {
      border-top-left-radius: 10px;
      border-top-right-radius: 10px;
      border-bottom-left-radius: 0;
      border-bottom-right-radius: 0;
      border-width: 0;
      margin-top: -0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    .container >:last-child {
      border-top-left-radius: 0;
      border-top-right-radius: 0;
      border-bottom-left-radius: 10px;
      border-bottom-right-radius: 10px;
      border-bottom-width: 0;
      border-left-width: 0;
      border-right-width: 0;
      margin-top: 0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    .container >:not(:first-child):not(:last-child) {
      margin-left: -0.5rem;
      margin-right: -0.5rem;
      margin-bottom: -0.5rem;
      border-right-width: 0;
      border-left-width: 0;
      border-bottom-width: 0;
    }
    .container >:only-child {
      border-radius: 10px;
      border-width: 0;
      margin-top: -0.5rem;
      margin-bottom: -0.5rem;
      margin-left: -0.5rem;
      margin-right: -0.5rem;
    }
    <div id="container-1" class="container">
    <p>first child</p>
    text
    <code>last child</code>
    </div>
    
    <div id="container-2" class="container">
    <p>first child</p>
    text
    </div>
    
    <div id="container-3" class="container">
    text
    <p>last child</p>
    </div>

    0 讨论(0)
  • 2020-12-02 02:57

    Only text that is wrapped in HTML tags can be targeted by CSS.

    Your text that is not explicitly wrapped by HTML tags is algorithmically wrapped by anonymous boxes. These boxes may inherit styles, but they cannot be targeted by CSS.

    From the spec:

    9.2.1.1 Anonymous block boxes

    The properties of anonymous boxes are inherited from the enclosing non-anonymous box. Non-inherited properties have their initial value.

    If adding HTML tags around your anonymous text is not an option, consider setting the text styles on the container. For the elements that can be targeted, you can then override the container styles. Of course, this method will fall flat if you want the text to have display: none.

    0 讨论(0)
提交回复
热议问题