LESS: concatenate multiple background rules - less

I have a mixin that creates a gradient with vendors' prefixes, and I would like to add this background to a DIV in addition to another background-image.
.horizontal(#start-color: #555; #end-color: #333; #start-percent: 0%; #end-percent: 100%) {
background:#start-color;
background-image: -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image+: linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
background-repeat: repeat-x;
}
.foo
{
background-image+:url('bg.png');
.horizontal;
}
I thought the solution could be use of comma merging, that in my example I added only to standard CSS3 gradient declaration. Doing this, here the generated CSS:
.foo {
background-image: url('bg.png'), linear-gradient(to right, #555555 0%, #333333 100%);
background: #555555;
background-image: -webkit-linear-gradient(left, #555555 0%, #333333 100%);
background-image: -o-linear-gradient(left, #555555 0%, #333333 100%);
background-repeat: repeat-x;
}
It's correct, but how to have this also for others vendors prefixes without losing flexibility of mixin? I tried to add + sign also on others "background-image: -webkit...." rules, but in this case, resulting CSS would be:
.foo {
background-image: url('bg.png'), -webkit-linear-gradient(left, #555555 0%, #333333 100%), -o-linear-gradient(left, #555555 0%, #333333 100%), linear-gradient(to right, #555555 0%, #333333 100%);
background: #555555;
background-repeat: repeat-x;
}
...obviously not correct... any suggestion?

Using Less for generating vendor prefixes (or related items) is not the best way to do it. It is much better to use the libraries like Prefix Free or Auto Prefixer etc.
Having said that, for your case I think using a separate parameter for the image would be the best option. The isurl() function returns true only if the input parameter is a URL.
The default value for the #image parameter is set to none because this is not a URL and will take care of the blank/null value handling.
.horizontal(#start-color: #555; #end-color: #333; #start-percent: 0%; #end-percent: 100%; #image: none) {
background:#start-color;
& when (isurl(#image)){
background-image: #image, -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #image, -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #image, linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
& when not (isurl(#image)){
background-image: -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
background-repeat: repeat-x;
}
.foo{
.horizontal(#image: url('bg.png'));
}
.foo2{
.horizontal(#image: 'bg.png');
}
In the above mixin, based on whether the value for the #image variable is a URL or not, the appropriate output would be generated.
In some cases, you may want to use a color (instead of/in addition to an image) in addition to the gradients and for that you can further enhance the mixin like below:
.horizontal(#start-color: #555; #end-color: #333; #start-percent: 0%; #end-percent: 100%; #image: none; #color: none) {
background:#start-color;
& when (isurl(#image)) and not (iscolor(#color)){
background-image: #image, -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #image, -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #image, linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
& when (iscolor(#color)) and not (isurl(#image)){
background-image: #color, -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #color, -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #color, linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
& when (isurl(#image)) and (iscolor(#color)){
background-image: #color, #image, -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #color, #image, -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: #color, #image, linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
& when not (isurl(#image)) and not (iscolor(#color)){
background-image: -webkit-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: -o-linear-gradient(left, #start-color #start-percent, #end-color #end-percent);
background-image: linear-gradient(to right, #start-color #start-percent, #end-color #end-percent);
}
background-repeat: repeat-x;
}
.foo{
.horizontal(#image: url('bg1.png'));
}
.foo2{
.horizontal(#image: 'bg.png');
}
.foo3{
.horizontal(#color: blue);
}
.foo3{
.horizontal(#color: red; #image: url('abc.gif'));
}
Note: I have used background-image property in the above sample but if we want use a solid color along with gradients and/or image, then the background property should be used instead.

Related

Apply rules to list of parent classes

I have the below LESS stylesheet and I know there has to be a better way to organize this. Is the only option to create a map containing the classes and a mixin perhaps to repeat the styles?
// child div is injected by JS
.ddemrcontent > span, .blocksmarttemplate > span, .blocktoken > span {
display: inline-flex;
align-items: center;
min-height: 1.7rem;
margin-top: 0.2rem;
padding-left: 0.2rem;
}
.ddfreetext {
display: flex;
min-height: 1.7rem;
margin-top: 0.2rem;
}
.ddemrcontent > span:hover, .blocksmarttemplate > span:hover, .blocktoken > span:hover {
text-decoration: underline;
cursor: pointer;
}
.ddemrcontent > span {
border-left: 4px solid cadetblue;
}
.blocksmarttemplate > span {
border-left: 4px solid burlywood;
}
.blocktoken > span {
border-left: 4px solid #8a7090;
}
.ddfreetext {
border: 1px dashed black;
}
UPDATE
Here is the best I've been able to come up with. Since the & parent selector won't apply to each distinct parent selector (that are comma delimited) I think I am forced to use a mixin and call it to apply the rules for each parent I have.
Would love to hear if there's still a better way.
.dyndoccontent(#color) {
& > span {
display: inline-flex;
align-items: center;
min-height: 1.7rem;
margin-top: 0.2rem;
padding-left: 0.2rem;
border-left: 4px solid #color;
&:hover {
text-decoration: underline;
cursor: pointer;
}
}
}
// child div is injected by JS
.ddemrcontent {
.dyndoccontent(cadetblue);
}
.blocksmarttemplate {
.dyndoccontent(burlywood);
}
.blocktoken {
.dyndoccontent(#8a7090);
}
.ddfreetext {
display: flex;
min-height: 1.7rem;
margin-top: 0.2rem;
border: 1px dashed black;
}
I would definitely recommend mixin if you have multiple parts in your less files which use the same styles.
For you example i would go for a more nested way:
// child div is injected by JS
.ddemrcontent, .blocksmarttemplate, .blocktoken {
& > span {
display: inline-flex;
align-items: center;
min-height: 1.7rem;
margin-top: 0.2rem;
padding-left: 0.2rem;
&:hover {
text-decoration: underline;
cursor: pointer;
}
}
}
.ddfreetext {
border: 1px dashed black;
display: flex;
min-height: 1.7rem;
margin-top: 0.2rem;
}
.ddemrcontent > span {
border-left: 4px solid cadetblue;
}
.blocksmarttemplate > span {
border-left: 4px solid burlywood;
}
.blocktoken > span {
border-left: 4px solid #8a7090;
}

Less multiple parent usage

There is a something i've wondered. I am using less my project and i wonder is it possible to do something like;
i want to do like this css result below;
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-submenu:hover > a,
.dropdown-submenu:focus > a {
text-decoration: none;
color: #ffffff;
background-color: #3DA857;
background-image: -moz-linear-gradient(top, #3DA857, #3DA857);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3DA857), to(#3DA857));
background-image: -webkit-linear-gradient(top, #3DA857, #3DA857);
background-image: -o-linear-gradient(top, #3DA857, #3DA857);
background-image: linear-gradient(to bottom, #3DA857, #3DA857);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
i used like this with less
.menuFocusHover(#fontColor, #bgColor) {
text-decoration: none;
color: #fontColor;
background-color: #bgColor;
background-image: -moz-linear-gradient(top, #bgColor, #bgColor);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#bgColor), to(#bgColor));
background-image: -webkit-linear-gradient(top, #bgColor, #bgColor);
background-image: -o-linear-gradient(top, #bgColor, #bgColor);
background-image: linear-gradient(to bottom, #bgColor, #bgColor);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
.dropdown-menu{
& > li {
> a {
&:hover, &:focus {
.menuFocusHover(#white,#baseColor);
}
}
}
}
.dropdown-submenu {
&:hover, &:focus {
> a {
.menuFocusHover(#white,#baseColor);
}
}
}
but result is;
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
text-decoration: none;
color: #ffffff;
background-color: #3da857;
background-image: -moz-linear-gradient(top, #3da857, #3da857);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3da857), to(#3da857));
background-image: -webkit-linear-gradient(top, #3da857, #3da857);
background-image: -o-linear-gradient(top, #3da857, #3da857);
background-image: linear-gradient(to bottom, #3da857, #3da857);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
.dropdown-submenu:hover > a,
.dropdown-submenu:focus > a {
text-decoration: none;
color: #ffffff;
background-color: #3da857;
background-image: -moz-linear-gradient(top, #3da857, #3da857);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3da857), to(#3da857));
background-image: -webkit-linear-gradient(top, #3da857, #3da857);
background-image: -o-linear-gradient(top, #3da857, #3da857);
background-image: linear-gradient(to bottom, #3da857, #3da857);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
How can i do as i want with less ?
You don't have to use a parent reference for .dropdown-menu{ & > li and you could also wonder why you nest the .dropdown > li > a selector.
But beside the above you could solve your question by using the extend feature:
#white: white;
#baseColor: blue;
.menuFocusHover(#fontColor, #bgColor) {
text-decoration: none;
color: #fontColor;
background-color: #bgColor;
background-image: linear-gradient(to bottom, #bgColor, #bgColor);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
.dropdown-menu{
> li {
> a {
&:hover, &:focus {
.menuFocusHover(#white,#baseColor);
}
}
}
}
.dropdown-submenu {
&:hover, &:focus {
> a {
&:extend(.dropdown-menu > li > a:hover);
}
}
}
Compiles into the CSS code like that shown beneath:
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-submenu:hover > a,
.dropdown-submenu:focus > a {
text-decoration: none;
color: white;
background-color: blue;
background-image: linear-gradient(to bottom, blue, blue);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3DA857', endColorstr='#3DA857', GradientType=0);
}
You can read more about this kind of stuff at: https://github.com/less/less.js/issues/1075 and finally you should consider to not prefix your properties, but use the autoprefixer instead, see also: LESS transition mixin with prefixes

Bootstrap 3 navbar and collapse menu different background colors?

I would like to have the Navbar background be a different color than the background of the collapsed menu.
I believe I found an answer to this, but would appreciate any further comments or alternate solutions, as this seems to be a bit hacky...
.navbar {background-color: #8e181b;}
.navbar-default .navbar-nav > li > a, .navbar-default .navbar-brand {color: #f1f1f1;}
.navbar-default .navbar-nav > li > a:hover,
.navbar-default .navbar-nav > li > a:focus {color: #f1f1f1; background-color: #b27677;}
#media only screen and (max-width: 766px) {
.collapsing, .in {background-color: #f7f7f7;}
.collapsing ul li a, .in ul li a {color: #555!important;}
.collapsing ul li a:hover, .in ul li a:hover {color: #f1f1f1!important;}
}
Here is the jsfiddle: http://jsfiddle.net/vp7XS/
You can do it like this
.navbar-default {
border-color: white;
background-color: #FF2032;
}
#media only screen and (max-width: 768px) {
.navbar-default .navbar-collapse {
border-color: white;
background-color: #e87373;
}
}
check this fiddle , i hope it answers your question

Working with Less: avoiding tree inheritance

When I want to write something like
.security-list ul {
list-style: none;
margin-left: 0;
}
.security-list ul li {
padding: 10px 9px;
display: inline-block;
}
.security-list ul li a {
width: 234px;
color: #000;
text-decoration: none;
display: inline-block;
background-image: url(http://domain.com/infopage-icons.png);
background-position: 200px 0;
background-repeat: no-repeat;
}
.security-list ul li a.basket,
.security-content h3.basket {
background-position: 200px 0;
}
.security-list ul li a.creditcard,
.security-content h3.creditcard {
background-position: 200px -205px;
}
I end up writting:
.security-list ul {
list-style: none;
margin-left: 0;
li {
padding: 10px 9px;
display: inline-block;
a {
width: 234px;
color: #000;
text-decoration: none;
display: inline-block;
background-image: url(http://domain.com/infopage-icons.png);
background-position: 200px 0;
background-repeat: no-repeat;
&.basket,
.security-content h3.basket {
background-position: 200px 0;
}
&.creditcard,
.security-content h3.creditcard {
background-position: 200px -205px;
}
}
}
but the problem I have is this will compile the last 2 blocks as
.security-list ul li a.basket,
.security-list ul li a .security-content h3.basket { ... }
.security-list ul li a.creditcard,
.security-list ul li a .security-content h3.creditcard { ... }
where what I really want is:
.security-list ul li a.basket,
.security-content h3.basket{ ... }
.security-list ul li a.creditcard,
.security-content h3.creditcard { ... }
What can I do in LESS that he knows that I do not want to inherit the hole tree, but still not repeat myself on the same style rule, in other words, don't create 2 rules with the same content...
Your problem is that you want to ignore the nest inside a nest, which is not (at least currently) possible. If it did work, it also would make for challenging code to read, as you would not expect a non-nesting item to be defined inside a nest.
I think one elegant solution to this, especially in your case, is to abstract the nest even further. This code gets close to what you desire by locating it all within a .security nest:
.security {
&-list ul {
list-style: none;
margin-left: 0;
li {
padding: 10px 9px;
display: inline-block;
a {
width: 234px;
color: #000;
text-decoration: none;
display: inline-block;
background-image: url(http://domain.com/infopage-icons.png);
background-position: 200px 0;
background-repeat: no-repeat;
}
}
}
&-list ul li a,
&-content h3 {
&.basket {
background-position: 200px 0;
}
&.creditcard {
background-position: 200px -205px;
}
}
}
The above disaccociates the call from the deep nesting in the list, which does require a small repetition of code in the ul li a call, but it produces this CSS:
.security-list ul {
list-style: none;
margin-left: 0;
}
.security-list ul li {
padding: 10px 9px;
display: inline-block;
}
.security-list ul li a {
width: 234px;
color: #000;
text-decoration: none;
display: inline-block;
background-image: url(http://domain.com/infopage-icons.png);
background-position: 200px 0;
background-repeat: no-repeat;
}
.security-list ul li a.basket,
.security-content h3.basket {
background-position: 200px 0;
}
.security-list ul li a.creditcard,
.security-content h3.creditcard {
background-position: 200px -205px;
}
Assuming the .security-list class is only used on a container that holds a true list (like a ul), then if you are able to remove the background-position from the straight security-list ul li a selector, you can then reduce the selector of the .basket and .creditcard by removing the ul li porition of that to make it just .security-list a.basket, etc. This would reduce the selector nesting bloat on that call.

Highlighting the selected row in a ComponentView?

I'm working with this ComponentView example:
Kitten ComponentView
In my variation, I'd like to highlight the selected row when the user taps on it, as would happen in an xtype: 'list'. How can I accomplish this?
You can achieve this by using an tpl property and then set the class of the css inside the <div> tag
Something like this,
....
xtype: 'list',
tpl: '<div class="clickedItem"> ...'
....
and then write your css code as,
.clickedItem{
background: // some color value;
text-shadow: // some color value;
}
After examining the Sencha Kiva example in their examples directory,
it looks like it's a combination of the .x-dataview-UI_NAME class with .x-list-item, where UI_NAME is defined is the dataview view config. In the Kiva example, it's the line 'ui: loans'.
So, the CSS section looks something like this:
.x-dataview-loans .x-list-item {
...
}
Defining the UI suffix in the view:
Ext.define('Kiva.view.LoansList', {
extend: 'Ext.DataView',
xtype : 'loanslist',
requires: [
'Kiva.view.LoansListItem'
],
config: {
ui : 'loans',
store: 'Loans',
useComponents: true,
defaultType: 'loanslistitem',
deselectOnContainerClick: false
},
onItemTap: function(container, target, index, e) {
var me = this;
me.callParent(arguments); // WARNING: without this call, the row will not become selected
}
The relevant code in application.css
.x-dataview-loans .x-img {
margin-right: 1em;
background-position: center center;
width: 60px;
height: 60px
}
.x-dataview-loans .x-list-item {
padding: 1em;
border-bottom: 1px solid #e1e1e1;
-webkit-transition: linear .2s background
}
.x-dataview-loans .x-list-item .name div {
font-weight: bold
}
.x-dataview-loans .x-item-selected {
background: #fff
}
.x-dataview-loans .completion {
display: -webkit-box;
display: box;
-webkit-box-align: center;
box-align: center
}
.x-dataview-loans .completion .x-innerhtml {
display: -webkit-box;
display: box;
-webkit-box-align: stretch;
box-align: stretch;
height: 1em;
width: 100%;
border: 1px solid #bbb;
-webkit-box-shadow: inset 0 0 1px #fff;
padding: 1px;
-webkit-border-radius: 1em;
border-radius: 1em;
background-color: #e2e2e2;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c9c9c9), color-stop(10%, #d5d5d5), color-stop(65%, #e2e2e2), color-stop(100%, #e3e3e3));
background-image: -webkit-linear-gradient(#c9c9c9, #d5d5d5 10%, #e2e2e2 65%, #e3e3e3);
background-image: linear-gradient(#c9c9c9, #d5d5d5 10%, #e2e2e2 65%, #e3e3e3)
}
.x-dataview-loans .completion .x-innerhtml .bar {
min-width: 1em;
border: 1px solid #4b9123;
-webkit-border-radius: 1em;
border-radius: 1em;
background-color: #74b446;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #c6e1b2), color-stop(2%, #87c05e), color-stop(100%, #639a3c));
background-image: -webkit-linear-gradient(#c6e1b2, #87c05e 2%, #639a3c);
background-image: linear-gradient(#c6e1b2, #87c05e 2%, #639a3c)
}