Less > Define variable on constant - variables

I have the following button mixin:
.Button(#type) {
color: #White;
&:hover {color: #White;} // :hover
} // Button
.Button(#type) when (#type = 'Delete') {
background-color: lighten(#Red, 20%);
border: 1px solid lighten(#Red, 20%);
&:hover {
background-color: lighten(#Red, 12%);
border: 1px solid lighten(#Red, 12%);
} // :hover
} // Button
.Button(#type) when (#type = 'Search') {
background-color: lighten(#Blue, 20%);
border: 1px solid lighten(#Blue, 20%);
&:hover {
background-color: lighten(#Blue, 12%);
border: 1px solid lighten(#Blue, 12%);
} // :hover
} // Button
This is working fine and, as you can see, what changes in each button is the color.
If it possible to have only one Mixin and according to the type define a color variable.
This way I wouldn't need to use so many Button mixin versions ...

There is no other way to do that. Guarded mixins in LESS is fixed to you use that format instead of if/else statements. But in your case, I suggest to do this :
//create a mixin for global rules.
.rules(#color){
background-color: lighten(#color, 20%);
border: 1px solid lighten(#color, 20%);
&:hover {
background-color: lighten(#color, 12%);
border: 1px solid lighten(#color, 12%);
}
}
And you just only to call .rules mixin to every your css rules.
.Button(#type) when (#type = 'Delete') {
.rules(#Red);
}
.Button(#type) when (#type = 'Search') {
.rules(#Blue);
}
This is simpler and no need a lot of space to write the same code. Hope this helps.

Yes, It Can Be Done
It can be folded into a single mixin that uses the #type to switch color values with a creative use of variable variables.
LESS
#White: #fff;
#Red: #f00;
#Blue: #00f;
.Button(#type) {
//define the variables with the name
//of the button you want to pass: Delete, Search, etc.
//associated to the color variable you desire
#Delete: #Red;
#Search: #Blue;
//set up a generic variable name to use, and
//then call the color value through a variable variable call (##)
#ContrastColor: ##type;
color: #White;
background-color: lighten(#ContrastColor, 20%);
border: 1px solid lighten(#ContrastColor, 20%);
&:hover {
color: #White;
background-color: lighten(#ContrastColor, 12%);
border: 1px solid lighten(#ContrastColor, 12%);
} // :hover
} // Button
.deleteClass {
.Button(Delete);
}
.searchClass {
.Button(Search);
}
CSS Output
.deleteClass {
color: #ffffff;
background-color: #ff6666;
border: 1px solid #ff6666;
}
.deleteClass:hover {
color: #ffffff;
background-color: #ff3d3d;
border: 1px solid #ff3d3d;
}
.searchClass {
color: #ffffff;
background-color: #6666ff;
border: 1px solid #6666ff;
}
.searchClass:hover {
color: #ffffff;
background-color: #3d3dff;
border: 1px solid #3d3dff;
}

Related

Why is my computed method running both server and client side?

I'm making a Universal Application with Nuxt and Vue.js and I noticed that my button was having some weird behaviour, it changed class after the page was loaded, and since it has a transition it became quite annoying.
I set the class of the button with a computed method. So I tried putting a console.log in the computed method, and then I saw that it called both server-side and client-side? How is this possible? Is there anything that I need to do so that the method will only be called server-side?
<template>
<a :href="link" :class="themeClass">
<slot />
</a>
</template>
<script>
export default {
props: {
link:{
type:String,
default: '',
},
theme:
{
type:String,
default: 'primary',
validator: (value) => ['secondary', 'tertiary'].includes(value),
},
inverted:{
type:Boolean,
default: false,
},
},
computed:{
themeClass: function()
{
console.log("set style");
let invertedStyle = this.inverted ? '-inverted' : '';
return 'butt ' + this.theme + invertedStyle;
}
}
}
</script>
<style lang="scss" scoped>
.butt{
box-sizing: border-box;
cursor: pointer;
display: block;
text-align: center;
width: 170px;
height: 40px;
line-height: 40px;
transition: 0.2s;
}
.primary{
border: 2px solid $transparant;
background-color: $primary-color;
color: $tertiary-color;
}
.primary:hover{
border: 2px solid $primary-color;
#include alphaBackground();
}
.primary-inverted{
border: 2px solid $primary-color;
color: $primary-color;
#include alphaBackground();
}
.primary-inverted:hover{
border: 2px solid $transparant;
background-color: $primary-color;
color: $tertiary-color;
}
.secondary{
border: 2px solid $transparant;
background-color: $secondary-color;
color: $tertiary-color;
}
.secondary:hover{
border: 2px solid $secondary-color;
color: $tertiary-color;
#include alphaBackground();
}
.secondary-inverted{
border: 2px solid $secondary-color;
color: $tertiary-color;
#include alphaBackground();
}
.secondary-inverted:hover{
border: 2px solid $transparant;
background-color: $secondary-color;
color: $tertiary-color;
}
.tertiary{
border: 2px solid $transparant;
background-color: $tertiary-color;
color: $primary-color;
}
.tertiary:hover{
border: 2px solid $tertiary-color;
color: $tertiary-color;
#include alphaBackground();
}
.tertiary-inverted{
border: 2px solid $tertiary-color;
color: $tertiary-color;
#include alphaBackground();
}
.tertiary-inverted:hover{
border: 2px solid $transparant;
background-color: $tertiary-color;
color: $primary-color;
}
</style>
I got the following answer from the Nuxt discord
computed: {
something() {
return !process.client ? 'runs on server' : ''
}
}

Button stays focused (hover) after clicked

I'm using bootstrap and vue 2.0.
It works normally when I don't click the button. It focus on #mouseenter and unfocus on #mouseleave like this.
But when I clicked button, it stay focused like this until I make another click anywhere, even in another window.
How can I fix this? Here is HTML and CSS code.
Button html:
<button class="btn btn-primary" v-on:click="search()"
type="button">{{$lang.ticketsSearch}}</button>
Button css:
.btn {
display: inline-block;
padding: 6px 12px;
margin-bottom: 0;
font-size: 14px;
font-weight: normal;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
.btn:focus,
.btn:active:focus,
.btn.active:focus,
.btn.focus,
.btn:active.focus,
.btn.active.focus {
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.btn:hover,
.btn:focus,
.btn.focus {
color: #333;
text-decoration: none;
}
.btn:active,
.btn.active {
background-image: none;
outline: 0;
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn.disabled,
.btn[disabled],
fieldset[disabled] .btn {
cursor: not-allowed;
filter: alpha(opacity=65);
-webkit-box-shadow: none;
box-shadow: none;
opacity: .65;
}
a.btn.disabled,
fieldset[disabled] a.btn {
pointer-events: none;
}
.btn-primary {
color: #fff;
background-color: #337ab7;
border-color: #2e6da4;
}
.btn-primary:focus,
.btn-primary.focus {
color: #fff;
background-color: #286090;
border-color: #122b40;
}
.btn-primary:hover {
color: #fff;
background-color: #286090;
border-color: #204d74;
}
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
color: #fff;
background-color: #286090;
border-color: #204d74;
}
.btn-primary:active:hover,
.btn-primary.active:hover,
.open > .dropdown-toggle.btn-primary:hover,
.btn-primary:active:focus,
.btn-primary.active:focus,
.open > .dropdown-toggle.btn-primary:focus,
.btn-primary:active.focus,
.btn-primary.active.focus,
.open > .dropdown-toggle.btn-primary.focus {
color: #fff;
background-color: #204d74;
border-color: #122b40;
}
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
background-image: none;
}
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus {
background-color: #337ab7;
border-color: #2e6da4;
}
.btn-primary .badge {
color: #337ab7;
background-color: #fff;
}
When that button is clicked, it takes on the :focus state. If you don't want it to behave like that, you'd have to overwrite the focus state, but that's probably not a good idea. You could look into programmatically putting the focus on something else.
In this particular case to remove the "green" when you click and move away, you should only need to do:
.btn-primary:focus,
.btn-primary.focus {
color: #fff;
background-color: #000; /*this is where the colour was green*/
border-color: #122b40;
}

SCSS rule Inheritance compared to LESS

I'm used to using LESS but im currently working with SCSS.
In Less I could do the following:
.sidebar_styles { background: red; border: 1px solid blue; }
aside[role="complementary"] { .sidebar_styles; }
Would the SCSS equivalent be:
.sidebar_styles { background: red; border: 1px solid blue; }
aside[role="complementary"] { #extend .sidebar_styles; }
I ask as I am using the Foundation framework and I'm trying to not use presentation classes in the html. I noticed Chrome was running slowly and opened up the inspector. The matched css rules for some elements is huge.
Below is about 5% of what I could copy from one of the elements before Chrome hangs.
.row.collapse .column, body.full_width div[role="main"] form .row.collapse .column, body.two_columns div[role="main"] form .row.collapse .column, body.homepage div[role="main"] .hero_container form .row.collapse .column, .row form .collapse.top_bar .column, .top_bar form .collapse.top_bar .column, header[role="banner"] form .collapse.top_bar .column, footer[role="contentinfo"] form .collapse.top_bar .column, body.full_width div[role="main"] form .collapse.top_bar .column, body.two_columns div[role="main"]
#extend will group the css selectors together in comma separated list. If you add additional rules after the #extend, it will keep those rules as it's own selector.
scss
.sidebar_styles {
background: red;
border: 1px solid blue;
}
aside[role="complementary"] {
#extend .sidebar_styles;
color: black;
}
css output
.sidebar_styles, aside[role="complementary"] {
background: red;
border: 1px solid blue;
}
aside[role="complementary"] {
color: black;
}
If you want to keep the rules separated then you can use a mixin and include it in the rules.
scss
#mixin test {
background: red;
border: 1px solid blue;
}
.sidebar_styles {
#include test;
}
aside[role="complementary"] {
#include test;
}
css output
.sidebar_styles {
background: red;
border: 1px solid blue;
}
aside[role="complementary"] {
background: red;
border: 1px solid blue;
}

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)
}

How to apply concatenated classes within another class using Less?

Let's say I have the following Less setup:
.box {
border: 1px solid #333;
&.error {
background-color: Red;
}
}
If I wanted to declare another class which applied the full style of .box.error, as .error-box for example, what's the correct syntax?
If I use:
.error-box {
.box.error;
}
All I get is the red background, with no border. I've tried many different combinations, but I always get a syntax error.
I plugged in your less as so:
.box {
border: 1px solid #333;
&.error {
background-color:red;
}
}
.error-box {
.box;
}
and the CSS output was this:
.box {
border: 1px solid #333;
}
.box.error {
background-color: red;
}
.error-box {
border: 1px solid #333;
}
.error-box.error {
background-color: red;
}
were you wanting the .error-box class to alone receive both styles? The only way I can think of doing that would be:
.error-bg {
background:red;
}
.box {
border:1px solid #333;
&.error {
.error-bg;
}
}
.error-box {
.box;
.error-bg;
}