64

I have the grap constructured by CSS, which is dynamically changes by JS. I show graph max value by pseudo element as:

.graph:before {
    content:""; //value that want set by JS
    position:absolute;
    top:0;
    left:0;
}

That's why I need to set this value by JS. I tried $(".graph:before").css("content", hh); but it didn't help. How to get that value?

jumancy
  • 1,290
  • 1
  • 9
  • 16

8 Answers8

110

I hope the below snippet might help, you can specify the content value you want via JS using the CSS attr() function. Below you have two options: to use JavaScript or jQuery:

jQuery:

$('.graph').on('click', function () {
    //do something with the callback
    $(this).attr('data-before','anything'); //anything is the 'content' value
});

JavaScript:

var graphElem = document.querySelector('.graph');
graphElem.addEventListener('click', function (event) {
    event.target.setAttribute('data-before', 'anything');
});

CSS:

.graph:before {
    content: attr(data-before); /* value that that refers to CSS 'content' */
    position:absolute;
    top: 0;
    left: 0;
}
boop
  • 7,413
  • 13
  • 50
  • 94
Santosh D
  • 1,172
  • 2
  • 7
  • 5
35

Update (2018): as has been noted in the comments, you now can do this.

You can't modify pseudo elements through JavaScript since they are not part of the DOM. Your best bet is to define another class in your CSS with the styles you require and then add that to the element. Since that doesn't seem to be possible from your question, perhaps you need to look at using a real DOM element instead of a pseudo one.

James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • -@JamesAllardice this seems like a confusion-inducing decision by either the CSS or JS camps, do you know of any more context for this? – tim peterson May 08 '12 at 08:45
  • 2
    @timpeterson - The pseudo elements are there to provide a way to access otherwise inaccessible information about a document. They were never intended to be accessible from within the document. See the section on [generated content](http://www.w3.org/TR/css3-content/#pseudo-elements) in the CSS spec. – James Allardice May 08 '12 at 08:54
  • 6
    A little late to this party, but for future readers, this isn't entirely correct. You can't *directly* modify pseudo elements with JS, but you can use javascript to modify element attributes which pseudo elements can "read". See the question linked above: http://stackoverflow.com/questions/5041494/manipulating-css-pseudo-elements-such-as-before-and-after-using-jquery – goldins Mar 18 '15 at 16:06
  • `You can't modify pseudo elements through JavaScript since they are not part of the DOM.` really? – xgqfrms Jun 03 '17 at 08:52
  • Maybe you should read this first! @james-allardice [https://stackoverflow.com/a/44342130/5934465](https://stackoverflow.com/a/44342130/5934465) – xgqfrms Jun 03 '17 at 09:15
  • 1
    this is no longer true. the below answers proved that you CAN. – tatsu Apr 10 '18 at 07:41
31

You can use CSS variable

:root {
  --h: 100px;
}

.elem:after {
  top: var(--h);
}

let y = 10;

document.documentElement.style.setProperty('--h', y + 'px')

https://codepen.io/Gorbulin/pen/odVQVL

12

I believe there is a simple solution using the attr() function to specify the content of the pseudo element. Here is a working example using the 'title' attribute, but it should work also with custom attributes.:

document.getElementById('btn_change1').addEventListener("click", function(){
    document.getElementById('test_div').title='Status 1';
});
   
document.getElementById('btn_change2').addEventListener("click", function(){       
    document.getElementById('test_div').title='Status 2';
});
#test_div {
   margin: 4em;
   padding:2em;
   background: blue;
   color: yellow;
}

#test_div:after {
   content:attr(title);
   background: red;
   padding:1em;
}
<button id='btn_change1'>Change div:after to [Status 1]</button>
<button id='btn_change2'>Change div:after to [Status 2]</button>

<div id='test_div' title='Initial Status'>The element to modify</div>
FrancoSF
  • 532
  • 5
  • 17
5

People who are still looking some solution of same problem, it is doable as follows using jQuery:

<button id="changeBefore">Change</button>
<script>
    var newValue = '22';//coming from somewhere
    var add = '<style>.graph:before{content:"'+newValue+'"!important;}</style>';
    $('#changeBefore').click(function(){
        $('body').append(add);
    });
</script>

This example illustrate that on clicking button: changeBefore , the value for .graph:before will change as per new dynamic coming value for it.

