使用 CSS :not() 定位元素中的选定内容

Posted

技术标签:

【中文标题】使用 CSS :not() 定位元素中的选定内容【英文标题】:Use CSS :not() to target selected content in an element 【发布时间】:2020-08-16 03:06:42 【问题描述】:

我有一个 .header div,其中包含一个跨度 maindomain 和一个 div otherdomains

<div class="header"><span class="maindomain">LatestFooty.co.uk</span> is currently available for sale, along with:
<div class="otherdomains">    
LatestFootie.com<br>
LatestFootie.co.uk
</div>
</div>

我正在尝试定位目前正在出售,以及:,而不涉及.maindomain.otherdomains 的内容。我知道解决这个问题的最佳方法可能是将它包装在一个跨度中并以它为目标,但在这一点上,我想弄清楚为什么我不能让 :not 伪类工作。

这是我所拥有的:

@media (min-width:300px) and (max-width:450px) 
  .header:not(.maindomain):not(.otherdomains) 
  font-style: italic;  
  

据我所知,语法是正确的,我不认为这是一个特殊性问题,因为!important 没有任何区别。我做错了什么?

【问题讨论】:

header 是您不想定位的元素的父元素。 这能回答你的问题吗? Is there a CSS parent selector? 相关:***.com/a/49609442/8620333 你需要 2 个 CSS 规则 【参考方案1】:

一切都在演示本身中,javascript 用于演示目的。

演示

const lnx = [...document.links];
lnx.forEach(lnk => lnk.addEventListener('click', viewhtml));
function viewHTML(e) 
  const link = e.target;
  const headers = document.querySelectorAll('.'+this.dataset.tag);
  headers.forEach(hdr => 
    if (!hdr.matches('.hide')) 
      link.className = 'off';
      let str = hdr.outerHTML;
      let txt = document.createElement('div');
      txt.className = 'txt';
      hdr.insertAdjacentElement('afterend', txt);
      hdr.nextElementSibling.insertAdjacentText('beforeend', str);
      hdr.classList.add('hide'); 
     else 
      link.className = '';
      hdr.classList.remove('hide');
      hdr.nextElementSibling.remove();
    
  );
body 
  font: 400 2.5vw/1.5 Consolas


[class^=header] 
  font-family: Arial;


/* Header (OP)
Selector fails -- :not() is prefixed incorrectly
.header:...  means .header is targeted
.header :... means the descendants of .header is targeted
There is no .header.A, .header.B, nor .header.A.B 
so .header without .A and/or .B will have everything in italics
*/
.header:not(.A):not(.B) 
  font-style: italic;  


/* Header 1
Best solution with no extra HTML tags:
Assign font-style: normal...
directly (.C1, .D1)
or by class (.N)
*/
.header1 
  font-style: italic;


.C1,
.D1,
.N 
  font-style: normal;


/* Header 2
Using :not() needs extra HTML tag:
Wrap second textnode in an inline or inline-block tag
As content of a descendant tag, the text can be targeted
*/
.header2 *:not(.E):not(.F) 
  font-style: italic;


/* Header 3
Smart solution with extra HTML tag:
Wrap second textnode in <i> or <em>
*/
.header3 
  /* no styles needed */


/* Header 4
Slickest solution with least HTML:
Wrap text that needs italics in <i> and then style lines with CSS
*/
.header4 
  white-space: pre-line;


/* For Demo Purposes */
.dash 
  border-style: dashed;


.edge 
  border-style: ridge;
  border-width: 3px;


summary:hover 
  color: lime;
  background: #000;
  cursor: pointer;


summary + u 
  display: inline-block;
  text-decoration: none;
  white-space: pre-line;


code 
  color: green;
  background: rgba(0, 0, 0, 0.2);
  white-space: pre;


summary + code 
  display: block;


a 
  display: block;
  text-decoration: none;
  text-align: center;


a:link, 
a:visited 
  color: cyan;
  background: #000;


a:hover,
a:active 
  color: blue;
  background: none;
  

a::before 
  content: 'View .'attr(data-tag);


a.off::before 
  content: 'Hide .'attr(data-tag);
 

a::after 
  content: ' HTML';


.hide 
  display: none;


.txt 
  color: blue;
  background: rgba(0, 0, 0, 0.2);
  white-space: pre;
<main>
<hr class='edge'>
<details><summary>Header (OP)</summary>
<u>Selector fails -- :not() is prefixed incorrectly
.header:...  means .header is targeted &#128078;
.header<code>&blank;</code>:... means the descendants of .header is targeted &#128077;
There is no .header.A, .header.B, nor .header.A.B so
.header <em>without</em> .A and/or .B will have everything in italics</u></details>
<details><summary>CSS</summary>
<code>.header:not(.A):not(.B) 
  font-style: italic;  
</code>
<a href='#/' data-tag='header'></a>
</details>
<hr>

<div class='header'>
  <span class="A">LatestFooty.co.uk</span> is currently available for sale, along with:
  <div class="B">
    LatestFootie.com<br> LatestFootie.co.uk
  </div>
</div>

<hr class='edge'>
<details><summary>Header 1</summary>
<u>Best solution with no extra HTML tags:
Assign <code>font-style: normal</code>...
directly (.C1, .D1)
or by class (.N)</u></details>
<details><summary>CSS</summary>
<code>.header1 
  font-style: italic;


