Yes, structuring the mixins like that provided in question is a bit inefficient because of common styles having to be repeated across multiple mixins.
There are a few ways to avoid the repetition and they are provided below.
Method 1 (Using Guards):
As you can see here, the common properties are specified only once within the parent mixin and the properties that are dependent on the size alone are provided within the guards. The con of this method is that when the size has a value outside of the list of supported values the mixin outputs nothing from the guarded area and does not throw any warnings also. This is because Less compiler silently skips the guarded area when no match is found and can be problematic when the end user knows nothing about the Less code.
.my-button-large {
.btn(@font: "Arial");
}
.my-button-medium {
.btn(@bg: #000, @font: "Calibri", @size: "medium");
}
.my-button-small {
.btn(@bg: #777, @font: "Verdana", @size: "small");
}
.btn(@bg: #FFF, @font: "", @color: #000, @size: "large"){
background-color: @bg;
font-family: @font;
color: @color;
& when (@size = "large"){
font-size: 24px;
padding: 12px;
line-height: 24px;
}
& when (@size = "medium"){
font-size: 18px;
padding: 8px;
line-height: 18px;
}
& when (@size = "small"){
font-size: 12px;
padding: 4px;
line-height: 12px;
}
}
Method 2 (Using Pattern Matching):
This is an alternate method where an error would be thrown during compilation if the value provided by the user is outside of the list of allowed values. This is because we are making use of the pattern matching to act as a switch.
.my-button-large {
.btn(@font: "Arial");
}
.my-button-medium {
.btn(@bg: #000, @font: "Calibri", @size: "medium");
}
.my-button-small {
.btn(@bg: #777, @font: "Verdana", @size: "small");
}
.btn(@bg: #FFF, @font: "", @color: #000, @size: "large"){
background-color: @bg;
font-family: @font;
color: @color;
.bg-size(@size);
}
.bg-size("large"){
font-size: 24px;
padding: 12px;
line-height: 24px;
}
.bg-size("medium"){
font-size: 18px;
padding: 8px;
line-height: 18px;
}
.bg-size("small"){
font-size: 12px;
padding: 4px;
line-height: 12px;
}