Conditional CSS rules with less, based on variable - css

The variable can take percentage or px values, like:
#some-var: 50px; or #some-var: 46%;
How can I define a certain set of CSS rules if the value is in pixels, and a different set of rules if the values is in percentages?
Is there something like
if(isValueInPixels(#some-var)){
// css rules here
}else{
// other rules here
}
?

I think you can use something that they call Guarded Mixins.
Try something like this...
.mixin (#a) when (ispixel(#a)) {
/* ... your pixel specific logic ... */
}
.mixin (#a) when (ispercentage(#a)) {
/* ... your percentage specific logic ... */
}
.coolStuff {
.mixin(50px);
.mixin(50%);
}
See the Guarded Mixins at http://lesscss.org/

As Adam Spicer noted the Guarded Mixins are your best solution.
However, LESS now offers a solution to group multiple guards, which will allow this to be accomplished with a single mixin.
http://lesscss.org/features/#css-guards-feature
For Example:
.mixin(#a){
& when (ispixel(#a)){
//logic
}
& when (ispercentage(#a)){
//logic
}
}
Usage:
selector{
.mixin(50px);
.mixin(46%);
}

Related

Using #mixin to achieve RTL support on Angular

I am using a mixin to convert my Angular app from LTR to RTL accordingly.
#mixin rtl($property, $ltr-value, $rtl-value) {
[dir='ltr'] & {
#{$property}: $ltr-value;
}
[dir='rtl'] & {
#{$property}: $rtl-value;
}
}
#mixin rtl-prop($ltr-property, $rtl-property, $value) {
[dir='ltr'] & {
#{$ltr-property}: $value;
}
[dir='rtl'] & {
#{$rtl-property}: $value;
}
}
When I use #include, for some reason it doesn't work. (html tag is defined properly)
#include rtl(border-radius, 0 10px 80px 0, 0 80px 10px 0);
<html lang="he" dir="rtl">
Any ideas why?
For those who will encounter this issue at the future, the problem was component's encapsulation - it was set to Emulated which probably interfered with the classes names.
Set it to None instead.
There are a couple of things you can do to solve this, but that are not optimal:
First and for all you are checking if the component itself has dir set, that is why it isn't working. Because the direction is set on the tag.
You can try to use :host-context, because than it will take a look at the html attribute and not your component. Like this:
#mixin rtl($property, $ltr-value, $rtl-value) {
:host-context([dir='ltr']) & {
#{$property}: $ltr-value;
}
:host-context([dir='rtl']) & {
#{$property}: $rtl-value;
}
}
But always check on canIUse to see if it has enough coverage. For this moment it is around 75% so I would say it is too low, certainly if you have a lot of mobile iOS users.
Another alternative to :host-context() is :dir(), but this has on the moment of writing only 3% coverage, so I would not bother using that either.
The currently approved answer (the one that suggests to set encapsulation to None) is not recommended since it will make all the mark-up for that component global and could cause some unexpected issues. Certainly because direction is maybe something you'd want to use in almost all of your components.
I think the best solution right now is to use logical properties from css. You use 'start' instead of 'left' for example. You can google it and find a lot of info to use it. (for example on developer mozilla site).
For your example you would have to use:
.yourClass {
border-start-start-radius: 0;
border-start-end-radius: 10px;
border-end-start-radius: 80px;
border-end-end-radius: 0;
}
And this would make it look the way you want it on any text-direction without the use of any mixins.

CSS - How to select multiple attribute values?

If I have multiple div tags with an attribute containing different numbered values, and I would like to select only number 1 through 10, what is the most efficient way to do this in css?
Is there anything like e.g. .div[line-number=1-10] ?
This is not possible in the standard CSS. It is convenient to use a CSS preprocessor like SASS or LESS which allow you creating loops among many other features. An example with SASS:
$selector: '.div';
#for $i from 1 to 10 {
$selector: $selector + '[line-number=' + $i + ']';
}
#{$selector} {
// style
}
In pure CSS you are doomed to use this solution instead:
.div[line-number=1], .div[line-number=2], .div[line-number=3], .div[line-number=4], .div[line-number=5], .div[line-number=6], .div[line-number=7], .div[line-number=8], .div[line-number=9], .div[line-number=10] {
}
if you have the ability to modify the line-number attribute starting with 0 (01,02,03,04...10) you can do this:
div[line-number^="0"], div[line-number="10"] {
// css properties
}
if not see the answer from #jackBauer
You cannot specify line-number in range (1-10).
This is not available in attribute selector - https://www.w3.org/TR/css3-selectors/#attribute-selectors.
But alternatively you can apply css on each attribute value with something like below
div[line-number="1"] {
color: red;
}
div[line-number="10"] {
color: green;
}
<p>Use attribute selectors</p>
<div line-number="1">one</div>
<div line-number="2">two</div>
<div line-number="10">ten</div>
Hope this will help in some way(y).

