如何使CSS文本装饰覆盖生效?

39

有些日子我感觉自己要疯了,今天就是这样一天。我认为我的CSS相当简单明了,但它似乎就是不起作用。我错过了什么?

我的CSS如下:

ul > li {
    text-decoration: none;
}
ul > li.u {
    text-decoration: underline;
}
ul > li > ul > li {
    text-decoration: none;
}
ul > li > ul > li.u {
    text-decoration: underline;
}

我的 HTML 代码如下:

<ul>
  <li>Should not be underlined</li>
  <li class="u">Should be underlined
    <ul>
      <li>Should not be underlined</li>
      <li class="u">Should be underlined</li>
    </ul>
  </li>
</ul>

但实际效果如下:

图片


在XHTML中,是的,它已经被弃用了。 - soapergem
在底部应用边框可以很好地替代使用下划线。有人认为这样看起来更好,而且你可以通过填充来调整间距。 - Surreal Dreams
7个回答

48

text-decoration与其他字体/文本相关的样式(如font-weight)不同。应用text-decoration会影响所有嵌套元素。

查看此网址:http://www.w3.org/TR/CSS21/text.html#propdef-text-decoration

摘自:

 

行内框上的文本装饰延伸至整个元素,横跨任何后代元素而不注意它们的存在。 后代元素上的'text-decoration'属性对元素的装饰没有任何影响。
  . . . .
  一些用户代理通过将修饰传播到后代元素来实现文本装饰,而不是像上面描述的简单地在元素中绘制修饰。 CSS2中使用了更宽松的措辞,这可以说是允许的。

信息来源:http://csscreator.com/node/14951


5
基本上无法实现,相反我必须确保永远不在父级 li 上设置该属性,而是在那里包含一个 <span> 或类似的东西。这似乎是 CSS 规范中包含的一个愚蠢和武断的规则;它太不符合直觉了。 - soapergem
2
说实话,那是真的。坦白地说,如果不是因为你的问题,我也不会发现这个:P。 - o.k.w
1
@o.k.w,我刚遇到了同样的问题,但我想你仍然可以通过将嵌套元素转换为块元素来应用文本修饰。https://dev59.com/VmPVa4cB1Zd3GeqP6ope#eKGdEYcBWogLw_1bvudM - KBN
27
在另一个问题上看到了这个解决方案,使用 display: inline-block; 来清除项目的文本装饰。https://dev59.com/JnjZa4cB1Zd3GeqPcEcT#19529256 - mikegertrudes
1
这个答案已经过时了;Oriol的答案展示了如何覆盖内部元素的下划线。 - Jukka K. Korpela

34
你需要在以下情况下取消应用于父元素的text-decoration

  • Out-of-flow elements, such as floated and absolutely positioned ones

    li {
      float: left; /* Avoid text-decoration propagation from ul */
      clear: both; /* One li per line */
    }
    ul { overflow: hidden; } /* Clearfix */
    

    ul {
      overflow: hidden; /* Clearfix */
    }
    li {
      float: left; /* Avoid text-decoration propagation from ul */
      clear: both; /* One li per line */
    }
    li.u {
      text-decoration: underline;
    }
    <ul>
      <li>Should not be underlined</li>
      <li class="u">Should be underlined
        <ul>
          <li>Should not be underlined</li>
          <li class="u">Should be underlined</li>
        </ul>
      </li>
    </ul>

  • Atomic inline-level elements, such as inline blocks and inline tables

    But if you use li{display:inline-block}, then you don't have bullets (you lose display:list-item) and the items appear one next to the others.

    Then, to have one item per line, you can use

    li {
      display: inline-block; /* Avoid text-decoration propagation from ul */
      width: 100%;           /* One li per line */
    }
    

    And to add the bullets, you can use ::before pseudo-elements. However, bullets shouldn't be underlined, so you will need to take them out-of-flow or make them atomic inline-level too.

    li {
      display: inline-block; /* Avoid text-decoration propagation from ul */
      width: 100%;           /* One li per line */
    }
    li:before {
      content: '• ';         /* Insert bullet */
      display: inline-block; /* Avoid text-decoration propagation from li */
      white-space: pre-wrap; /* Don't collapse the whitespace */
    }
    li.u {
      text-decoration: underline;
    }
    <ul>
      <li>Should not be underlined</li>
      <li class="u">Should be underlined
        <ul>
          <li>Should not be underlined</li>
          <li class="u">Should be underlined</li>
        </ul>
      </li>
    </ul>

    li {
      display: inline-block; /* Avoid text-decoration propagation from ul */
      width: 100%;           /* One li per line */
    }
    li:before {
      content: '•';          /* Insert bullet */
      position: absolute;    /* Avoid text-decoration propagation from li */
      margin-left: -.75em;
    }
    li.u {
      text-decoration: underline;
    }
    <ul>
      <li>Should not be underlined</li>
      <li class="u">Should be underlined
        <ul>
          <li>Should not be underlined</li>
          <li class="u">Should be underlined</li>
        </ul>
      </li>
    </ul>


