This question already has an answer here:
Markup:
Hello World
CSS:
.title { border-bottom: 3px solid #aaa; position: relative; } .title:after { content: ""; width: 100px; border-bottom: 3px solid red; display: block; position: absolute; }
Demo: http://codepen.io/anon/pen/HDBqe
I wanted to change the .title:after's width based on the text's width, how do I change :after's width using javascript?
$.fn.textWidth = function(){ var html_org = $(this).html(); var html_calc = '' + html_org + ''; $(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()); });
A pseudo-element is not part of the DOM. Therefore, you cannot change its CSS properties directly through JS.
In order to get your desired effect the way you want it, my best guess would be YUI.StyleSheet and manipulate the stylesheet itself, although I have to admit I haven't tested it myself in recent years.
Including such a utility and doing all of this calculation seems like a lot of work for width matching.
If you are willing to compromise a little bit on the semantic HTML, there is a working technique:
Your element takes the entire width of the screen. Wrapping the text with a span and adding the pseudo-element to that, as an inline-block should allow you to get the border under the text only
HTML:
Hello World
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; }
Here is my version of the codePen.
For future reference:
There is a W3C Candidate Recommendation that suggests the capability of using attributes for CSS properties other than content.
This way, if and when the recommendation is approved and implemented, it might be possible to have the pseudo-element reflect the parent's attributes, as such:
this.setAttribute("length", $(this).textWidth());
And the relevant CSS:
.title:after { ... width: attr(length px); ... }
I've found a trick which works in this case. I've updated your demo:
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; }
Notice, that .title:after has width set to inherit but his parent (.title) has overridden width with min-width. Now I can freely to set width by JavaScript to title and it take effect only on his nested pseudoelement:
$('.title').each(function(){ $(this).css('width', $(this).textWidth()); });
How's this for a different approach.... http://jsfiddle.net/mayYt/
Added CSS
.title span { border-bottom: 3px solid red; }
JQuery
$('.title').wrapInner('');
With just a simple trick any pseudo-element can be changed (or at least replaced with something else):
$('.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; }
click here!