Dynamically change style through JS

Asked

Viewed 1,382 times

2

In a progressibar, for example, with this style:

#progress {
background: #000000;
border-radius: 13px;
height: 20px;
width: 400px;
padding: 3px;
}

#progress:after {
content: '';
display: block;
background: white;
width: 300;
height: 100%;
border-radius: 9px;
}

I need to change the fill of the bar as a function of time. In case, I need to change the width of the Progress:after. How can I do this?

2 answers

5


I need to change the fill of the bar as a function of time. In case, I need to change the width of the Progress:after. How can I do this?

Cannot directly change the style of a pseudo-elemento, as is the case with :after.

However, you can add specific rules directly into the styles interpreted by the browser.

For this we can use the method .addRule of the object CSSStyleSheet.

However, it is worth noting that this method is not supported on all browsers.

To ensure the code works, we will create an auxiliary function responsible for checking if the browser supports the method .addRule. If not, we will work with the direct rewriting of the property CSS that we want to change.

The auxiliary function created for the example was:

function changeRule(selector, property, value) {

    var stylesheet = document.styleSheets[0];

    if (stylesheet.addRule) {
        stylesheet.addRule(selector, property + ': ' + value);
    } else {

        var rules = stylesheet.cssRules;

        for (var i = 0; i < rules.length; i++) {
            var rule = rules[i];
            if (rule.selectorText == selector) {
                rule.style[property] = value;
            }
        }

    }

}

Here is an example of the use:

var INCREMENT_FACTOR = 25;

function changeRule(selector, property, value) {

  var stylesheet = document.styleSheets[0];

  if (stylesheet.addRule) {
    stylesheet.addRule(selector, property + ': ' + value);
  } else {

    var rules = stylesheet.cssRules;

    for (var i = 0; i < rules.length; i++) {

      var rule = rules[i];

      if (rule.selectorText == selector) {
        rule.style[property] = value;
      }

    }

  }

}

var progressInterval = setInterval(function() {

  var progress = document.getElementById('progress');

  var maximumWidth = parseInt(window.getComputedStyle(progress).getPropertyValue('width'));

  var currentWidth = parseInt(window.getComputedStyle(progress, '::after').getPropertyValue('width'));

  var newWidth = currentWidth + INCREMENT_FACTOR;

  changeRule('#progress::after', 'width', newWidth + 'px');

  if (newWidth == maximumWidth) {
    clearInterval(progressInterval);
    alert('success!');
  }

}, 500);
#progress {
  background: #000000;
  border-radius: 13px;
  height: 20px;
  width: 400px;
  padding: 3px;
}
#progress:after {
  content: '';
  display: block;
  background: white;
  width: 0;
  height: 100%;
  border-radius: 9px;
}
<div id="progress"></div>

Read more on the subject at Modify pseudo element Styles with Javascript.

  • @Sergio believe it is now ok. In the last change did not work because the method .insertRule in FF ends up replacing all the style instead of adding.

  • Good! I already gave +1 I think it’s great now. If you want to explain this Feature Detect stylesheet.addRule would be excellent :P

5

In HTML5 there is a tag <progress> which serves precisely this. The difference is that instead of modifying the width of an element, you will need to change only its value (attribute value).

var $progress = document.querySelector('progress'), // Pegando o elemento
    MAXIMUM   = $progress.max;                      // Pegando o valor máximo: 100

/* Aumentando o valor a cada 1 segundo para exemplificar... */
var interval = setInterval(function(){
  $progress.value++;
  if($progress.value >= MAXIMUM)
    clearInterval(interval);
}, 100);
<progress max='100' value='0'></progress>


It is also possible to customize it like any other HTML element. The difference is that, as the properties are not standardized, we will need to look for properties and prefixes to change the appearance:

.custom {
  background-color: #ecf0f1;
  border: 1px solid #ecf0f1;
  height: 10px
}

/* cor de background da barra */
.custom::-webkit-progress-bar {
  background-color: #fff
}

/* cor de background do valor de progresso */
.custom::-webkit-progress-value {
  background-color: #9b59b6
}

.custom::-moz-progress-bar {
  background-color: #9b59b6
}
<h4>Default:</h4>
<progress max='100' value='50'></progress>

<h4>Customizada:</h4>
<progress class='custom' max='100' value='75' data-value=''></progress>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.