qrikko
qrikko

Reputation: 2603

dynamic or adaptable class in css

I have a problem where I will be displaying a variable number of items displayed, and they will have a margin setting which is updated uniformly over the set.

So basically to put it simple if I have a set that is [1,2,3,4,5] it might be something like:

1        2        3        4        5

while if the number of number were to double they would require the same amount of space:

1   2   3   4   5   6   7   8   9   10

I have some solutions for this but what hit me was that if I have an css-class (as the margin is uniform over the given set) I could share the layout. So I would have liked it if it were possible to update the class dynamically if that makes sense I haven't found any information of that being possible to do, so if we assume that in the first example the margin is something like margin-right: 10px; then if I could change the class, (similar to how I set style on an element I guess is how I am thinking, but for the whole class), it would be really smooth. So let's assume a functionality to do this I could have a class:

.myclass {
    margin-right: 10px;
}

and through our magic function .myclass.setProperty('margin-right', '5px'); (or whatever the syntax would be :P). It would act as if i had defined the class:

.myclass {
    margin-right: 5px;
}

I hope that is enough to grasp my ideas and problem thus far. The way I am going about it at the moment is that I use a class for all shared behavior and set style for each element. However this is a bit tedious as it become something like:

for (var i in mynumbers) {
    mynumbers.style.marginRight = new_margin;
}

Where new_margin is calculated based on a scale (i.e. it could change many times in a short period of time).

So to the question-part. Is there perhaps a way to achieve something like the first part (a way to dynamically change a class), or any thoughts or ideas how to implement it if the way I am doing it feels like a bad idea or if you feel there are better ways of handling this.

Thanks for reading and hope you find the problem interesting.

Upvotes: 2

Views: 72

Answers (3)

Leo
Leo

Reputation: 13838

Ah, just another typical use case of flex layout:

.container {
  display: flex;
  border: 1px solid;
  justify-content: space-between;
}
<h2>5 elements in a line with equal width gaps</h2>
<div class="container">
  <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
</div>

<h2>10 elements in a line with equal width gaps</h2>
<div class="container">
  <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
  <span>6</span><span>7</span><span>8</span><span>9</span><span>10</span>
</div>

If your browser supports the feature, you would see something like this: enter image description here

Here for browser compatibility.

EDIT: another interesting use case, although OP didn't ask about:

.container {
  display: flex;
  border: 1px solid;
  justify-content: space-between;
}
.container:before, .container:after {
  content: '';
  width: 0;
}
<h2>5 elements in a line with equal width gaps</h2>
<div class="container">
  <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
</div>

<h2>10 elements in a line with equal width gaps</h2>
<div class="container">
  <span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
  <span>6</span><span>7</span><span>8</span><span>9</span><span>10</span>
</div>

If your browser supports the feature, you would see something like this: enter image description here

Space is divided equally not only between elements, but also include both ends of the container. And you could see how simple the code is!

Upvotes: 2

dbcb
dbcb

Reputation: 898

Yes. This is possible. One thing to be aware of is that changing a class's property may cause the browser's renderer to recalculate the entire page's layout (it needs to figure out how your class change affects the overall layout). So if you plan on changing your margin-right in a way to animate the change, it's not going to perform very well depending on the complexity of your page. That said, here is a quick and dirty implementation that should work on everything IE9+:

<html>
<head>
<style>
.thing {
    display: inline-block;
    width: 20px;
    height: 20px;
    background: #f00;
}
</style>
</head>
<body>
<div>
    <div class="thing myClass"></div>
    <div class="thing myClass"></div>
    <div class="thing myClass"></div>
    <div class="thing myClass"></div>
    <div class="thing myClass"></div>
    <div class="thing myClass"></div>
</div>

<div>
<button id="doit">Make bigger</button>
</div>
</body>
<script>
var styleTag = document.createElement("style"),
    styleSheet, index, cssRule, style;

// Create a <style> tag that will hold our CSS rule
document.head.appendChild(styleTag);
styleSheet = styleTag.sheet;

// Insert an empty .myClass rule into the style sheet
index = styleSheet.insertRule(".myClass {}", styleSheet.cssRules.length);

// Get the 'style' object from the rule. This is nearly identical to elem.style
cssRule = styleSheet.cssRules[index];
style = cssRule.style;

// Sets .myClass { margin-right: 5px; }
style.marginRight = "5px";

// Demo to show that it works when you click a button
document.querySelector("#doit").addEventListener("click", function() {
    style.marginRight = "20px";
});

</script>
</html>

Upvotes: 0

Wex
Wex

Reputation: 15695

This sounds like a job for table-layout: fixed. Your browser computes the width of each "column" (element) in the first "table-row" based on the number of columns in the "table".

.table {
    display: table;
    table-layout: fixed;
    width: 100%;
}

.table > span {
    display: table-cell;
    text-align: center;
}
<div class="table">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
    <span>6</span>
    <span>7</span>
    <span>8</span>
    <span>9</span>
</div>

<div class="table">
    <span>1</span>
    <span>2</span>
    <span>3</span>
    <span>4</span>
    <span>5</span>
</div>

Upvotes: 0

Related Questions