Transform properties/variables clashing in sass and overwriting eachother - css

I have the code at the bottom of the page in my sass. In my html I am targeting it as follows
class=" transform rotate-5 zoom-2 ......"
the problem is that the transform properties are clashing and aren't applying scale and rotate to the same div tag, I'm either getting one or the other.
I thought I could change this by using the #extend property and something like,
&.rotate-#{$i}
{#extend &.skew-#{$i}, &.zoom-#{$i}, &.zoom--#{$i};
transform: rotate($rotate#{deg});
}
but so far I've had no luck, if anyone can help it'd be greatly appreciated.
.transform {
overflow:hidden;
#for $i from 1 through 360 {
$rotate: $i;
$skew: $i;
$zoom: $i;
&.rotate-#{$i} {
transform: rotate($rotate#{deg});
}
&.skew-#{$i} {
transform: skew($skew#{deg});
}
&.zoom-#{$i} {
transform: scale($zoom,0);
}
&.zoom--#{$i} {
transform: scale(-$zoom,0);
}
}
}

I'm a big fan of utility classes that I thought easier to debug and to build with. But here it doesn't seem to be a good idea:
1) You are creating 360 * 4 selectors, yet you will probably only use 10-20 of them. It is a bit overkill.
2) As you describe it, the transform property values do not "combine" well, at least for what you are looking for. Even atomic CSS, which pushes very far the utility classes approach, specificies that combining different values of filter (for instance) needs creating a custom value / class.
I understand that it is not really a good answer, at least not the answer you were looking for, but if you want to keep your CSS only approach, I suggest you adopt a more "object-oriented" method for this issue and set your transform property directly in the css of your object, for instance with this mixin:
#mixin transform($rotate, $skew, $zoom) {
transform: rotate($rotate#{deg}) skew($skew#{deg}) scale($zoom,0) scale(-$zoom,0);
}

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.

Add logic to CSS

I would like to use logic in my CSS. Styles need to be applied only if a product ID is higher than a specific number, e.g:
if (data-product-id > 25) {
padding: 50px;
}
Is this possible with CSS?
No, it isn't. Attribute selectors are based on simple string matching. There is no provision for less than / greater than numerical comparisons.
The closest you could get with CSS itself would be something like:
[data-product-id="25"],
[data-product-id="26"],
[data-product-id="27"],
/* etc */
This sort of thing is better handled with JS or server-side code which adds classes to elements.
You can apply some limited logic of the like you were asking about in CSS, but I advise against it. Nevertheless, the answer below is an answer, it's better to implement your logic in Javascript.
Assuming that you have a class called data-product for all your data products, you can create this rule:
.data-product {
padding: 50px;
}
.data-product[data-product-id="1"],
.data-product[data-product-id="2"],
.data-product[data-product-id="3"],
.data-product[data-product-id="4"],
.data-product[data-product-id="5"],
.data-product[data-product-id="6"],
.data-product[data-product-id="7"],
.data-product[data-product-id="8"],
.data-product[data-product-id="9"],
.data-product[data-product-id="10"],
.data-product[data-product-id="11"],
.data-product[data-product-id="12"],
.data-product[data-product-id="13"],
.data-product[data-product-id="14"],
.data-product[data-product-id="15"],
.data-product[data-product-id="16"],
.data-product[data-product-id="17"],
.data-product[data-product-id="18"],
.data-product[data-product-id="19"],
.data-product[data-product-id="20"],
.data-product[data-product-id="21"],
.data-product[data-product-id="22"],
.data-product[data-product-id="23"],
.data-product[data-product-id="24"],
.data-product[data-product-id="25"] {
padding: 25px;
}

How to create dynamic classes in less

I've been looking for the answers, but either it's not what I am really looking for, or I am not searching up properly. I want to dynamically generate the class name. Since, I use margin-top quite frequently, I have multiple classes defined with a set of rules, and I want to achieve with LESS.
I don't think is possible to create dynamic generated classes, as far as I did my research. Here is my code:
.margin-top-(#value)px {
margin-top: #value;
}
Desired Output
.margin-top-20px {
margin-top: 20px;
}
.margin-top-100px {
margin-top: 100px;
}
Just an example of what I am expecting.
Try to use mixin to achieve this.
//define the mixin
.margin-top(#value) {
.margin-top-#{value}{
margin-top:#value;
}
}
//use the mixin like this
.margin-top(20px);
U can try it here: http://winless.org/online-less-compiler

Dynamic prefixed keyframe generation with LESS CSS

I'm currently trying to find a way to generate prefixed keyframes with Less.
This is the loop that generates the prefixed versions, and it works. The only problem is when I add a from{} to{} declaration inside the dostuff animation it breaks it and causes Less to treat them like a mixin.
Is there any way to get this to work?
#key-prefix: ~"#-webkit-",~"#-o-",~"#-moz-",~"#";
.generate-keyframes(#i) when (#i > 0) {
.load1-keyframes((#i - 1));
#prefix: extract(#key-prefix,#i);
#{prefix}keyframes dostuff {
}
}
.generate-keyframes(4);
In short, no, an interpolation of the at-rule directive identifiers is not supported (and is not planned to be).
Well, you can get what you want with something like:
.vendorize-keyframes(dostuff, {
0% {color: tomato}
to {color: potato}
});
.vendorize-keyframes(#name, #frames) {
#-webkit-keyframes #name {#frames();}
#-moz-keyframes #name {#frames();}
#-o-keyframes #name {#frames();}
#keyframes #name {#frames();}
}
But in general the recommendation is to consider to use a tool like autoprefixer and stop polluting your Less and/or CSS code with these hardcoded vendor prefixes.

Applying Same Style to Multiple IDs with Same Words

I'd like to know if there's a way to apply the same styles to IDs that start with the same workds.
For example, I have #youtube_gallery_item_1, #youtube_gallery_item_2,....and the number keeps increasing, so I can't add a new ID every time I add a new item. FYI, I'm working with Wordpress and YouTube SiimpleGallery plugin.
I'd appreciate your help!
The "starts with" selector in CSS3.
div[id^=youtube_gallery_item] {
}
Note that this doesn't work in IE8 and below.
What would be a better idea would be to assign all of your #youtube_gallery_items a class, and then assign styles to that class. I'm sure that the plugin that you're using is doing this. Look at the source code, and if you see that they all have the same class, use:
.name-of-the-class {
}
You can use an attribute selector:
[id^="youtube_gallery_item"] {
color: skyblue;
}
http://jsfiddle.net/p9Ya8/
I would suggest adding a class
.youtube_gallery_item {
background: ;
width: ;
...
}
Its compatible with all browsers and is the easiest way to get around.
<div id="youtube_gallery_item_1" class="youtube_gallery_item"></div>
<div id="youtube_gallery_item_2" class="youtube_gallery_item"></div>
<div id="youtube_gallery_item_3" class="youtube_gallery_item"></div>

Resources