SASS mixin for swapping images / floats on site language (change) - css

Currently using SASS on a website build. It is my first project using it, tried a little LESS before and liked it. I made a few basic mixins and variables with LESS, super useful stuff!
I am trying to get my head around SASS mixins, and syntax, specifically for swapping images when the page changes to a different language, be that with body ID changing or <html lang="en">. And, swapping floats around if, for example, a website changed to Chinese. So a mixin where float left is float left unless language is AR and then it becomes float right.
With LESS I think it would be something like:
.headerBg() when (#lang = en) {background-image:url(../img/hello.png);}
.headerBg() when (#lang = it) {background-image:url(../img/ciao.png);}
.header {.headerBg(); width: 200px; height:100px}
.floatleft() when (#lang = en) { float: left;}
.floatleft() when (#lang = ar) { float: right;}
.logo {.floatleft();}
It's the syntax I am having problems with.

I'd probably use the #content feature and do something like this:
#mixin headerBg {
.header {
#content
}
}
#mixin floatDir {
.logo {
#content
}
}
:lang(en) {
#include headerBg {
background-image:url(../img/hello.png);
}
#include floatDir {
float: left;
}
}
:lang(ar) {
#include headerBg {
background-image:url(../img/ciao.png);
}
#include floatDir {
float: right;
}
}
Which compiles to:
:lang(en) .header {
background-image: url(../img/hello.png); }
:lang(en) .logo {
float: left; }
:lang(ar) .header {
background-image: url(../img/ciao.png); }
:lang(ar) .logo {
float: right; }
If the background image names where based on the language, then it might make sense to use #each and do something like this:
#each $lang in en, ar {
:lang(#{$lang}) {
#if $lang == en {
.logo {
float: left;
}
} #else if $lang == ar {
.logo {
float: right;
}
}
.header {
background-image:url(../img/#{$lang}.png);
}
}
}
Which compiles to:
:lang(en) .logo {
float: left; }
:lang(en) .header {
background-image: url(../img/en.png); }
:lang(ar) .logo {
float: right; }
:lang(ar) .header {
background-image: url(../img/ar.png); }

Related

SASS mixin : how to add class before?

I'm struggling with creating a mixin with sass and I can't seem to find a solution. If anyone has any ideas...
I have something like this:
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
and I'd like to have something like this when compiled:
html .tata .toto .tutu {background:red}
I've tried this, but the result is not what I expected:
#mixin mixin_test {
html{
#content;
}
}
Does anyone have a solution?
You need to edit your mixin. Missing & after the selector:
#mixin mixin_test {
html & {
#content;
}
}
.tata {
font-size: 12px;
.toto{
display: block;
.tutu {
text-align: left;
#include mixin_test{
background: red;
}
}
}
}
On this page you can read more about parent selector: Parent Selector

SASS Ampersand – Chaining CSS class with the parent selector '&' like in LESS

LESS (CSS)
see in action
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
// rtl direction
.rtl& { //////////////////////////////////
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
Consider the line I have highlighted with ///.....
I want the same result in SASS (.scss). Is it possible?
Expected result should be:
.rtl.app #page .inner .left.padding-left-10px {}
and not
.rtl .app #page .inner .left.padding-left-10px {}
Thanks.
It looks like you are attempting to use the LESS feature where you can change the order of the selectors by using the parent selector. It isn't working as expected because that specific LESS feature isn't implemented the same way in SASS.
If you want the equivalent output code in SASS, then you can use the #at-root directive in order to scope the selector to the root. Then you would also need to use variable interpolation (i.e., .rtl#{&}) for the parent selector:
.app {
#page {
.inner {
.left {
&.padding-left-10px {
padding-left: 10px;
#at-root {
.rtl#{&} {
padding-left: 0;
padding-right: 10px;
}
}
}
}
}
}
}
Which would compile to:
.app #page .inner .left.padding-left-10px {
padding-left: 10px;
}
.rtl.app #page .inner .left.padding-left-10px {
padding-left: 0;
padding-right: 10px;
}
Josh gave you an answer which will work, i guess. But I still wanna give you some advice and that is look into BEM, or someway. Nesting like this is really unnecessary.
Your code could be better for readability.
For example:
.padding {
padding: 10px;
}
.padding--left { // This is a modifier for padding
padding: 0 0 0 10px;
}
.padding--right { // This is a modifier for padding
padding: 0 10px 0 0;
}
<div class="padding padding--left">Using it in a div</div>
You don't have to follow all the rules which are defined in BEM, but some are really nice to use.

