使用JavaScript修改伪元素:after的宽度

14

标记:

<h1 class="title">Hello World</h1>

CSS:

.title {
  border-bottom: 3px solid #aaa;
  position: relative;
}
.title:after {
  content: "";
  width: 100px;
  border-bottom: 3px solid red;
  display: block;
  position: absolute;
}

演示:http://codepen.io/anon/pen/HDBqe

我想根据文本的宽度来改变.title:after的宽度,如何使用JavaScript来改变:after的宽度?

$.fn.textWidth = function(){
  var html_org = $(this).html();
  var html_calc = '<span>' + html_org + '</span>';
  $(this).html(html_calc);
  var width = $(this).find('span:first').width();
  $(this).html(html_org);
  return width;
};

$('.title').each(function(){
  // Change :after's width based on the text's width
  // .css('width', $(this).textWidth());
});

你无法使用JS访问这个伪选择器。 - gvee
1
他可以在样式表中更改样式。 - Itay
1
@Itay,这将是我采取的方法。由于伪元素不是DOM的一部分,您将不得不针对样式表进行目标设置。请参见此答案 - MasterAM
4个回答

18

我发现了一个在这种情况下有效的技巧。我已经更新了你的演示:

http://codepen.io/anon/pen/bHLtk

.title {
  border-bottom: 3px solid #aaa;
  position: relative;
  min-width: 100%;
}

.title:after {
  content: "";
  width: inherit;
  border-bottom: 3px solid red;
  display: block;
  position: absolute;
}

需要注意的是,.title:after 的宽度设置为inherit,但其父元素 (.title) 已通过min-width覆盖了width属性。现在我可以通过JavaScript自由地设置标题的宽度,并且它只会影响其嵌套的伪元素:

$('.title').each(function(){
  $(this).css('width', $(this).textWidth());
});

6
做得很好,想出了新思路。 - V Maharajh
这非常聪明,谢谢! - Engin Yapici

4

伪元素不是DOM的一部分。因此,您不能通过JS直接更改其CSS属性。

为了以您想要的方式获得所需的效果,我最好的猜测是使用YUI.StyleSheet并操纵样式表本身,尽管我必须承认我近年来没有测试过它。

包括这样的实用程序并进行所有这些计算似乎是很多工作来匹配宽度。

如果您愿意在语义HTML上做出一些妥协,那么有一种有效的技术:

您的元素占据整个屏幕的宽度。将文本用span包装并将伪元素添加到其中,作为inline-block,应该允许您仅在文本下方获得边框。

HTML:

<h1 class="title"><span>Hello World</span></h1>

CSS:

.title {
    border-bottom: 3px solid #aaa;
    position: relative;
}

.title span{
    display:inline-block;
    position:relative;
}

.title span:after {
    content: "";
    width: 100%;
    border-bottom: 3px solid red;
    display: block;
    position: absolute;
}

这是我版本的CodePen

供日后参考:

有一个W3C候选推荐,建议使用属性来控制CSS属性,而不仅限于content

这样,如果该推荐得到批准并实施,伪元素可能会反映父级的属性,如下所示:

this.setAttribute("length", $(this).textWidth());

相关的CSS代码如下:

.title:after {
    ...
    width: attr(length px);
    ...
}

你是怎么知道应该使用 display:block 的?我的第一个想法是 bottom: -3px; left: 0,但是 display:block 的技巧起了作用。 - Jürgen Paul
FYI,截至Chrome 59版本,仍不支持此功能 :( - Alex White
我不知道你从哪里得到了 "width: attr(length px);",但那根本不起作用。 - A Friend
1
正如这个(相当古老的)答案所述,这是一个__候选推荐__,因此不能保证它会被接受。话虽如此,使用以data-为前缀的属性可能会起作用。 - MasterAM

1

这种方法如何…… http://jsfiddle.net/mayYt/

添加 CSS

.title span {
    border-bottom: 3px solid red;
}

JQuery

$('.title').wrapInner('<span />');

0

只需一个简单的技巧,任何伪元素都可以被更改(或至少替换为其他内容):

$('.something').click(function(){
  $(this).toggleClass('to_show');
});
.something
{
  background: red;
  height: 40px;
  width: 120px;
  position: relative;
}
.something.to_show:after
{
  content: "X";
  color: white;
  background: green;
  width: 20px;
  height: 20px;
  position: absolute;
  right: 0px;
  top: 0px;
  display: block;
  text-align: center;
}
.something:after
{
  content: "O";
  color: white;
  background: blue;
  width: 30px;
  height: 25px;
  position: absolute;
  right: 0px;
  top: 0px;
  display: block;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <body>
    <div class="something">
      click here!
    </div>
  </body>
</html>


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