Applying css rules if under a specific class or id

Is it possible to define several rules under a class without having to write the class before each time. For example:
.container-class .id-1 // {rules}
.container-class .id-2 // {rules}
.container-class .id-3 // {rules}
Is it possible to avoid having to write .container-class every single time?
Only if you use a preprocessor language like LESS or SASS
With LESS you can write this:
.container-class {
.id-1 { }
.id-2 { }
.id-3 { }
}
To achieve what you want.
You can read more here: http://lesscss.org/
If the rules for all your elements are the same, what you can do at the moment is:
.container-class .id-1,
.container-class .id-2,
.container-class .id-3{
/*...*/
}
There is an experimental property :any() which could be used.
Selectors Level 4 specifies the pseudo-class :matches().
.container-class :-moz-any(.id-1 .id-2 .id-3){
/*...*/
}
/* standards compliant*/
.container-class :matches(.id-1 .id-2 .id-3){
/*...*/
}
Problem with this atm is, that you have to use vendor prefixes which makes this a bit useless, because you have to put each vendor prefix into a separate rule block.
If you have different rules for those elements, you can't group them. You can shorten it with LESS or SASS, but in the end, it still compiles to the verbose form.

CSS Pre-processors: Getting the current value of a css property and changing it

Let's say I have following declaration
.foo {
.grid(1);
}
.grid(#num) {
width: ... // Some calculated percentage
}
Now later I realize that I need .foo to be 5% wider is it somehow possible todo .foo { width: +5%;} or something similar?
For LESS
In LESS you cannot get at that info so directly. You would need to modify the .grid mixin to something like:
.grid(#num, #adjust: 0) {
width: (your regular calaculation) + #adjust; // Some calculated percentage
}
By giving it a default of 0, then you can still just pass .grid(1) when you want to, but then if .foo needed an adjustment, you do:
.foo {
.grid(1, 5%);
}
For SASS
I'm not 100% certain, but I believe SASS cannot access the property directly either, and would essentially need to do some type of similar solution where the mixin calculation itself is changed.

Declare a global CSS property ? Is this possible?

I have a very wierd question, I dont know wether if its possible in css or not
Suppose I have say 3 different css classes as shown below, as you can see I have a common property of all these classes, I want to declare this color somewhere else and pass a reference to it here, so if next time I want to change the color I can simply change at one place rather than changing in all the 5 classes.
I know that you can use body{}, or a wrapper for this but that would affect the colors of the entire site right ? Is there a way to do this ?
Is this even possible ?
.abc {
color:red;
}
.abc2 {
color:red;
}
.abc3 {
color:red;
}
.abc4 {
color:red;
}
.abc5 {
color:red;
}
The bad news: you can't do it in CSS.
The good news: you can write in a meta-CSS language like LESS, which then processes a LESS file to pure CSS. This is called a "mixin".
In LESS:
#errorColor: red;
.error-color {
color: #errorColor;
}
#error-1 {
.error-color;
}
.all-errors {
.error-color;
}
More info: http://lesscss.org/#-mixins
if you want to declare all of them at a time, you can use:
.abc, .abc2, .abc3, .abc4, .abc5 {
color:red;
}
Or you can declare an additional class & add to all the .abc, .abc2.... & make its color:red;.
This can not be done with CSS, but that is still a very popular thing to do by using a CSS preprocessor such as LESS, SASS, SCSS, or Stylus.
A preprocessor will let you define a variable (say $red = #F00). It will replace the variable in your CSS document with the variable value for you, allowing you to write very DRY and module CSS.
This functionality is referred to as "CSS variables", which is part of the future spec, but not yet implemented on any browsers.
For now, the best way to do this in pure CSS is to declare an additional class for the desired "global", and then add that class to all relevant items.
.abc_global { color: red; }
.abc1 { /* additional styling */ }
.abc2 { /* additional styling */ }
<div class="abc1 abc_global"></div>
<div class="abc2 abc_global"></div>
With LESS
You are able to define that red color once:
.myRedColor {
color:red;
}
Now you can call that red on any CSS styles. Even NESTED styles! It's a wicked tool!
.abc1 {
.myRedColor;
}
.abc2 {
.myRedColor;
}
.abc3 {
.myRedColor;
}
.abc4 {
.myRedColor;
}
NESTED EXAMPLE:
.abc {
.itsEasyAsOneTwoThree{
.myRedColor;
}
}
Now all of our "itsEasyAsOneTwoThree" classes that are properly nested inside of an "abc" class will be assigned the red style. No more remembering those long #867530 color codes :) How cool is that?!
You can also use PostCSS with the plugin postcss-preset-env and support custom properties/variables, then use the :root selector to add global css variables.
:root {
--color-gray: #333333;
--color-white: #ffffff;
--color-black: #000000;
}

Resources