.C1,
.D1,
.N 
  font-style: normal;
</code>
<a href='#/' data-tag='header1'></a>
</details>
<hr>

<div class="header1">
  <span class="C1">LatestFooty.co.uk</span> is currently available for sale, along with:
  <div class="D1">
    LatestFootie.com<br> LatestFootie.co.uk
  </div>
</div>

<hr class='dash'>

<div class="header1">
  <span class="C2 N">LatestFooty.co.uk</span> is currently available for sale, along with:
  <div class="D2 N">
    LatestFootie.com<br> LatestFootie.co.uk
  </div>
</div>

<hr class='edge'>
<details><summary>Header 2</summary>
<u>Using :not() needs extra HTML tag:
Wrap second textnode in an inline or inline-block tag
As content of a descendant tag, the text can be targeted</u></details>
<details><summary>CSS</summary>
<code>.header2 *:not(.E):not(.F) 
  font-style: italic;
</code>
<a href='#/' data-tag='header2'></a>
</details>
<hr>

<div class='header2'>
  <span class="E">LatestFooty.co.uk</span> <span>is currently available for sale, along with:</span>
  <div class="F">
    LatestFootie.com<br> LatestFootie.co.uk
  </div>
</div>

<hr class='edge'>
<details><summary>Header 3</summary>
<u>Smart solution with extra HTML tag:
Wrap second textnode in <code>&lt;i&gt;</code> or <code>&lt;em&gt;</code></u></details>
<details><summary>CSS</summary>
<code>.header3 
  /* no styles needed */
</code>
<a href='#/' data-tag='header3'></a>
</details>
<hr>

<div class='header3'>
  <span class="G">LatestFooty.co.uk</span> <i>is currently available for sale, along with:</i>
  <div class="H">
    LatestFootie.com<br> LatestFootie.co.uk
  </div>
</div>

<hr class='edge'>
<details><summary>Header 4</summary>
<u>Slickest solution with least HTML:
Wrap text that needs italics in <code>&lt;i&gt;</code> and then style lines with CSS</u></details>
<details><summary>CSS</summary>
<code>.header4 
  white-space: pre-line;
</code>
<a href='#/' data-tag='header4'></a>
</details>
<hr>

<header class='header4'>LatestFooty.co.uk <i>is currently available for sale, along with:</i>
  LatestFootie.com
  LatestFootie.co.uk
</header>
</main>

【讨论】:

【参考方案2】:

你需要两个选择器:

.header 
  font-style:italic;

.header .otherdomains,
.header .maindomain 
  font-style:initial;


/* OR
.header * 
  font-style:initial;


*/
<div class="header"><span class="maindomain">LatestFooty.co.uk</span> is currently available for sale, along with:
<div class="otherdomains">    
LatestFootie.com<br>
LatestFootie.co.uk
</div>
</div>

【讨论】:

我选择了另一个答案,因为它是对这个问题的更直接的答案,但我赞成解释如何在没有:not() 的情况下在 CSS 中实现这一点。【参考方案3】:

.header:not(.maindomain):not(.otherdomains) 仅针对具有 .header 类且本身不具有 .maindomain 和/或 .otherdomain 类的元素。

您目前的规则是:

&lt;div class="header"&gt; 被定位

&lt;div class="header maindomain"&gt; 不是目标

&lt;div class="header otherdomains"&gt; 不是目标

&lt;div class="header maindomain otherdomains"&gt; 不是目标

但这显然不是你想在这里做的。

您不能将规则应用到 .header 类,这取决于它的子类仅使用 CSS。

您的问题here 有一个已获批准的答案,它可能会引导您朝着正确的方向前进(在这种情况下使用 JavaScript 或 jQuery)。

【讨论】:

所以我误解了:not() 的工作原理,这很公平。 JavaScript 或 jQuery 将是矫枉过正,所以我认为此时最好只在有问题的文本周围环绕一个跨度。谢谢。 @Hashim 这将是最好的方法,是的。【参考方案4】:

我正在尝试定位“目前有售,以及:”,而不触及 .maindomain.otherdomains 的内容。

您不能在 CSS 中定位匿名元素。

CSS 规则需要附加到 HTML 中的“钩子”。该钩子是一个 HTML 标记。没有标签,CSS 就没有目标。这个概念适用于所有盒子模型。

来自MDN:

当没有用于该框的 HTML 元素时,将创建一个匿名框。例如,当您在父元素上声明 display: flex 时,就会发生这种情况,并且直接在其中有一段文本不包含在另一个元素中。为了修复框树,围绕该文本运行创建了一个匿名框。然后它将表现为一个弹性项目,但是,它不能像常规框一样被定位和设置样式,因为没有可定位的元素

(强调我的)

【讨论】:

以上是关于使用 CSS :not() 定位元素中的选定内容的主要内容,如果未能解决你的问题,请参考以下文章

如何使用not选择器定位ID中的元素?

CSS使容器相对父元素垂直水平居中定位(父容器及子元素大小不确定)

css如何不改变原位置的使多个图片在原地动画

CSS定位机制之浮动定位float

怎样使网页设计中的css盒子内容居中?

CSS入门学习