For more description about changing of :before or :after element style or getting its content:

Lets suppose your HTML is like this:

<div id="something">Test</div>

And then you are setting its :before in CSS and designing it like:

#something:before{
   content:"1st";
   font-size:20px;
   color:red;
}
#something{
  content:'1st';
}

Please notice I also set content attribute in element itself so that you can take it out easily later. Now there is a button clicking on which, you want to change the color of :before to green and its font-size to 30px. You can achieve that as follows:

Define a css with your required style on some class .activeS :

.activeS:before{
   color:green !important;
   font-size:30px !important;
 }

Now you can change :before style by adding the class to your :before element as follows:

<button id="changeBefore">Change</button>
<script>
    $('#changeBefore').click(function(){
        $('#something').addClass('activeS');
    });
</script>

If you just want to get content of :before, it can be done as:

<button id="getContent">Get Content</button>
<script>
    $('#getContent').click(function(){
        console.log($('#something').css('content'));//will print '1st'
    });
</script>

I hope it helps

Abhay Maurya
  • 11,819
  • 8
  • 46
  • 64
  • best answer here. append (prepend) worked and the rest of the methods (attr, html, ect) did not. I did add the css from the answer above which is the best way to clear out what was already there. – tatsu Apr 10 '18 at 07:41
  • 1
    Thank you, I am glad it helped you! – Abhay Maurya Apr 23 '18 at 13:07
1

I had a similar problem, but with icons. I needed to switch the play and pause icons for an audio player in html5.

The problem here was that HTML, CSS and jQuery all interpret differently the "content" values to show icons, due to the use of \ symbol.

So the best workaround is to delete and re-create the node. Here's my code:

<ul class="list list--buttons">
    <li><a href="#" class="list__link previuos"><i class="fa fa-step-backward"></i></a></li>

    <li><a href="#" class="list__link playpause"><i class="fa fa-play"></i></a></li>

    <li><a href="#" class="list__link next"><i class="fa fa-step-forward"></i></a></li>
</ul>

And the script

<script type="text/javascript">
            $(
                function(){
                    var aud = $('audio')[0];
                    $('.playpause').on('click', function(e){
                        e.preventDefault();
                    if (aud.paused) {
                        aud.play();
                        /* from play icon to pause icon */
                        $('.playpause .fa-play').remove();
                        $('.playpause').append('<i class="fa fa-pause"></i>');
                    }
                    else {
                        aud.pause();
                        /* from play icon to pause icon */
                        $('.playpause .fa-pause').remove();
                        $('.playpause').append('<i class="fa fa-play"></i>');
                    }

                })
                $('.next').on('click', function(e){
                    e.preventDefault();
                    aud.src = '{$content:audio-file}';
                })
                $('.previuos').on('click', function(e){
                    e.preventDefault();
                    aud.src = '{$content:audio-file}';
                })
                aud.ontimeupdate = function(){
                    $('.progress').css('width', aud.currentTime / aud.duration * 100 + '%')
                }
            })
        </script>

Hope it helps!

Anandaweb
  • 11
  • 1
1

You can use document.styleSheets to modify pseudo selector cssRules

document.styleSheets[0].cssRules[0].style.content = '"111"';
michael
  • 111
  • 1
  • 4
  • This tell us it actually CAN be done, without the `content: attr(...)` (and I'd almost +1 you for it), but should it be done that way? Only if you wish to change your Twitter bio from "Developer of web applications" to "Maintainer of one project". – s3c Aug 02 '21 at 13:30
-1

If you use something like an onoffswitch and want to translate the css content attribute with i18next then you can use one of the i18next Framework example from github (i18next Jquery Framework) and then you extended the function with this code:

var before = i18next.t('onoffswitch.before');
var after = i18next.t('onoffswitch.after');
$('.onoffswitch-inner')
    .attr('data-before', before )
    .attr('data-after', after );

and the css code must be this:

.onoffswitch-inner:before {
    content:  attr(data-before);
    padding-left: 10px;
    background-color: #65AFF5; color: #FFFFFF;
}
.onoffswitch-inner:after {
    content:  attr(data-after);
    padding-right: 10px;
    background-color: #EEEEEE; color: #999999;
    text-align: right;
}
GerA
  • 87
  • 8