Alter CSS applied by LESS Mixin when body class is present? - less

I have a LESS mixin. When I apply this to an element I want it be styled slightly differently if a body class is present.
This:
.mixin() {
font-weight: bold;
color: red;
}
.element {
.mixin()
}
Outputs to this:
.element {
font-weight: bold;
color: red;
}
But I also want this to be outputted:
.body-class .element {
color: blue;
}

You can define your mixin this way:
.mixin() {
font-weight: bold;
color: red;
.body-class & {
color: blue;
}
}

Related

Generate rules via LESS plugin

I'd like to write a plugin that can generate a LESS function named alt that can do the following transformation:
.button {
background-color: alt(red, blue);
color: alt(black, white);
}
And output the following:
.button {
background-color: red;
color: black;
body.alt & {
background-color: blue;
color: white;
}
}
There doesn't seem to be much documentation about writing LESS plugins on the site, so hoping someone can provide an example of how this might be written :) Thanks!
I think a mixin would be best for this. Something like the following LESS:
.alt(#property, #primary-color, #alternate-color) {
#{property}: #primary-color;
body.alt & {
#{property}: #alternate-color;
}
}
.button {
.alt(background-color, red, blue);
.alt(color, black, white);
}
Which will compile to the following CSS:
.button {
background-color: red;
color: black;
}
body.alt .button {
background-color: blue;
}
body.alt .button {
color: white;
}

Less: class then node type

I have two <p> and one <button> that extend a certain class named test. I want to know if it is possible to add certain style rules to .test and then specific rules for the element type?
I thought of something like this:
.test {
font-weight: bold;
color: blue;
&p {
font-size: 26px;
}
&button {
font-size: 20px;
}
}
I know it is impossible to write it like that. This example is only for a concept example.
I've read the documentation and alas i found nothing...
Any idea or is this just impossible to achieve?
If I understand correctly you should use :extend:
LESS:
.test {
font-weight: bold;
color: blue;
}
p:extend(.test) {
font-size: 26px;
}
button:extend(.test){
font-size: 20px;
}
Output:
.test, p, button {
font-weight: bold;
color: blue;
}
p {
font-size: 26px;
}
button {
font-size: 20px;
}

Dynamically class in mixin

I have the following definition:
.f-color {
.a {color: #000000;}
.b {color: #ffffff;}
}
.f-type {
._36 {
font-family: Arial;
font-size: 36px;
}
._24 {
font-family: Arial;
font-size: 24px;
}
}
I want to create mixin that will look like this:
.a_36 {
color: #000000;
font-family: #font-omnes-light;
font-size: 36px;
}
I tried the following function:
.buildForColor(a);
.buildForColor(b);
.buildForColor(#c){
.#{c}_36 {
.f-color > .#{c};
.f-type > ._36;
}
}
But I'm getting an error with the line: .f-color > .#{c};
How can I pass the letter "a" so it will look like: .f-color > .a;
Thanks in advance
I found other way to define it:
In variables.less I defined:
#main_color_a: #000000;
#main_color_b: #ffffff;
Then in the mixin.less I defined:
.f-type {
._36 {
font-family: Arial;
font-size: 36px;
}
._24 {
font-family: Arial;
font-size: 24px;
}
}
.buildForColor(a);
.buildForColor(b);
.buildForColor(#c){
.#{c}_36 {
color: ~"#{main_color_#{c}}";
.f-type > ._36;
}
}
The compiled css looks like this:
.a_36 {
color: #000000;
font-family: Arial;
font-size: 36px;
}
.b_36 {
color: #ffffff;
font-family: Arial;
font-size: 36px;
}

Using guards in the mixin

I want to create a clever mixin for Bootstrap sources (mixin->buttons.less).
What I have is as follows:
Less:
.button-variant(#color; #background; #border) {
color: #color;
background-color: #background;
border-color: #border;
/* this variables must be used when I have parent's class="invert"*/
color: #background;
background: #color;
border-color: #background;
/* end */
/*when not - use variables in the beggining of mixin */
}
How I see using this mixin
.btn-primary,
.btn-primary-invert{
.button-variant(#btn-primary-color; #btn-primary-bg; #btn-primary-border);
}
Can I do something like I want? I understand that it could be done with Less guards, but don't understand how to use it. Have anybody some ideas?
The simplest approach would be to make use of the parent selector (&) like in the below snippet and forget using guards. Here the mixin by default produces both the normal and inverted state for all buttons. You can use this if you want both states to be applicable for all buttons.
.button-variant(#color; #background; #border) {
&{
&:hover, &:active{
color: #color;
background-color: #background;
border-color: #border;
}
}
&-invert{
&:hover, &:active{
color: #background;
background: #color;
border-color: #background;
}
}
}
.button-primary{
.button-variant(#000; #fff; #777);
}
The above snippet when compiled would result in the following CSS:
.button-primary:hover,
.button-primary:active {
color: #000000;
background-color: #ffffff;
border-color: #777777;
}
.button-primary-invert:hover,
.button-primary-invert:active {
color: #ffffff;
background: #000000;
border-color: #ffffff;
}
If you really want to use guards for whatever preferences (like you don't want either of the states for a specific button), then you could use a snippet like the below. For using guards, you need to send an extra parameter which indicates the type based on which the guard can be verified.
.button-variant(#color; #background; #border; #type:normal) {
& when (#type = normal){
color: #color;
background-color: #background;
border-color: #border;
}
& when (#type = invert){
color: #background;
background: #color;
border-color: #background;
}
}
.button-primary{
.button-variant(#000; #fff; #777);
}
.button-primary-invert{
.button-variant(#000; #fff; #777; invert);
}

Alter LESS Mixin when body class is present?

I have a LESS mixin. When a certain body class is present I want to alter one value of the mixin.
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element {
.my-style;
}
.body-class .element {
.my-style-altered;
}
This is working fine. However my list of selectors is getting longer:
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element,
.element-2,
.element-3 {
.my-style;
}
.body-class .element,
.body-class .element-2,
.body-class .element-3 {
.my-style-altered;
}
Is there a smarter way of writing my list of selectors so I dont have to repeat them twice? Ideally I would write them once, and for all of them my-style-altered() would be also applied if .body-class is present.
Method 1: (Using different mixins for the base version and the body-class specific version)
Yes, you could avoid having to write all the selectors multiple times by nesting the .body-class * variants of the selector within the generic one and appending the parent selector like in the below snippet. When this code is compiled, Less compiler will automatically replace the & with each one of the parent selectors.
.my-style() {
font-weight: bold;
color: red;
}
.my-style-altered() {
color: blue;
}
.element, .element-2, .element-3 {
.my-style;
.body-class &{
.my-style-altered;
}
}
Compiled CSS:
.element, .element-2, .element-3 {
font-weight: bold;
color: red;
}
.body-class .element,
.body-class .element-2,
.body-class .element-3 {
color: blue;
}
Method 2: (Using same mixin for the base version and the body-class specific version)
Alternately, if you wish to avoid having to use two different mixins and output both the content (the default one and the .body-class * variant) through the same mixin, it can be done like below:
.mixin() {
font-weight: bold;
color: red;
.body-class &{
color: blue;
}
}
.element, .element-2 {
.mixin()
}