这种行为在CSS 2.1CSS文本修饰模块3级中有规定:
请注意,文本装饰不会传播到任何流外后代,也不会传播到原子内联级后代的内容,如内联块和内联表格。

你可以在 li 元素内部的一个 div 上使用 inline:block,这样就不会失去项目符号。 - Omu

2
你看到的原因是你的规则。这是因为你可能已经编写了一个CSS样式表,或者在HTML中使用了内联样式或行内样式。
ul > li.u

优先于:
ul > li > ul > li

作为一个指定了类的样式,其权重比元素选择器加在一起还要大。 编辑:你可以尝试以下方法:
.u ul {
        text-decoration: none;
}
.u {
        text-decoration: underline;
}

玩弄它(也许你需要使用 li.u 而不是只有 .u)。

然而,根据内容的不同,您可能想要将下划线部分包装在 qemstrong 标签中,并样式化这些标签,而不是使用类。这样,您就可以描述您的内容并样式化它。


这是正确的,CSS中最具体的规则在这些规则的级联应用中将具有最大的权重,#id是最具体的,然后是.class,再然后是元素选择器。 - Colin
我曾经在某个地方看到过一个列表,其中包含计算规则权重的确切值。但现在找不到了... - jeroen
我理解,但是我的问题在于如何覆盖继承的下划线属性并将其设置回无下划线,因为它似乎当前正在忽略那个规则,即使我在更具体的无下划线规则中添加!important。 - soapergem

2

上面的o.k.w.答案 很好地解释了为什么你不能在不进行其他更改的情况下实现你所要求的。 不,你没有发疯!

可能的解决方法:

  • 尝试使用 border-bottom
  • 将要加下划线的文本包含在一个 span class="u" 标签中?(以防止文本装饰嵌套元素)
  • 如果您无法更改标记,则可以添加一些脚本来完成与我的先前建议相同的操作。

祝你好运!


我经常简化/修改我在问题中给出的示例,以使我的解释尽可能清晰。实际上,我将要处理text-decoration: line-through,而且没有任何边框属性真正与之对齐。看起来额外的span标签或JavaScript是解决方案。但两者都似乎不太优雅;这似乎更像是CSS规范中的一个“错误”而已。 - soapergem

0
我发现最干净的方法就是将下划线设置为背景颜色。

0

当我使用外部主题/CSS时,遇到了类似的问题,因此无法修改它以删除text-decoration: none;。在我的情况下,我有一个带有链接的子元素,但链接没有像预期的那样被下划线。我尝试使用其他人提到的display: inline-block;,但没有效果。

对我有效的是覆盖text-decoration,就像你所做的那样,但还包括!important,以强制它覆盖父级的text-decoration

// Defined in an external CSS, so I couldn't modify it.
.footer {
    text-decoration: none;
}

// In my CSS file.
.footer a {
    text-decoration: underline !important;
}

因此,针对您的特定示例,我想这可能是一个解决方法(我没有测试它来确认):

ul > li > ul > li {
    text-decoration: none !important;
}

我尝试了这个,但它没有起作用。你能上传一小段代码吗? - Math is Hard
@MathisHard 我认为我在这里提供的代码片段更容易理解,但是这里是我在博客中使用它的地方,如果你想看到一个真实的示例。 - deadlydog

-3
.u {text-decoration: underline;}

2
无法正常工作,因为子列表中的所有元素都将被强调。请访问http://jsbin.com/iweri查看其效果。 - Vegard Larsen
看看安德鲁的代码,它和我的相反,但它却能工作。奇怪的是我的不能 :) - James
OP已经使用了等效的代码,但没有解释。这不是一个答案。 - Oriol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接