SASS rule reuse

I have a set of icons with different colors and each color is used with different status declared with CSS classes. For example, <span class="icon icon--app"><span> gives a gray app icon while <span class="icon icon--app icon__light icon__selected"><span> gives a white app icon.
The following code is written in SCSS.
span.icon {
display: inline-block;
width: 32px;
height: 32px;
&.icon--app {
background: url(../images/app_gray.png);
&.icon__selected {
background: url(../images/app.png);
}
&.icon__light {
background: url(../images/app_gray.png);
&.icon__selected {
background: url(../images/app_white.png);
}
}
}
&.icon--device {
background: url(../images/device_gray.png);
&.icon__selected {
background: url(../images/device.png);
}
&.icon__light {
background: url(../images/device_gray.png);
&.icon__selected {
background: url(../images/device_white.png);
}
}
}
}
The problem is, there's a long list of CSS rules as above, which shares much similarity for app and device and other icons. I wonder if I can simplify these CSS rules using SASS?
I think you can use mixin in Sass:
e.g.
#mixin icon($type) {
.icon-#{$type} {
background: url(../images/#{$type}_gray.png);
}
}
#include icon(app);
#include icon(device);
I created a mixin for you:
#mixin icon($type) {
&.icon--#{$type} {
background: url(../images/#{$type}_gray.png);
&.icon__selected {
background: url(../images/#{$type});
}
&.icon__light {
background: url(../images/#{$type});
&.icon__selected {
background: url(../images/#{$type}_white.png)
}
}
}
}
span.icon {
display: inline-block;
width: 32px;
height: 32px;
#include icon(app);
#include icon(device);
}

Is there a replace function/script in Sass to swap CSS properties?

I'm working on a right-to-left solution in Sass.
So for example, if the original style is:
#foo {
float: left;
padding-left: 10px;
}
...the function/script will run through looking for floats and padding-lefts and replace the styles with:
#foo {
float: right;
padding-right: 10px;
}
I already have a solution using mixins, like this:
#mixin float($origin: left) {
#if $origin == left {
#if $rtl { float: right; }
#else { float: left; }
} #else {
#if $rtl { float: left; }
#else { float: right; }
}
}
#mixin padding-left($value) {
padding-right: $value;
}
#foo {
#include float(left);
#include padding-left(10px);
}
...but is there a way to do this without having to replace all reversible properties with includes?
You could use a variable so you can set the direction in one place, but Sass doesn't have the ability to alter existing CSS based on rules you set.
$direc: left;
div {
float: $direc;
padding-#{$direc}: 10px;
}

Less nested namespaces?

So I have this bit of Less
#footer {
ul {
// stuff
}
li {
// stuff
}
}
everything is contained nicely within #footer, but say I want to prefix #footer. How would I prefix footer with a class like .ie6 or .ie7, but within the less "closure" of #footer?
for example, I want to do this (observe pseudo syntax >.ie6, >.ie7) :
#footer {
<.ie6, <.ie7 {
// ie6/7 stuff
}
ul {
// stuff
}
li {
// stuff
}
}
and have it generate this:
.ie6 #footer,
.ie7 #footer {}
#footer {}
#footer ul {}
#footer li {}
Any idea how to accomplish this with Less?
I think this might be of interest to you: https://github.com/cloudhead/less.js/pull/268#issuecomment-1207479
What you want to do isn't possible yet in the master less.js. But a guy, James Foster, forked it and added this feature.
Example:
#box {
#other-box {
margin: 10px 0 0;
.ie7 & {
margin: 5px 0 0;
}
}
}
I don't believe it's possible to place the class before the #footer, unless you wrapped everything in .ie6/7 instead of #footer
LESS website shows the following example:
#header { color: black;
.navigation { font-size: 12px }
.logo { width: 300px;
&:hover { text-decoration: none }
}
}
Which I think is the only way to achieve similar to what you want, so:
#footer {
.ie6{
// ie6 stuff
}
.ie7{
//ie7 stuff
}
ul {
// stuff
}
li {
// stuff
}
}
Would generate with the classes after the ID, I can't seem to find a way to achieve what you want without nesting everything inside the .ie6/7

Resources