3

I have the following piece of less:

@image-ui-wave-width: 28px;

[...]
.wave {
    &.saw {
        background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
    }
    &.triangle {
        background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
    }
}
[...]

Now, how can I add the rule that if any of those .wave elements also have the class .selected, the x value of background position must remain the same but the y value must be doubled?

2 Answers 2

2

Option 1: (Has better browser support)

Less cannot pick up the value from a prior defined property and do any math operations on it. Due to this we have to manually calculate and assign the value to the property. Since you are already making use of variables, the code change should really be simple (given below):

@image-ui-wave-width: 28px;
@image-ui-tab-height: 28px;
.wave {
  &.saw {
    background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
    &.selected{
      background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height * 2;
    }
  }
  &.triangle {
    background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
    &.selected{
      background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height * 2;
    }        
  }
}

That could be compressed further by using loops and an @index variable (if the X value increases by the same factor for each item).

Below is an implementation of how that would work out. As you can see, all the 4 div elements have a gradient background image where the first 28px is taken by one color and the other 28px is taken by the rest.

For those without the selected class, the second color from the gradient gets displayed (because the Y position is -28px) and for those with the selected class, the first color from the gradient is displayed (because Y position is -56px and gradients by default get repeated).

.wave.saw {
  background-position: -56px -28px;
}
.wave.saw.selected {
  background-position: -56px -56px;
}
.wave.triangle {
  background-position: -84px -28px;
}
.wave.triangle.selected {
  background-position: -84px -56px;
}
.wave.saw {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, red 50%, green 50%);
  background-size: 56px 56px;
}
.wave.triangle {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, yellow 50%, orange 50%);
  background-size: 56px 56px;
}
div {
  margin-bottom: 20px;
}
<div class='wave saw'></div>

<div class='wave saw selected'></div>

<hr>

<div class='wave triangle'></div>

<div class='wave triangle selected'></div>


Option 2: (Poorer browser support - Browser Compatibility chart is available here)

Another thing that we could do now with the Level 4 Background and Borders Standard is to split the whole background-position into x and y parts so that the x position won't have to be repeated. This was originally removed from CSS3 spec but seems to be available now as mentioned here.

@image-ui-wave-width: 28px;
@image-ui-tab-height: 28px;

.wave {
    &.saw {
        background-position: -@image-ui-tab-height * 2 -@image-ui-tab-height;
        &.selected{
            background-position-y:  -@image-ui-tab-height * 2;
        }
    }
    &.triangle {
        background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height;
        &.selected{
            background-position-y: -@image-ui-tab-height * 2;
        }        
    }
}

Below is the implementation for this approach where we override only the background-position-y value with a more specific selector:

.wave.saw {
  background-position: -56px -28px;
}
.wave.saw.selected {
  background-position-y: -56px;
}
.wave.triangle {
  background-position: -84px -28px;
}
.wave.triangle.selected {
  background-position-y: -56px;
}
.wave.saw {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, red 50%, green 50%);
  background-size: 56px 56px;
}
.wave.triangle {
  width: 56px;
  height: 28px;
  background-image: linear-gradient(to bottom, yellow 50%, orange 50%);
  background-size: 56px 56px;
}
div {
  margin-bottom: 20px;
}
<div class='wave saw'></div>

<div class='wave saw selected'></div>

<hr>

<div class='wave triangle'></div>

<div class='wave triangle selected'></div>

Sign up to request clarification or add additional context in comments.

3 Comments

Seems like firefox is the only major browser not supporting this?
Yeah @Persijn I tried it in Chrome and it seems to work even in older versions (v38).
was recommended in css3 a long while, but got rejected. Its assumed it was rejected so the css3 did not get delayed any longer.
2

Could this not be solved with adding another class (.selected) to the .wave selector?

.wave {
    [yourcode]
}
.wave.selected {
    &.saw {
        background-position: -@image-ui-tag-height * 2 -@image-ui-tab-height * 2;
    }
    &.triangle {
     background-position: -@image-ui-tab-height * 3 -@image-ui-tab-height * 2;
    }
}

Note
The .wave.selected must come after the .wave selector because the last one will override the css properties.

1 Comment

Shure, but the idea was to avoid having to write the x position again

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.