Assign CSS Attributes According to Class "Range"

Assign CSS attributes according to class range

Yes, with Limits

I have been pondering a solution that is similar to cimmanon's, only I knew it needed to be far more refined than that (which is why it has taken some time to answer).

Let me state up front that this probably needs a practical limit (I don't know if there is a limit on the number of characters that it can be in your situation). As you can see in my example fiddle, anything 300+ fails to resolve to larger sizes. If there is a high or unknown upper limit, then javascript is really going to be your best solution. My example works for less than 300, and perhaps up to 999 could be made with not too much more code. But 1000+ I think would be unreasonable.

CSS

/* set default as small size */
[class ^= "txtField"] {
width: 50px;
}

/* weed out 50-99, making sure not to get 5-9 */
[class *= "d5"]:not([class $= "d5"]),
[class *= "d6"]:not([class $= "d6"]),
[class *= "d7"]:not([class $= "d7"]),
[class *= "d8"]:not([class $= "d8"]),
[class *= "d9"]:not([class $= "d9"])
{
width: 80px;
}

/* weed out 100-199, making sure not to get 1 or 10-19
NOTE: this becomes a highly specific selector
*/
[class *= "d1"]:not([class $= "d1"]):not([class $= "d10"]):not([class $= "d11"]):not([class $= "d12"]):not([class $= "d13"]):not([class $= "d14"]):not([class $= "d15"]):not([class $= "d16"]):not([class $= "d17"]):not([class $= "d18"]):not([class $= "d19"])
{
width: 120px;
}

/* weed out 150-199, making sure not to get 15-19
NOTE: because the previous selector is so specific, this one
needed the !important flag (which I hate to use, but here
seemed to be the best and only solution)
*/
[class *= "d15"]:not([class $= "d15"]),
[class *= "d16"]:not([class $= "d16"]),
[class *= "d17"]:not([class $= "d17"]),
[class *= "d18"]:not([class $= "d18"]),
[class *= "d19"]:not([class $= "d19"])
{
width: 150px !important;
}

/* weed out 200-299, making sure not to get 2 or 20-29
NOTE: again high specificity
*/
[class *= "d2"]:not([class $= "d2"]):not([class $= "d20"]):not([class $= "d21"]):not([class $= "d22"]):not([class $= "d23"]):not([class $= "d24"]):not([class $= "d25"]):not([class $= "d26"]):not([class $= "d27"]):not([class $= "d28"]):not([class $= "d29"])
{
width: 180px;
}

/* weed out 250-299, making sure not to get 25-29
NOTE: !important needed again;
also, anything 300+ reverts back to smallest size unless
one keeps going... maybe 999 could be reached "reasonably"
*/
[class *= "d25"]:not([class $= "d25"]),
[class *= "d26"]:not([class $= "d26"]),
[class *= "d27"]:not([class $= "d27"]),
[class *= "d28"]:not([class $= "d28"]),
[class *= "d29"]:not([class $= "d29"])
{
width: 210px !important;
}

css having a range after a class attribute

There is no such kind of css pseudo on what you wanted to achieve.

You can try to use SASS to achieve what you wanted.

and then use the @for Directive

SASS

@for $i from 1 through 3 {
.product#{$i} { width: 20px; }
}

CSS

.product1 {
width: 20px;
}

.product2 {
width: 20px;
}

.product3 {
width: 20px;
}

Also you can try to use LESS

Hope this helps

How can I change the css from elements of a range of data attributes?

At a minimum, you can combine them into a single selector:

$("td[data-row='2'][data-date='2018-04-03'],td[data-row='2'][data-date='2018-04-04']")
.css({ "background":"lightblue", "border-right-color":"lightblue" })

which you could then reduce with .filter()

$("td[data-row='2']").filter("[data-date='2018-04-03'],[data-date='2018-04-04']")
.css({ "background":"lightblue", "border-right-color":"lightblue" })

given that the range would not be fixed, you could build up the selector using a loop (to create a giant selector string) or you could loop through the values, eg:

var cells = $("td[data-row='2']");

var start = new Date("2018-05-28");
var end = new Date("2018-06-02");
var newend = end.setDate(end.getDate()+1);
var end = new Date(newend);
while(start < end){
var datadate = start.toISOString().split('.')[0]+"Z";

cells.filter("[data-date='" + datadate + "']").css({ "background":"lightblue", "border-right-color":"lightblue" })

var newDate = start.setDate(start.getDate() + 1);
start = new Date(newDate);
}

(loop source: Javascript - get array of dates between 2 dates)

The final option would be to apply a 'compare' within a filter, something like:

var start = new Date("2018-05-28");
var end = new Date("2018-06-02");

$("td[data-row='2']").filter(function() {
var thisdate = $(this).data("date");
return (thisdate > start && thisdate <= end);
}).css({"background":"lightblue", "border-right-color":"lightblue"})

As an aside, you'd be better off using a class rather than set css properties directly.

Is possible create a css class name with numbers from-to ?

There is nothing in pure CSS which will do this, but you could use JavaScript to create a stylesheet for you which has all that tedious repetition created automatically.

In this snippet you say what the ends of the class ranges are and what styling is to be put in each of the ranges.

If there is a range which you don't want to alter then you still need to include it but make its styles string just an empty string.

The snippet runs through each of the ranges creating the relevant style sheet entries and puts them in a style element in the head element of the document.

A few fairly random divs are shown here just to test that we are hitting the right ranges.

const rangeEnds = [4, 20, 35, 41, 48, 100];
const styles = ['color: pink;', 'color: red; background-color: black;', 'color: green;', 'color: yellow;', 'color: blue;', 'color: black; background: pink;'];

let lastRangeEnd = 0;
const styleEl = document.createElement('style');
for (let i = 0; i < rangeEnds.length; i++) {
for (let j = lastRangeEnd + 1; j < rangeEnds[i]; j++) {
styleEl.innerHTML += '.class-' + j + ',';
}
styleEl.innerHTML += '.class-' + rangeEnds[i] + '{' + styles[i] + '}';
lastRangeEnd = rangeEnds[i];
}
document.querySelector('head').append(styleEl);
<!doctype html>
<html>

<head>
<title>Classes</title>
</head>

<body>
<div class="class-1">ABCD</div>
<div class="class-19">ABCD</div>
<div class="class-21">ABCD</div>
<div class="class-40">ABCD</div>
<div class="class-41">ABCD</div>
<div class="class-48">ABCD</div>
<div class="class-100">ABCD</div>
</body>

Styling a CSS item depending on it's value

If you could set the percentages <100% to start with a 0 like 099% , You could use the attr starts with, and attr equals selector. Works in modern browsers and ie 7 +

 .progress[title^=1], .progress[title^=2] { background: red; } /* Starts with 1 or 2*/
.progress[title^=0], .progress[title=100%], { background: green; } /* Starts with 0 or is 100% */

Alternatively you could make a selector for all 200 odd variations you have , which is quite long winded

Apply different styles in component based on body tag classes/attributes

The following component CSS syntax appears to work:

body.pink :host p {
color: pink;
}

body.blue :host p {
color: blue;
}

See this stackblitz for a demo.

CSS attribute selectors taking precedence over normal CSS class selectors

I'd originally posted this as a comment, but perhaps I should've made it answer.


Let's look at the actual conditions of your two CSS rules:

div[class='example'] {color:green}
  • Element must be a <div>
  • Element must have class "example"
.example {color:blue}
  • Element must have class "example"

Because your first CSS rule has two conditions, whereas your second rule only has one, the first rule is more specific - therefore it will take precedence.

If you were to remove the div portion from your first rule, it would be considered equivalent (as MDN states), at which point the text would be blue.



Related Topics



Leave a reply



Submit