I'm using LESS CSS and I have the following situation. Can you suggest me if there is a way to further optimize LESS code?
As you can see, there are many objects sharing properties between them but each one has also its own specific customization.
Thank you
footer a
{
font-weight:bold;
&#acme,
&#email_footer,
&#browser_ok,
&#browser_old
{
display:inline-block;
position:relative;
white-space:nowrap;
background:url('footer_items.png') no-repeat;
text-align:left;
text-indent:-9999px;
border:none;
}
&#acme
{
width:130px;
height:25px;
top:1px;
background-position:-90px 0;
&:hover
{
background-position:-90px -25px;
}
&:active
{
top:0px;
}
}
&#email_footer,
&#browser_ok,
&#browser_old
{
width:38px;
height:31px;
top:-3px;
}
&#email_footer
{
background-position:-230px 0;
&:hover
{
background-position:-230px -31px;
}
&:active
{
top:-2px;
}
}
&#browser_ok,
&#browser_old
{
background-position:0 -2px;
&:active
{
top:-2px;
}
}
&#browser_ok
{
background-position:0 -2px;
&:hover
{
background-position:0 -35px;
}
}
&#browser_old
{
background-position:-45px -2px;
&:hover
{
background-position:-45px -35px;
}
}
}
Looks like you could still combine some things together. Specifically some of your :active code and some of the background-position info. In order to keep the newly combined :active after :hover, I moved the definition containing it below the extra definitions, which should not matter for your code. In all it reduced it by 7 lines of code.
footer a
{
font-weight:bold;
&#acme,
&#email_footer,
&#browser_ok,
&#browser_old
{
display:inline-block;
position:relative;
white-space:nowrap;
background:url('footer_items.png') no-repeat;
text-align:left;
text-indent:-9999px;
border:none;
}
&#acme
{
width:130px;
height:25px;
top:1px;
background-position:-90px 0;
&:hover
{
background-position:-90px -25px;
}
&:active
{
top:0px;
}
}
&#email_footer
{
background-position:-230px 0;
&:hover
{
background-position:-230px -31px;
}
}
&#browser_ok,
&#browser_old
{
background-position:0 -2px;
}
&#browser_ok
{
&:hover
{
background-position:0 -35px;
}
}
&#browser_old
{
background-position:-45px -2px;
&:hover
{
background-position:-45px -35px;
}
}
&#email_footer,
&#browser_ok,
&#browser_old
{
width:38px;
height:31px;
top:-3px;
&:active
{
top:-2px;
}
}
}
Related
How to double loop in LESS to generate a set of mixins such as:
.p_0_0 {
padding: 0rem 0rem;
}
.p_1_0 {
padding: 1rem 0rem;
}
.p_0_1 {
padding: 0rem 1rem;
}
.p_1_1 {
padding: 1rem 1rem;
}
It is better to use built-in tools...
Since LESS 3.x version LESS has each function, see more here. In this case, we can use this function to its fullest:
#steps: {
0: 0rem;
1: 1rem;
};
each(#steps, .(#valueX, #keyX, #indexX) {
each(#steps, .(#valueY, #keyY, #indexY) {
.p_#{keyY}_#{keyX} {
#{valueP}: #valueY #valueX;
}
})
})
Which generates:
.p_0_0 {
padding: 0rem 0rem;
}
.p_1_0 {
padding: 1rem 0rem;
}
.p_0_1 {
padding: 0rem 1rem;
}
.p_1_1 {
padding: 1rem 1rem;
}
I wanted to do some things with LESS but it's not working as I want.
I have this code :
.pl, #pl {
&-logo {
max-width: 100%;
height: auto;
&-test1:extend(.pl-logo) {
background-image: url('url');
}
&-test2:extend(.pl-logo) {
background-image: url('url');
}
&-test3:extend(.pl-logo) {
background-image: url('url');
}
}
}
But it's not working, I just have :
.pl-logo, #pl-logo {
max-width: 100%;
height: auto;
}
.pl-logo-test1, #pl-logo-test1 {
background-image: url('url');
}
.pl-logo-test2, #pl-logo-test2 {
background-image: url('url');
}
.pl-logo-test3, #pl-logo-test3 {
background-image: url('url');
}
Instead :
.pl-logo, .pl-logo-test1, .pl-logo-test2, .pl-logo-test3, #pl-logo {
max-width: 100%;
height: auto;
}
.pl-logo-test1, #pl-logo-test1 {
background-image: url('url');
}
.pl-logo-test2, #pl-logo-test2 {
background-image: url('url');
}
.pl-logo-test3, #pl-logo-test3 {
background-image: url('url');
}
I thought LESS more evolutive, is my code wrong or LESS does not compile correctly ?
Is there an other way to do what I want ?
Thank you
As already made clear by Harry, you can not extend dynamically formed selectors and How do I extend a class/mixin which has dynamically formed selector will provide you some solutions.
Alternatively you could try to change your HTML and use two classes the .pl-logo, #pl-logo base classes and the test* style classes:
< class="pl-logo test2">
Now you can use the following Less code:
.pl, #pl {
&-logo {
max-width: 100%;
height: auto;
&.test1 {
background-image: url('url');
}
&.test2 {
background-image: url('url');
}
&.test3 {
background-image: url('url');
}
}
}
Th above compiles into CSS as follows:
.pl-logo,
#pl-logo {
max-width: 100%;
height: auto;
}
.pl-logo.test1,
#pl-logo.test1 {
background-image: url('url');
}
.pl-logo.test2,
#pl-logo.test2 {
background-image: url('url');
}
.pl-logo.test3,
#pl-logo.test3 {
background-image: url('url');
}
In the above .pl-logo.test1 means having both the pl-logo and test1 classes. (#pl-logo.test1 having id=pl-logo and class=test1, see: How to combine class and ID in CSS selector?)
Or when you can not change your HTML use attribute selectors:
[class^="pl-logo-"], [class*=" pl-logo-"], [id^="pl-logo-"], [id*=" pl-logo-"] {
max-width: 100%;
height: auto;
}
.pl, #pl {
&-logo {
&.test1 {
background-image: url('url');
}
&.test2 {
background-image: url('url');
}
&.test3 {
background-image: url('url');
}
}
}
I am starting out with Less and one of the reasons I wanted to is because of the ligthen() function. So my first attempt was to do something with that.
This is my HTML
<div class="box blue">
<div class="boxbar">Foo</div>
blue
</div>
I finally got it working, but I doubt it's supposed be like this:
#blue: #468ACE;
#green: #41A53D;
#red: #9C2525;
#purple: #8938BF;
div
{
padding: 10px;
}
.blue {
background-color: #blue;
.boxbar { background-color: lighten(#blue, 10%); }
}
.green {
background-color: #green;
.boxbar { background-color: lighten(#green, 10%); }
}
.red {
background-color: #red;
.boxbar { background-color: lighten(#red, 10%); }
}
.purple {
background-color: #purple;
.boxbar { background-color: lighten(#purple, 10%); }
}
.boxbar
{
height: 10px;
}
How can I refactor this? Surely it must be easier to say "get your parent color, and lighten it a bit". I tried a couple of things: inherit (was worth a shot!), have the lightened versions inside .boxcar. But this obviously compiled to .boxcar .blue.. which is not what I want and I ended with what you can see here.. it works.. but it doesn't feel right. Then I would need to write code for every new color I introduce..
I am not completely sure what your desired solution would be ... but maybe something like making a mixin would help you from having to write so much stuff out.
LESS:
.bgmixin(#color) {
(~".#{color}") {
background-color: ##color;
.boxbar {
background-color: lighten(##color, 10%);
}
}
}
#blue: #468ACE;
#green: #41A53D;
#red: #9C2525;
.bgmixin("blue");
.bgmixin("green");
.bgmixin("red");
CSS:
.blue{
background-color: #468ace;
}
.blue .boxbar {
background-color: #6ea3d9;
}
.green{
background-color: #41a53d;
}
.green .boxbar {
background-color: #59c055;
}
.red{
background-color: #9c2525;
}
.red .boxbar{
background-color: #c52f2f;
}
Update:
In LESS>=1.4 you would want to use something like this to interpolate the class name from the color name:
.bgmixin(#color) {
#classname: ~"#{color}";
.#{classname} {
background-color: ##color;
.boxbar {
background-color: lighten(##color, 10%);
}
}
}
This is the mixin I wrote (.scss format), but I'm getting this error:
Invalid CSS after "($x) ": expected expression (e.g. 1px, bold), was "{"
#mixin x_cards_wide($x) {
.card {
&:nth-child(-n + $x) { margin-top: 0; }
&:nth-child($x * n) { margin-right: 0; }
}
}
Check it out on CodePen
You can accomplish this using interpolations:
#mixin x_cards_wide($x) {
.card {
&:nth-child(-n+#{$x}) { margin-top: 0; }
&:nth-child(#{$x}n) { margin-right: 0; }
}
}
I am using lessphp (latest from git)
Is it possible to call a mixin from another mixin in the same "namespace"?
Here is a short sample of code which produces no output (but should give a border to h1)
#test {
.mix() {
border: 1px solid #000000;
}
.mix2() {
.mix();
}
}
h1 {
#test > .mix2();
}
I got it to work by adding this:
#test {
.mix() {
border: 1px solid #000000;
}
.mix2() {
#test .mix();
}
}
h1 {
#test > .mix2();
}
Try:
#test {
...
.mix2() {
.mix;
}
}
h1 {
#test > .mix2;
}