【问题标题】:Targeting text nodes with CSS使用 CSS 定位文本节点
【发布时间】:2016-11-21 19:31:04
【问题描述】:

我正在处理容器对象的 CSS。我大部分时间都在工作。具体来说,我正在查看测试用例 1、2 和 3。它们都有文本节点。有没有办法像对待任何子元素一样对待文本节点?

有没有办法调整 CSS 以使文本节点及其兄弟节点正常工作?除非有一个 CSS 选择器可以使用,它会选择一个 .container,如果有的话,只有在有一个文本节点的情况下,所以我可以 display: none 它(或者更好的东西,但仍然让开发人员知道事情不工作)?

这里也是Codepen

code,
p,
quote {
  display: block;
  position: relative;
  margin: 0;
  padding: 1em;
  border: 1px solid black;
  box-sizing: border-box;
}
code {
  background-color: #ccc;
}
p {
  background-color: #0df;
}
quote {
  background-color: #fd0;
}
quote::after {
  display: table;
  clear: both;
  content: "";
}
.hidden {
  display: none;
}
.third {
  height: 100%;
  width: 33%;
  float: left;
  border: 1px solid black;
}
.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;
}
<p>p</p>
<br />
<code>code</code>
<br />
<quote>quote</quote>

<div id="0" class="container">
  text
</div>

<div id="1" class="container">
  <p>first child</p>
  text
  <code>last child</code>
</div>

<div id="2" class="container">
  <p>first child</p>
  text
</div>

<div id="3" class="container">
  text
  <p>last child</p>
</div>

<div id="4" class="container">
  <p>first child</p>
  <code>last child</code>
</div>

<div id="5" class="container">
  <code>first child</code>
  <p>last child</p>
</div>

<div id="6" class="container">
  <code>first child</code>
  <code>last child</code>
</div>

<div id="7" class="container">
  <p>first child</p>
  <p>last child</p>
</div>

<div id="8" class="container">
  <code>only child</code>
</div>

<div id="9" class="container">
  <p>first child</p>
  <quote>middle child</quote>
  <quote>middle child</quote>
  <p>last child</p>
</div>

<div id="10" class="container">
  <quote>
    <div class="third">1</div>
    <div class="third">2</div>
    <div class="third">3</div>
  </quote>
</div>

<div id="11" class="container">
  <quote class="hidden">hidden child</quote>
  <p>first child</p>
  <p>last child</p>
</div>

<div id="12" class="container">
  <p>first child</p>
  <p>last child</p>
  <quote class="hidden">hidden child</quote>
</div>

【问题讨论】:

标签: html css css-selectors


【解决方案1】:

只有用 HTML 标记包裹的文本才能成为 CSS 的目标。

您没有被 HTML 标记明确包裹的文本在算法上被 匿名框包裹。这些框可以继承样式,但它们不能被 CSS 定位。

来自规范:

9.2.1.1 Anonymous block boxes

匿名框的属性继承自封闭框 非匿名框。非继承属性有其初始值。

如果无法在匿名文本周围添加 HTML 标记,请考虑在容器上设置文本样式。对于可以定位的元素,您可以覆盖容器样式。当然,如果您希望文本具有display: none,则此方法将失败。

【讨论】:

    【解决方案2】:

    在这种情况下,我很想将每个文本节点放在 &lt;span&gt; 中,这是经典的非语义短语元素。

    见:http://www.w3.org/TR/html-markup/span.html

    然后,您可以按照与设置 pcode 的样式类似的方式设置 span 的样式。

    如果您选择这种方法,您有两个选择。您可以:

    1) 将spans 直接写入标记:

    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>

    或者,如果您不想在标记中包含spans,您可以

    2) 在页面加载后动态添加span 元素:

    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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-25
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-10-12
      • 1970-01-01
      相关资源
      最近更新 更多