0

I just learned that I can select elements by using data-attributes, which is great. I then want to stylize these elements differently based on certain calcutions. for example, I want to have 4 varieties of style, and I want to use modulus of the existing [data-pid] attribute of the elements to help determine the style.

For example, imagine there are a set of divs containing text that has one of four font colors (e.g. red, orange, yellow, or green), and that an individual div's color depends on its modulus of four. I believe the CSS (if it is possible) would go something like this:

div[0=data-pid-modulus-by-4]{
  color: red;
}

div[1=data-pid-modulus-by-4]{
  color: orange;
}

div[2=data-pid-modulus-by-4]{
  color: yellow;
}

div[3=data-pid-modulus-by-4]{
  color: green;
}

Is it possible to calculate the modulus of a data-pid/attribute using just CSS in a way similar to what I illustrate above or do I have to use javascript to accomplish this modulus of an attribute's value? If it is not possible can someone suggest the smallest/easiest js solution they can think of to do it?

Thanks!

CoderScissorhands
  • 485
  • 1
  • 6
  • 26

4 Answers4

2

Here's a simple JavaScript solution:

var pids = document.querySelectorAll('[data-pid]');

Array.prototype.forEach.call(pids, function(elem, index) {
    elem.classList.add('pid-mod-' + (index % 4));
});
.pid-mod-0 {
  color: red;
}

.pid-mod-1 {
  color: orange;
}

.pid-mod-2 {
  color: yellow;
}

.pid-mod-3 {
  color: green;
}
<div data-pid="0">0</div>
<div data-pid="1">1</div>
<div data-pid="2">2</div>
<div data-pid="3">3</div>
<div data-pid="4">4</div>
<div data-pid="5">5</div>
<div data-pid="6">6</div>
<div data-pid="7">7</div>

If all the elements are siblings of each other, then you can use :nth-of-type() or :nth-child() with a range.

div[data-pid]:nth-of-type(4n+1){
  color: red;
}

div[data-pid]:nth-of-type(4n+2){
  color: orange;
}

div[data-pid]:nth-of-type(4n+3){
  color: yellow;
}

div[data-pid]:nth-of-type(4n+4){
  color: green;
}
<div class="only-pids-in-here">
  <div data-pid="0">0</div>
  <div data-pid="1">1</div>
  <div data-pid="2">2</div>
  <div data-pid="3">3</div>
  <div data-pid="4">4</div>
  <div data-pid="5">5</div>
  <div data-pid="6">6</div>
  <div data-pid="7">7</div>
</div>
Jacob
  • 2,212
  • 1
  • 12
  • 18
  • 1
    The js solution (the second one listed) allows me to do what I wanted beautifully. With it I can consistently style my elements, regardless of what their position on the list is, which is what I wanted. Readers should note that the first solution of this answer will change the style of elements, depending on their order on a list, so that if an object is for whatever reason, changes position, its styling will also change. – CoderScissorhands Jan 13 '17 at 00:17
1

You can not calculate the value directly in CSS, nor SASS/LESS.

You will have to use Javascript in order to do that.

Which makes total sense as calculating parts of html in CSS even if would be doable would be terrible practice.

Michal Takáč
  • 1,005
  • 3
  • 17
  • 37
  • I'm sorry, i don't understand. The elements already have the data-pid values assigned. I don't want to edit any html value, or assign it, i merely want to use the data-pid value as input for the selector to modify style- that's not so awful, is it? Are you sure this is not possible? – CoderScissorhands Jan 12 '17 at 16:47
  • Not sure Im getting what are you trying to do. If you already have values in data-pid you can write selector and styles for that exact pid like this div[data-pid=3] – Michal Takáč Jan 12 '17 at 16:49
  • I don't want to use the exact pid because I will have thousands of elements and using the values themselves means I'd have to constantly update my css file, adding each pid to the selector every time a new object is created. That isn't reasonable. This is why I want to calculate based on modulus. – CoderScissorhands Jan 12 '17 at 16:51
  • On modulus of what? You need two numbers to calculate modulus, where are those numbers coming from? – Michal Takáč Jan 12 '17 at 16:53
  • You are right, this is framed wrong, I want to do modulus of 4, and then then have the css vary be different for each of the four possible results.I changed it to more closely reflect what I meant. – CoderScissorhands Jan 12 '17 at 16:59
  • As mentioned above, you are not able to do that. I would say there is a flaw in your design of the code when you need to do tricky stuff as this. Try to find a better way to structure your code. For example you should add class when adding this stuff in your js or backend code using tempting for example. – Michal Takáč Jan 12 '17 at 17:07
1

You cannot perform arithmetic calculations with the values of attribute selectors within a selector. Attribute values are always strings, and only support substring matching at best.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
1

There's attr but

The attr() function can be used with any CSS property, but support for properties other than content is experimental.

In theory, you should be able to do

div[data-color] {
    color: attr(data-color, 'color');
}

But nothing seems to support it.

I was thinking maybe you could use that in conjunction with calc but calc doesn't support modulo either, so there's really no way for you to calculate a color from a pid using CSS properties.

I think you're out of luck. You should do the calculation of pid->color in whatever template language you're using instead, should be just as easy to do.

mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • 1
    "support for properties other than content is experimental" That's a rather optimistic way of saying "support for properties other than content is [nonexistent](http://stackoverflow.com/questions/8769786/css3s-attr-doesnt-work-in-major-browsers/8769922#8769922)" – BoltClock Jan 12 '17 at 17:07