I want to make rate stars progress bar with single div
element and css pseudo elements like ::before
.
Only thing what I can't do is manipulating width of ::before
element with Javascript.
Here is my example:
.review-rate {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAACp0lEQVRIx6VVz29MURQeC5UQ/AHCAgv+AT9KRBGNBSsre0IiQVjYCLGpiDFl0UqxaqdaDQkVGWVU40eGEtFFabWNVlKJtNMgmtJ2Pt9597575973XtPEyVmc851z5t53zrnfpBCV4TweHUK2Ek2bRGnQJRiRlOONf0TbHnSeQrHPwekSZIgJ8cVfu9C4EcV+JEnxMxo3YORZpHj8k9xwasLJHn2Nb28chAlNm835qriElh1S78mdvbi7L3J+H1qqpEQXf3mM/DE/6eeIVFJpeMJkluji3EF8/+BnvDiLgfuiNDxhMkt0cfM2jb67ipvr0bpLlHebnRaloRCGmKAkuyUsvrVdQzNTaD+AwoWYVhNkiAlKgpKgWBpgpISu0+g4olqiEboELQLZHP/aRpq34s8vbdMILukI51rWsB4b+PsbrTvlnO40ui+LQZdgfMO8UQ09ROdJ3NuPV+dFaXA3CcaPSpakyi5J/jjqVmAoF/5WTlyCZkmkW6Wy9Rzrtev5vh4/hp0vpEswYT0D4cZz76NLahezP+FhmCd5ezeennD6Jx3qEZChxCdphM1gMxUTcIpUukGH5iSDcia5vhbpClEa82USdvJiKl4ZmotJapclViqtXZrAJFeW+6lkJbbXA5nmMwm3N3rO4AMMtMfg8irKmSSaUb8SpRlRGtGowyTR8Mtz+otoRKP2YXAYCnpyFBODWqcndTENAzJBZTasCYs5TAWlF6E3m7ieDDFBZ1aExRyAvdICFGriaKhGQibNFt9Y53/SaMFnfy/BXttrWGaxJTpDjATjG+aNin9oMvtZPD8jSoNCMH5UsiSVNvA2g8kxtFWHv1UtLkGTQD7wmcSsZ8dhXFvlnEOXYMJ6hkzitH3+D+N/n6THJA2rcWkhMktkkAlM8g8rt+IWmuHa2gAAAABJRU5ErkJggg==);
background-repeat: repeat-x;
width: 100px;
height: 18px;
}
.review-rate::before {
content: "";
display: block;
width: attr(data-width);
height: 18px;
width: 55%;
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAACp0lEQVRIx6VVz29MURQeC5UQ/AHCAgv+AT9KRBGNBSsre0IiQVjYCLGpiDFl0UqxaqdaDQkVGWVU40eGEtFFabWNVlKJtNMgmtJ2Pt9597575973XtPEyVmc851z5t53zrnfpBCV4TweHUK2Ek2bRGnQJRiRlOONf0TbHnSeQrHPwekSZIgJ8cVfu9C4EcV+JEnxMxo3YORZpHj8k9xwasLJHn2Nb28chAlNm835qriElh1S78mdvbi7L3J+H1qqpEQXf3mM/DE/6eeIVFJpeMJkluji3EF8/+BnvDiLgfuiNDxhMkt0cfM2jb67ipvr0bpLlHebnRaloRCGmKAkuyUsvrVdQzNTaD+AwoWYVhNkiAlKgpKgWBpgpISu0+g4olqiEboELQLZHP/aRpq34s8vbdMILukI51rWsB4b+PsbrTvlnO40ui+LQZdgfMO8UQ09ROdJ3NuPV+dFaXA3CcaPSpakyi5J/jjqVmAoF/5WTlyCZkmkW6Wy9Rzrtev5vh4/hp0vpEswYT0D4cZz76NLahezP+FhmCd5ezeennD6Jx3qEZChxCdphM1gMxUTcIpUukGH5iSDcia5vhbpClEa82USdvJiKl4ZmotJapclViqtXZrAJFeW+6lkJbbXA5nmMwm3N3rO4AMMtMfg8irKmSSaUb8SpRlRGtGowyTR8Mtz+otoRKP2YXAYCnpyFBODWqcndTENAzJBZTasCYs5TAWlF6E3m7ieDDFBZ1aExRyAvdICFGriaKhGQibNFt9Y53/SaMFnfy/BXttrWGaxJTpDjATjG+aNin9oMvtZPD8jSoNCMH5UsiSVNvA2g8kxtFWHv1UtLkGTQD7wmcSsZ8dhXFvlnEOXYMJ6hkzitH3+D+N/n6THJA2rcWkhMktkkAlM8g8rt+IWmuHa2gAAAABJRU5ErkJggg==);
background-repeat: repeat-x;
background-position: 0 -18px;
}
<div class="review-rate" data-toggle="review" data-value="3.5" data-width="50" data-count="17"></div>
Is there any way to manipulate width
of ::before
element?
Maybe something like width: attr(data-width);
?
Any help will be appreciated.
The ::before selector inserts something before the content of each selected element(s). Use the content property to specify the content to insert. Use the ::after selector to insert something after the content.
A CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s). For example, ::first-line can be used to change the font of the first line of a paragraph.
::before. In CSS, ::before creates a pseudo-element that is the first child of the selected element. It is often used to add cosmetic content to an element with the content property.
The input element has no content in the CSS view, and so has no :before or :after pseudo content. This is true of many other void or replaced elements.
One way I know of changing :before
& :after
css dynamically is the one @Brett DeWoody mentioned, Adding style tags.
In your case you can simply switch the role of :before
& div
. Then use div width instead of :before
. Like this:
.review-rate {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAACp0lEQVRIx6VVz29MURQeC5UQ/AHCAgv+AT9KRBGNBSsre0IiQVjYCLGpiDFl0UqxaqdaDQkVGWVU40eGEtFFabWNVlKJtNMgmtJ2Pt9597575973XtPEyVmc851z5t53zrnfpBCV4TweHUK2Ek2bRGnQJRiRlOONf0TbHnSeQrHPwekSZIgJ8cVfu9C4EcV+JEnxMxo3YORZpHj8k9xwasLJHn2Nb28chAlNm835qriElh1S78mdvbi7L3J+H1qqpEQXf3mM/DE/6eeIVFJpeMJkluji3EF8/+BnvDiLgfuiNDxhMkt0cfM2jb67ipvr0bpLlHebnRaloRCGmKAkuyUsvrVdQzNTaD+AwoWYVhNkiAlKgpKgWBpgpISu0+g4olqiEboELQLZHP/aRpq34s8vbdMILukI51rWsB4b+PsbrTvlnO40ui+LQZdgfMO8UQ09ROdJ3NuPV+dFaXA3CcaPSpakyi5J/jjqVmAoF/5WTlyCZkmkW6Wy9Rzrtev5vh4/hp0vpEswYT0D4cZz76NLahezP+FhmCd5ezeennD6Jx3qEZChxCdphM1gMxUTcIpUukGH5iSDcia5vhbpClEa82USdvJiKl4ZmotJapclViqtXZrAJFeW+6lkJbbXA5nmMwm3N3rO4AMMtMfg8irKmSSaUb8SpRlRGtGowyTR8Mtz+otoRKP2YXAYCnpyFBODWqcndTENAzJBZTasCYs5TAWlF6E3m7ieDDFBZ1aExRyAvdICFGriaKhGQibNFt9Y53/SaMFnfy/BXttrWGaxJTpDjATjG+aNin9oMvtZPD8jSoNCMH5UsiSVNvA2g8kxtFWHv1UtLkGTQD7wmcSsZ8dhXFvlnEOXYMJ6hkzitH3+D+N/n6THJA2rcWkhMktkkAlM8g8rt+IWmuHa2gAAAABJRU5ErkJggg==");
background-position: 0 -18px;
background-repeat: repeat-x;
height: 18px;
overflow: visible;
position: relative;
width: 50px;
}
.review-rate::before {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAIAAAAGkY33AAACp0lEQVRIx6VVz29MURQeC5UQ/AHCAgv+AT9KRBGNBSsre0IiQVjYCLGpiDFl0UqxaqdaDQkVGWVU40eGEtFFabWNVlKJtNMgmtJ2Pt9597575973XtPEyVmc851z5t53zrnfpBCV4TweHUK2Ek2bRGnQJRiRlOONf0TbHnSeQrHPwekSZIgJ8cVfu9C4EcV+JEnxMxo3YORZpHj8k9xwasLJHn2Nb28chAlNm835qriElh1S78mdvbi7L3J+H1qqpEQXf3mM/DE/6eeIVFJpeMJkluji3EF8/+BnvDiLgfuiNDxhMkt0cfM2jb67ipvr0bpLlHebnRaloRCGmKAkuyUsvrVdQzNTaD+AwoWYVhNkiAlKgpKgWBpgpISu0+g4olqiEboELQLZHP/aRpq34s8vbdMILukI51rWsB4b+PsbrTvlnO40ui+LQZdgfMO8UQ09ROdJ3NuPV+dFaXA3CcaPSpakyi5J/jjqVmAoF/5WTlyCZkmkW6Wy9Rzrtev5vh4/hp0vpEswYT0D4cZz76NLahezP+FhmCd5ezeennD6Jx3qEZChxCdphM1gMxUTcIpUukGH5iSDcia5vhbpClEa82USdvJiKl4ZmotJapclViqtXZrAJFeW+6lkJbbXA5nmMwm3N3rO4AMMtMfg8irKmSSaUb8SpRlRGtGowyTR8Mtz+otoRKP2YXAYCnpyFBODWqcndTENAzJBZTasCYs5TAWlF6E3m7ieDDFBZ1aExRyAvdICFGriaKhGQibNFt9Y53/SaMFnfy/BXttrWGaxJTpDjATjG+aNin9oMvtZPD8jSoNCMH5UsiSVNvA2g8kxtFWHv1UtLkGTQD7wmcSsZ8dhXFvlnEOXYMJ6hkzitH3+D+N/n6THJA2rcWkhMktkkAlM8g8rt+IWmuHa2gAAAABJRU5ErkJggg==");
background-repeat: repeat-x;
content: "";
display: block;
height: 18px;
position: relative;
width: 100px;
z-index: -1;
}
<div class="review-rate" data-toggle="review" data-value="3.5" data-width="50" data-count="17"></div>
Though it's not ideal, you can append a new <style>
element to the page using jQuery with the new width
value.
$('head').append('<style>.review-rate:before{width:75%}</style>');
Here's a demo.
Update
As Imran pointed out in the comment below, the above approach would result in many <style>
tags over time. To prevent this a combo of append
and replaceWith
could be used to keep the number of <style>
tags to a minimum.
if ($('head style[data-class="review-rate"]').length) {
$('head style[data-class="review-rate"]').replaceWith('<style data-class="review-rate">.review-rate:before{width:75%}</style>')
} else {
$('head').append('<style data-class="review-rate">.review-rate:before{width:35%}</style>');
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With